# Storybook source shape
`.storybook/` found — the component list and story args come from `storybook-static/index.json`. Run `npm run build-storybook` (or pass the converter `--storybook-config
` / `--storybook-static ` if you already have one built).
## 2. Explore, then write config (continued)
3. The converter needs the built `dist/` entry + its `.d.ts` tree. Check whether the entry (from `package.json` `module`/`main`/`exports['.']`) already exists — install may have built it via `prepare`. If missing:
- Run ` run build`. No `build` script → try `prepare`/`prepack`. In a monorepo, the build may be at the repo root (`turbo build --filter=`, `pnpm -F build`, `nx build `). **Some build scripts fork a watcher and exit 0 early — after the command returns, `ls` the expected output (dist/, build/esm/, or whatever `package.json` `module`/`main` points at) and confirm it's populated before continuing.** If it's empty, check for a `--watch` flag in the script and use the one-shot variant, or poll the output dir.
- Still missing → `AskUserQuestion`("What command builds this package?", options = any `scripts.*` containing `tsc|tsup|rollup|vite build|esbuild|swc`, plus freeform). Record the answer as `buildCmd` in the config.
- User says there's no build → the converter will synthesize an entry from `src/` (last resort — `.d.ts` contracts will be weaker; recommend adding a build).
4. **Check what's already in the project.** `DesignSync(list_files)` on the target. If it returns files, read `_ds_bundle.js` via `DesignSync(get_file)` and note the component names from its first-line `/* @ds-bundle: {…} */` header — but **always still rebuild** (step 7); the existing bundle is stale the moment source changes. The header's `sourceHashes` diff decides what to *upload* incrementally via `DesignSync`, not what to build.
5. **Confirm the plan with the user before building.** `AskUserQuestion` with: the component list you found (or a count + a few names if it's long), which files the tokens/CSS are coming from, and which build command you'll run. The build can take minutes and burn tokens — aligning now avoids re-running because it was pointed at the wrong package or missed half the components.
- If the project already has N components (step 4), include that in the question and offer the scope: **(a)** full rebuild + re-upload everything, **(b)** update only the changed components (diff from `sourceHashes`), **(c)** tokens + CSS only (no component rebuild). Default to (b) when the diff is small.
6. **Write `design-sync.config.json` and commit it** — re-sync reuses it so output is reproducible. Only `pkg` and `globalName` are required. **If the file already exists, read it first and preserve `previewArgs`, `dtsPropsFor`, `libOverrides`, and `overrides` — only add to those fields, never replace them.** They accumulate fixes from prior verify-loop iterations. **Also Read `.design-sync/NOTES.md` (or whatever `cfg.notes` points at) before anything else** — it holds repo-specific gotchas a prior sync recorded.
| Field | Value |
|---|---|
| `pkg` / `globalName` | package name and the `window.*` global to assign — required |
| `shape` | `'storybook'` or `'package'` — pins the source shape (overrides auto-detection). Written on first run. |
| `storybookConfigDir` | path to the `.storybook/` dir (relative to this config file) when it's outside the package — e.g. a central `apps/storybook/.storybook` in a monorepo |
| `storybookStatic` | path to a pre-built `storybook-static/` dir, if you've already run `build-storybook` |
| `titleMap` | `{storyTitle: ComponentName}` — maps Storybook story titles to component export names when they don't match (see `[TITLE_UNMAPPED]`) |
| `buildCmd` | the discovered build command; re-sync re-runs it |
| `tsconfig` | path to `tsconfig.json` — esbuild reads `compilerOptions.paths` so `@/…` path aliases resolve in synth-entry mode |
| `extraEntries` | package names to merge into `window.` alongside the DS entry (e.g. the DS's separate icon package). Sibling icon packages under the same scope are auto-detected (`[ICON_PKG]`). |
| `componentSrcMap` | **sparse** `{Name: path}` — non-null pins/adds a component's src path; `null` excludes a `.d.ts`-exported internal |
| `dtsPropsFor` | `{Name: "prop?: Type; …"}` — hand-written `Props` body when auto-extraction fails (complex generics, cross-package types) |
| `previewArgs` | `{Name: {prop: value, …}}` — props rendered as a `Preview` export in the auto-generated `.design-sync/previews/.tsx`. Use for simple flat props; for composed JSX children edit the `.tsx` directly. |
| `cssEntry` / `tokensPkg` / `tokensGlob` | stylesheet + token files |
| `docsDir` | directory (package-relative; may point outside, e.g. `../../apps/docs`) holding per-component `.md`/`.mdx` docs. Auto-detected as `docs/` or `documentation/` under the package. |
| `docsMap` | sparse `{Name: path \| null}` — explicit doc path per component (overrides discovery); `null` excludes |
| `guidelinesGlob` | string or string[] (package-relative) of design-guideline `.md` files to copy into `guidelines/`. Default `['docs/guides/**/*.md', 'docs/*.md', 'guides/**/*.md']`. |
| `extraFonts` | paths (package-relative; may point outside the package, e.g. a sibling typography package) to `@font-face` `.css` files or bare `.woff2`/`.ttf`/`.otf` for brand families the DS expects its host app to provide. CSS entries are parsed and their local font files copied to `fonts/`; bare font files are copied as-is. Use when validate prints `[FONT_MISSING]`. |
| `runtimeFontPrefixes` | string[] — family-name prefixes for fonts the host app serves at runtime from a font service (via a `