Pixel-port
Port one executable design (HTML/CSS/JS that can be served statically — Claude Design by default) into a production site. Same process every run. Framework and brand are project-local.
Leading words: temple (anyone walking the tree knows where a thing lives). Foundation first (tokens + primitives before pages). Fail loud (never silently diff the wrong variant or viewport).
Inputs
A session needs:
- A Claude Design share link or an existing
design-ref/<slug>/tree. - A page name (slug = kebab-case).
- A framework, chosen once.
If .pixelport/config.json exists, read it and never re-ask. Else detect astro.config.* / next.config.* in the target repo, or ask once, then write config with npx pixel-port init. Stop if framework is still unset.
Then read adapters/<framework>.md (astro | next-static | html).
Optional variants (regions, locales) live in config. Default variant is default. Do not invent Transket-style geo unless the project config lists it.
Two-pass
Foundation pass (once per site, or when the design kit changed): extract _ds/, kit/*.css, ui/*, ui-icons/* into tokens + chrome + primitives. No marketing page. Done when: token files exist, SPEC.md reuse checklist has real paths, layout/smoke page consumes those tokens, visual-diff --self-test of the design-ref pipeline is green.
Page pass (every page): steps below. Do not re-extract tokens unless the kit changed.
If config is missing, run foundation before any page. If config exists and tokens already sit at src/styles/tokens/, skip to page pass.
Temple (every port)
Read structure.md before writing files. Hard rules:
- One file, one job. A page is a thin route plus
src/sections/<group>/<slug>/*.— never a giant route file. - Reuse → extend → compose → promote → create. Check
SPEC.mdbefore a new primitive. - ~300 lines is a smell. ~5 helpers on one job earn a
lib/. - Refactors move bytes (slice by line range, re-hash). Raise tangles; do not turn a page port into an unrequested refactor.
Tokens: read tokens.md. Components consume CSS custom properties. Sections do not invent hex or spacing. Do not rewrite the kit through Tailwind (or any other system) unless the design source already is that system.
Page-pass steps
Copy and tick. Each step has a completion criterion. Do not start the next step until the current one is done.
- [ ] 1 config/adapter
- [ ] 2 foundation (if missing)
- [ ] 3 resolve design
- [ ] 4 implementation-details doc (no code)
- [ ] 5 plan gate
- [ ] 6 implement
- [ ] 7 visual-diff
- [ ] 8 tracker
- [ ] 9 human review (still-frame is not done)
1. Config / adapter
Write or confirm .pixelport/config.json via npx pixel-port init (template: templates/config.json). Read the matching adapter.
Done: config has framework, targetUrl, viewports; adapter file has been read this session.
2. Foundation if missing
If src/styles/tokens/ is empty or SPEC.md has no filled reuse checklist: extract kit → primitive then semantic tokens (component tokens only at 3+ stable uses). Port chrome + ui + icons. Fill SPEC from templates/SPEC.md.
Done: tokens on disk, SPEC checklist cites real paths, smoke/layout renders with tokens, --self-test once for the pipeline.
3. Resolve design
Parse projectId + file from the share link. If DesignSync MCP exists: get_project, list_files, get_file (read-only). Else require design-ref/<slug>/ already on disk. Pull the page loader plus depended app/*, ui/*, ui-icons/*, kit/*, _ds/ into design-ref/<slug>/ before step 7.
Done: the page’s .html/content file exists under design-ref/<slug>/ and tracker designPath can be set.
4. Implementation-details doc
Create implementation_details/<slug>.md from templates/implementation-details.md. What: title/description, ordered sections 1:1 with the design’s top-level components, shared vs new. How, per section: target path, design source symbol, which existing primitive to reuse (cite path).
No .astro/.jsx/code in this step.
Done: the doc exists, every top-level design section has a row, no implementation files created this step.
5. Plan gate
Run the doc past advisor, or an Agent with Opus, before writing code.
Done: the stronger-model review has happened; requested plan fixes are in the doc.
6. Implement
Follow the adapter: thin route → one file per section → reuse src/components/{chrome,ui,icons}/. Interactivity: vanilla <script> plus a re-entry guard, unless the adapter explicitly allows a framework island.
Done: every section in the doc has a file at the named path; route composes them; no new primitive that already existed on the SPEC checklist.
7. Verify
Protocol: visual-diff.md. Run the skill script, do not regenerate a one-off.
From the target repo:
npx pixel-port diff <slug> [--self-test] [--variant default] [--budget 5] [--target-url <url>] [--clip]
First time on a page: --self-test (design vs design, expect ~0%). That does not prove the port. Then a real run. Fail loud on variant/marker/zoom mismatch. Default budget 5%. PNGs in diff-output/<slug>/. Full-page is the gate; --clip only localizes a failure.
Done: self-test already green for this slug; real run within budget for every viewport of this variant; or tracker records fail with diff images.
8. Track
One JSON file per page: .pixelport/pages/<slug>.json (schema: templates/page-tracker.schema.json). Create before step 7 (designPath required; targetRoute required unless --self-test). Step 7 writes visualDiff. On done, stamp specHash of SPEC.md.
Done: tracker exists, status matches reality, visualDiff present after a real run.
9. Human review
A passing still-frame is not done. Animations, hover, and anything that moves are invisible to pixelmatch. Put a human on the live page. How they are notified is project-local (email, ticket, chat). Do not add SES or deploy-on-push to this skill.
Done: the tracker notes that review was requested; status is not done until a human has looked or the user explicitly accepts the still-frame risk.
Out of scope
Unattended queues, skip-permissions, usage-limit sleep, commit/push as approval, Cloudflare adapter injection, Figma-as-source, generating a React/shadcn design system.
Additional resources
- File tree and promotion: structure.md
- Token layers and extraction: tokens.md
- Diff protocol: visual-diff.md
- Adapters: adapters/astro.md, adapters/next-static.md, adapters/html.md