feat(ui): emit a standalone stylesheet and sync the DS to Claude Design #153
No reviewers
Labels
No labels
dependencies
major
security-pin
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
trails-cool/trails!153
Loading…
Reference in a new issue
No description provided.
Delete branch "design-sync-ui"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Imports
@trails-cool/uiinto a Claude Design project so the design agent builds with our real components and brand instead of generic ones.Getting there surfaced three problems that are latent independent of the sync — each would bite anyone consuming this package outside the two apps.
1. The package shipped no CSS
Components are styled with Tailwind utilities (
bg-accent,text-text-inv,h-9 px-3.5), butsrc/theme.cssholds only the@themetoken block. The utilities are generated by each app (apps/*/app/styles.cssdoes@import "tailwindcss"+@import "@trails-cool/ui/theme.css"+@source).So any consumer outside those apps gets tokens with nothing using them and renders unstyled. Adds a
buildscript emittingdist/ui.cssfrom a newsrc/build.cssthat mirrors the apps' composition.dist/stays gitignored — the stylesheet is regenerated, never committed.2. Scanning only
packages/ui/srcwas not enoughTailwind emits only classes it sees used, so the stylesheet contained exactly what these 8 components happen to reference. Any composition on top — a preview, or a screen the design agent generates — silently lost its layout classes.
Caught visually: a stat row rendered as a vertical stack instead of a mono row.
flex,gap-4,font-mono,max-w-sm,justify-between,mt-3— absentbuild.cssnow also scans the two apps (the vocabulary the product actually uses) and safelists the full semantic token surface via@source inline(...), so the documented families all exist rather than just the used subset — the elevation ramp (text-eg-lo/mid/hi) andborder-border-mdwere documented but absent until this.3. Fonts did not ship
The build emitted
@font-facerules whoseurl()targets were never copied, and dropped 8 as dead.cfg.extraFontsnow points at the@fontsource-variablestylesheets so the real.woff2binaries are copied — Outfit and Geist Mono render for real instead of falling back to system faces.Also
"@parcel/watcher": falseinallowBuilds—@tailwindcss/clipulls it in and pnpm refuses an unlisted build script. The watcher is only used by--watch, which this build never runs, sofalsepreserves the status quo per the existing convention in that block.What
.design-sync/holdsSync inputs, so re-syncs are reproducible and mostly deterministic:
config.json, the 8 authored preview sources,NOTES.md(repo gotchas + re-sync risks), andconventions.md— the header prepended to the generated README and read by the design agent. Every class, token and component named in conventions.md was verified against the built artifacts, since a header naming things that do not exist is worse than none.Verification
package-validate.mjsexits 0; render check 8/8 cleanpnpm typecheck15/15 ·pnpm lint15/15 ·pnpm test13/13https://claude.ai/design/p/7192cc60-4068-4a5b-a13d-fcc85b2cc6d9One remaining warning is triaged and recorded in NOTES.md:
[FONT_MISSING] "Outfit"fires because--font-sansis"Outfit Variable", "Outfit", …— the variable family ships and is first in the stack; the bare name is only a fallback for machines with the static family installed.For future re-syncs
dist/ui.cssis generated and gitignored, socfg.buildCmdmust run before the converter or a stale stylesheet ships with no error. Recorded under Re-sync risks.🤖 Generated with Claude Code
https://claude.ai/code/session_01EZvKUP2oYUWYPaCvteKrEN