Install any skill in seconds. Free to start, no credit card required.
Get Started Free →asgeirtj/package-source-shape
No Storybook — the component list comes from the package's shipped `.d.ts` exports, and there is **no reference render to verify against**. Preview quality therefore comes from two layers: the converter ships every component fully functional (bundle + `.d.ts` + `.prompt.md`) with an honest **floor c
Passed 14 of 19 test cases with the skill, and 5 of 19 without it.
and 9 more in the full report
11 fixed6 passed either way6 still failing0 broke
Tokens, turns and time describe resource use, not a dollar price.
One of 10 test cases the skill fixed. Same model, same prompt, with and without the skill.
We have verified all authored previews and are ready to finalize our sync. Should we generate `.design-sync/conventions.md` before or after executing our final driver build pass for upload?
| Checked | Without skill | With skill |
|---|---|---|
| Author .design-sync/conventions.md and set readmeHeader in config prior to executing the final driver build pass | Missed | Passed |
The instructions your model reads when the skill loads.
No Storybook - the component list comes from the package's shipped .d.ts exports, and there is no reference render to verify against. Preview quality therefore comes from two layers: the converter ships every component fully functional (bundle + .d.ts + .prompt.md) with an honest floor card, and rich previews are authored - by you, from the repo's own usage examples - for the components the user scopes in (§4). Authored previews are graded on an absolute rubric (§4.3) and reviewed by the user (§4.4); the floor card is never a failure, just an unauthored component.
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:
<pm> run build. No build script -> try prepare/prepack. In a monorepo, build the package and its workspace dependencies from the repo root: turbo build --filter=<pkg> or pnpm -F "<pkg>..." build (the trailing ... is required - bare -F <pkg> skips dependencies and you'll see Cannot find module '@scope/tokens'). 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.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.src/ (last resort - .d.ts contracts will be weaker; recommend adding a build).Check what's already in the project. DesignSync(list_files) on the target (the base skill §1 already picked the upload path: pinned-at-run-start -> atomic; otherwise empty -> incremental, non-empty -> atomic). If it has files, fetch the small verification anchor: DesignSync(get_file, path: "_ds_sync.json") and save it locally (.design-sync/.cache/remote-sync.json) - never download _ds_bundle.js for this. The driver run (the "Re-syncs are one command" block, --remote pointing at the saved anchor) diffs it into .sync-diff.json with TWO partitions answering different questions. Verification (unchanged/changed/added): which components need capture + grading - unchanged were verified at the last upload and skip §4 entirely. Upload (upload.components/upload.deletePaths/upload.bundle/upload.styling): which files the project is missing - sourceHashes-based, so .d.ts/.prompt.md-only edits, regroups (old paths land in deletePaths), and bundle-only changes still ship even when no render changed. Never scope uploads by the verification partition. No sidecar in the project (never synced, or shape change) -> no anchor -> full first-sync scope; if list_files showed the project NON-empty, deletes can't be derived - review its file list once for files this build doesn't produce; those reviewed paths go into the upload plan's deletes at §5.
Confirm the plan AND the preview scope 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.
--force-equivalent) or changed-components-only (the verdict's worklist; default). The precise partition exists only after the driver runs - state it then ("N verified-by-upload, M to verify: [names]") before starting §4 work, and check in with the user if it's surprisingly large.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 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 before anything else - it holds repo-specific gotchas a prior sync recorded.
| Field | Value |
|---|---|
pkg / globalName | package name (required) and the window.* global to assign (auto-derived from pkg when omitted) |
projectId | the claude.ai/design project this repo syncs to - recorded automatically in §1, the moment the target is settled (the atomic upload's post-verify record is a backstop); re-syncs fetch their verification anchor (_ds_sync.json) from it without asking |
shape | 'storybook' or 'package' - pins the source shape (overrides auto-detection). Written on first run. |
buildCmd | the discovered build command - tells Claude what to re-run before the converter on re-sync |
srcDir | source root when not src//lib//components/ |
tsconfig | path to tsconfig.json - esbuild reads compilerOptions.paths so @/... path aliases resolve in synth-entry mode |
extraEntries | package names to merge into window.<globalName> 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 <Name>Props body when auto-extraction fails (complex generics, cross-package types) |
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. Exceptions only, never an enumeration: set docsDir and let discovery bind docs; add entries only for misses, exclusions, regroup stubs, or [DOCS_AMBIGUOUS] pins. A map that names every component duplicates what discovery already does and rots on every component add. |
readmeHeader | string path relative to the config home (the directory containing .design-sync/) of a repo-committed file prepended verbatim to the generated README - the conventions-header slot (see base SKILL.md "Author the conventions header"). |
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 <script> or JS loader, so there's no @font-face to ship). Suppresses [FONT_MISSING] for matching families. Use when the brand font is never meant to ship with the bundle. |
replaces | {<raw-element>: [<ComponentName>, ...]} - extends the adherence-config raw-element map |
libOverrides | {"<name>.mjs": "<one-line reason>"} - declares which .design-sync/overrides/*.mjs files this repo forks and why (see §Troubleshooting). Cross-checked at build time. |
provider | wrapper for previews that need context (see §Troubleshooting). Literal props are for small scalars and stable snippets; for data that already exists in the repo (locale JSON, theme objects), prefer {"$ref": "<export>"} backed by a 2-line module added via extraEntries - an inlined copy duplicates into every card and silently rots when the source file changes, so anything sizable or evolving belongs behind a $ref. Repo-owned modules need an explicit .//../ package-relative path in extraEntries (workspace-bounded); bare names resolve from node_modules. |
Top-level config keys are validated strictly: an unknown or removed key fails the run immediately with the fix named in the message (a config: ... error line, prefixed with a cross mark). That is the migration path when the schema changes - fix the config as the message says; the scripts carry no compat code.
test cases passed, vs 5 / 19 without
More skills from the same source and nearby in the registry, with their headline benchmark lift.