* feat(design-systems): add structured tokens for notion, linear, github, figma, slack, discord, openai, shopify, spotify, uber
Hand-authored batch-2 oracle fixtures for 10 high-profile brands.
Each brand ships tokens.css (A1/A2/B-slot declarations) + components.html
(:root pasted verbatim, no off-token values). pnpm guard reports 12
structured brands (up from 2), all 13 checks pass.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(design-systems): correct elev-ring, focus-ring, and spacing schema drift
- slack: rebind --elev-ring to hairline form (0 0 0 1px var(--border)) so
cross-brand components expecting a 1px outline get a ring, not a soft
drop shadow; the previous value was Slack DESIGN.md "Low" elevation
accidentally placed in the wrong slot
- linear-app: expand --focus-ring to the DESIGN.md §6/§7 multi-layer
stack (accent ring + black blur) so keyboard focus is visible on the
near-black #08090a canvas
- openai: restore --space-{5,6,8,12} to the shared 4·N px spine and
introduce --space-16 (64 px) as a brand extension in BRAND_EXTENSIONS;
syncs components.html :root in all three brands
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(design-systems): add structured tokens for cursor brand
Introduces design-systems/cursor/tokens.css + components.html, the
third structured brand after default and kami. Brings the prose
DESIGN.md into the schema-checked form so agents picking the cursor
design system get the structured token channel (PR-D #1544) instead
of having to re-derive Cursor's warm-cream palette, three-voice
typography (CursorGothic / jjannon / berkeleyMono), oklab borders,
and depth-based focus from prose every turn.
Why now: PR-D made the structured channel default-on, but it only
materially helps the 2 brands shipping tokens.css today. To expand
batch-design-system-test (#1515) coverage beyond default + kami,
we are hand-authoring 5 high-profile brands (cursor first as
template, then apple / stripe / airbnb / vercel) before the bulk
derive script (PR-B). These five also serve as the byte-identical
oracle the future derive script must reproduce.
Brand-specific schema decisions, captured in the tokens.css header:
- Surface: 3-tier cream ladder (#f2f1ed → #ebeae5 → #e6e5e0).
--surface-warm binds to a real intermediate tier, not aliased.
- Foreground: 4-tier ramp via rgba(38,37,30,a) at 1.0 / 0.9 / 0.55
/ 0.4 — Cursor genuinely has the richer ramp.
- Borders: oklab origins shipped as rgba fallbacks per DESIGN.md
§Agent Prompt Guide rule 3.
- --tracking-display: -0.03em (the 72px hero value normalized to
em). Smaller display sizes scale tracking proportionally inline.
- --elev-raised: signature 28/70px diffused atmospheric shadow.
- --focus-ring: depth-only (0 4px 12px), never the cool-blue halo.
- --ease-standard: ease (per DESIGN.md), not the schema cubic-bezier.
- --danger: warm crimson #cf2d56, used for the brand-signature
hover-text-shift on buttons.
components.html demonstrates the full surface (hero with 72px
CursorGothic + jjannon serif lead, three-voice typography, warm-
surface CTA with crimson hover, accent-orange pill CTA used once,
oklab-fallback bordered cards, AI timeline signature element with
the warm pastel state colors, jjannon-serif input with 4-12 depth
focus). :root paste is byte-identical to tokens.css.
Verified:
- pnpm guard — 13/13 checks pass, including all 8 design-system
sub-checks now reporting "3 brands" (default + kami + cursor):
- token-fixture sync: 3 brand pairs aligned
- A1/A2/B-slot required tokens: all 3 brands declare
26 A1 + 26 A2 + 4 B-slot
- unknown token allowlist: 185 declarations across 3 brands all
match shared schema or brand extensions
- flag parity: 146 prose-only brands byte-identical, 3 structured
diverge as expected
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(design-systems): correct h2/h3 line-height in cursor components fixture
Per DESIGN.md §Hierarchy, 36px section headings use line-height 1.20
and 26px sub-headings use 1.25. The shared h1/h2/h3 rule was locking
all three to --leading-tight (1.10), baking wrong vertical rhythm into
the oracle fixture.
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(design-systems): add structured tokens for apple, stripe, airbnb, vercel brands
Batch follow-up to #1652 (cursor). Adds tokens.css + components.html
for the remaining four high-profile brands, using cursor as the
format/template oracle.
Each brand encodes its specific identity:
- apple: SF Pro tight-compressed display (--leading-tight 1.05),
system-blue accent, SF Symbols grid, frosted glass surfaces
- stripe: sohne-var weight-300 anti-convention signature, --leading-tight
1.10 (matches all heading spec values exactly), indigo accent
- airbnb: Cereal weight-700 display with Rausch coral, --leading-tight
1.20 with per-size overrides (h2→1.18, h3→1.25)
- vercel: Geist 600 compressed display, --leading-tight 1.10 with
per-size overrides (h2→1.20, h3→1.33 per DESIGN.md §Typography)
pnpm guard: 13/13 checks pass; flag-parity now shows 6 structured
brands and 143 prose-only brands.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(design-systems): add structured tokens.css schema (default + kami)
Compile each brand's DESIGN.md prose into a machine-readable :root
block agents paste verbatim, removing the "Primary → --accent"
translation step where most token misuse happens. Daemon prompt
injection lands in a follow-up; lint-artifact already enforces the
shared token vocabulary so no rule changes needed.
Schema validated across two contrasting aesthetics:
- default (sans-serif, cobalt, B2B utility) — stress test the
shallow form, 2-level fg / 2-level surface
- kami (serif, parchment, ink-blue, print-first) — stress test the
rich form, 4-level fg ramp, 3-level surface, ring elevation, i18n
font stacks, and solid-hex tag tints (print renderers double-paint
alpha)
Schema growth from kami's stress test (5 new optional slots, all
backward-compatible — default aliases via var() to existing tokens):
- --fg-2 / --meta (4-level fg ramp)
- --surface-warm (3-level surface)
- --border-soft (2-level border)
- --elev-ring (ring elevation as first-class level)
Brand-specific extensions live in tokens.css with explicit "NOT in
shared schema" labels and a documented promotion path (≥2 brands
need it → promote to schema slot).
components.html in each brand is a self-contained reference fixture
that exercises every token through real layouts. Both fixtures lint
clean against apps/daemon/src/lint-artifact.ts.
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(design-systems): add token-fixture drift guard
Each design system in design-systems/<brand>/ ships two files agents
consume in tandem: tokens.css (canonical token bindings) and
components.html (a self-contained fixture whose first <style> embeds
the same :root paste so the file renders standalone). The fixture's
:root block is a copy of tokens.css's :root block, kept in sync only
by an inline comment.
This adds scripts/check-tokens-fixture-sync.ts and registers it in
pnpm guard. The check pairs each brand's tokens.css with its
components.html and asserts the unscoped :root block is byte-equivalent
after canonical normalization (CSS comments stripped, whitespace
collapsed, separator spacing normalized). Brands missing one half of
the pair, or with no :root rule in either file, fail the guard.
Scoped overrides like :root[lang="zh-CN"] are not required to appear
in the fixture (per the kami fixture's inline comment they are pasted
only when an artifact's <html lang> matches), so the check only
compares the unscoped :root block.
Verified: pnpm guard passes for default + kami, fails on intentional
value drift, fails on missing token, tolerates whitespace-only
formatting differences.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(design-systems): point fixture CTAs to real files
Both default and kami components.html advertised in-page anchors
(#tokens, #spec, #surface, #accent, #type, #components) but defined
no matching ids, so every CTA was a no-op when the fixture was
opened locally — flagged by mrcfps in #1231.
Re-point each link to a real artifact in the same brand directory:
- "View tokens" / "Inspect tokens" / "Inspect typography" → ./tokens.css
- "Read the spec" / "Read the rule" → ./DESIGN.md
Browsers render these as raw source views, which is the desired UX
for a reference fixture: clicking the CTA shows the underlying
contract instead of jumping to nothing. Agents copying the fixture
also learn the pattern of "buttons link to actual sibling resources".
The :root token block is unchanged, so the token-fixture drift guard
still passes for both brands.
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(design-systems): codify token schema (A1/A2/B/C layers)
The two-brand pilot (default + kami) settled the shape of the shared
token schema; this commit codifies it as a machine-readable contract
and enforces it in pnpm guard, addressing lefarcen's review on #1231:
> the optional-vs-required split won't generalize cleanly when brand
> #3 needs different Layer A tokens or when multiple brands converge
> on the same extension (promoting C→B→A). Consider surfacing that
> limitation in the PR narrative or in a future SCHEMA.md.
Schema lives under design-systems/_schema/ as three files:
- tokens.schema.ts — TypeScript declaration of every shared token
with its layer (A1-identity / A1-structure /
A2 / B-slot), plus per-brand C-extension
allowlists and a global C-prefix allowlist
- defaults.css — CSS mirror of A2 fallback values, used as the
human-readable contract reviewer's-eye copy
and the future input to the derive script
- AGENTS.md — schema layer model, C → B-slot → A2 promotion
rules, when-not-to-add-a-token guidance
Layer model:
A1-identity 8 tokens — bg/surface/fg/muted/border/accent +
font-display/font-body. The brand IS these values;
no fallback is defensible.
A1-structure 18 tokens — type scale (8), leading (2), tracking
(1), section-y (3), container (4). Structural
decisions vary per brand by design and have no
cross-brand default.
A2 26 tokens — accent states, semantic colors, motion,
base spacing scale, radius, elevation, focus,
font-mono. Required in every tokens.css; fallback
lives in defaults.css for the future derive script
to inline when DESIGN.md does not specify the value.
B-slot 4 tokens — fg-2 / meta / surface-warm / border-soft.
Brand may bind independently or alias the named
sibling via var(...) for components that target the
richer ramp.
C-extension n tokens — brand-specific names (kami's tag-bg-*,
leading-display, accent-light, etc.). Allowlisted
per-brand in BRAND_EXTENSIONS or globally by prefix
in BRAND_EXTENSION_PREFIXES. Promote when a second
brand adopts the same name.
Why A2 fails the guard today:
Artifacts are generated by agents pasting one brand's :root block
into a single <style>; there is no global stylesheet that supplies
fallbacks at runtime. A tokens.css missing an A2 declaration would
silently break any var() reference in the fixture. Until the
derive script (PR-B) lands and inlines defaults, every brand's
tokens.css must declare every A2 token directly. The guard
enforces this strictly.
Why --font-mono lands in A2 (not A1):
149 brands' DESIGN.md files were surveyed: 87 (58%) declare a
monospace stack, 62 (42%) do not — including major brands like
bmw / nike / apple / notion / mastercard / meta. Agent paste
cannot rely on the brand author having written it down; a
defaultable A2 fallback (with CJK brands like kami overriding) is
safer than forcing every brand author to add a field they may not
realize their kbd / code-block components need.
Five guard checks, each registered as its own entry in scripts/guard.ts
so failures attribute to a specific contract:
1. token-fixture sync — components.html :root ↔ tokens.css :root
byte-equivalent (existing)
2. A1 required tokens — every brand declares every A1 token
3. A2 required tokens — every brand declares every A2 token
4. unknown token allowlist — every declared token is in schema or
brand-extension allowlist
5. A2 defaults parity — defaults.css ↔ tokens.schema.ts
fallback byte-equivalent
Verified on default + kami:
- 26 A1 tokens declared in both brands
- 26 A2 tokens declared in both brands
- 129 total declarations, all match shared schema or brand extensions
- defaults.css ↔ tokens.schema.ts parity holds
- sanity test: drifting --motion-fast in defaults.css fails check 5
with a clear divergence message
The PR description originally listed "Dedicated SCHEMA.md" as
explicitly NOT in this PR ("Once 3+ brands ship, extracting a single
source of truth becomes worthwhile"). That boundary moves: lefarcen's
review surfaced the schema-generalization risk, and the schema must
exist as a machine-enforced contract before the derive script can
read it. The TS file replaces the markdown that was deferred.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(web/tests): pass missing designTemplates prop to ProjectView
Pre-existing typecheck regression on main: PR #955 (b5eb8c16,
"generic skills + split skills/design-templates + finalize-design
API") added required `designTemplates: SkillSummary[]` to ProjectView
Props but updated only two of the three test fixtures that render
ProjectView directly. The third — ProjectView.api-empty-response.test.tsx
— was missed, so `pnpm typecheck` (and CI on any PR merging into
main) fails on:
apps/web/tests/components/ProjectView.api-empty-response.test.tsx
(168,6): error TS2741: Property 'designTemplates' is missing in
type ...
The other two ProjectView tests already pass `designTemplates={[]}`,
so this aligns this fixture with the existing pattern. Out of scope
for #1231 strictly, but the regression blocks the merged-state
typecheck CI runs that #1231 triggers, and the one-line fix here
restores main's typecheck health for everyone.
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(design-systems): enforce B-slot required tokens in pnpm guard
Closes mrcfps + lefarcen review comment thread on #1231:
> The guard validates A2 required tokens here, but there's no
> sibling check for B-slot aliases (--fg-2, --meta, --surface-warm,
> --border-soft). Per the schema docs, every brand must declare
> A1 + A2 + B-slot names so shared components can safely read
> var(--fg-2) etc. Without a B-slot guard, a brand can omit those
> aliases, pass pnpm guard, and break any artifact that references
> them.
Same artifact-paste constraint as A2: agents render artifacts by
pasting one brand's :root block into a single <style>; there is no
runtime cascade, so a missing B-slot makes any var(--fg-2) reference
resolve to nothing. Until now the schema narrative claimed B-slots
were optional with a var() default, but no machine check enforced
declaration — a contract gap reviewers reasonably refused to merge.
This commit closes the gap in three places so machine and narrative
agree:
1. scripts/check-tokens-fixture-sync.ts
- Add checkDesignSystemBSlotRequiredTokens, mirroring the A2
check but using getBSlotNames() from the schema.
- Failure message names each missing slot AND the schema-suggested
alias (--fg-2 (default alias: var(--fg))) so a brand author
fixing the failure has a copy-pasteable resolution.
- Renumber section comments: 5 checks → 6 checks.
2. scripts/guard.ts
- Register the new check between A2 required and unknown
allowlist so failures attribute to a specific contract.
3. design-systems/_schema/AGENTS.md
- Update the layer table: B-slot row's "If omitted" column
changes from "resolves via var() to a richer sibling" to
"guard fails — brand must declare, either as var(--sibling)
(collapsed) or independent value (richer)".
- Add a "Why B-slot is required (and what the alias is for)"
section that distinguishes the schema-suggested alias from a
runtime fallback, with worked examples for default (alias) and
kami (independent bind).
Verified on default + kami:
- pnpm guard passes all 6 design-system checks
- 4 B-slot tokens declared in both brands (default aliases via var(),
kami binds independently — both forms satisfy the contract)
- pnpm typecheck clean across the workspace
- Sanity test: removing --fg-2 + --meta from default/tokens.css fires
the new guard with a precise per-token alias hint:
[default] design-systems/default/tokens.css is missing 2 B-slot
tokens (alias the named sibling via var(...) or bind
independently):
--fg-2 (default alias: var(--fg)),
--meta (default alias: var(--muted))
The schema contract is now machine-enforced end-to-end (A1 + A2 +
B-slot all required-with-fixed-form-of-fallback). The derive script
in PR-B can rely on every brand's tokens.css containing every shared
slot name.
Co-authored-by: Cursor <cursoragent@cursor.com>
* test(e2e): skip leading-underscore meta-directories under design-systems/
CI for #1231 went red on `Validate workspace` after merging origin/main.
Cause is a clean collision between two recently-landed changes:
- main #1270 (be77dc03 "Default English resource i18n fallback")
tightened tests/localized-content.test.ts so every directory under
design-systems/ is run through assertResourceId() with the strict
RESOURCE_ID_PATTERN /^[a-z0-9][a-z0-9-]*$/.
- this branch #1231 introduced design-systems/_schema/ as the home
of the shared token contract (tokens.schema.ts, defaults.css,
AGENTS.md). The leading underscore signals "meta-directory, not
brand" — the same convention SCSS partials, Jekyll, Hugo all use.
The two changes never met until CI built the merge commit, where
assertResourceId('_schema') deterministically failed:
Error: Design system directory _schema has malformed resource id: _schema
at invariant tests/localized-content.test.ts:66:11
at assertResourceId tests/localized-content.test.ts:71:3
at readDesignSystemResources tests/localized-content.test.ts:202:8
Fix tightens readDesignSystemResources's directory filter so the
leading-underscore convention is recognised explicitly:
.filter((entry) => entry.isDirectory() && !entry.name.startsWith('_'))
This aligns with what apps/daemon/src/design-systems.ts:listDesignSystems
already does implicitly — it requires DESIGN.md per directory, so
_schema/ was always invisible at runtime; the test was the only place
that surfaced it.
Verified locally on the post-merge tree:
- pnpm test (e2e vitest) — tests/localized-content.test.ts: 4 passed
- pnpm guard — all 6 design-system checks pass on default + kami
- pnpm typecheck — clean across the workspace (after pnpm install
to pull deps for tools/pr that arrived with main)
The fix is intentionally narrow (one filter line in one test) and
documents the convention inline so future meta-directories under
design-systems/ (e.g. _archive/, _drafts/) are covered for free.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: chaoxiaoche <chaoxiaoche@192.168.10.16>
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat: add WeChat design system, login-flow skill, and fix API mode tool_calls bug
- Add WeChat design system (design-systems/wechat/) with full brand spec
including color palette, typography, and component rules for chat UI
- Add login-flow skill (skills/login-flow/) for mobile authentication flows
with P0 checklist, example HTML, and i18n registration across 3 locales
- Fix DeepSeek V4 bug: API/BYOK mode (streamFormat=plain) models now receive
a directive to emit only <artifact> HTML blocks and suppress tool_calls,
since plain adapters proxy to external providers that cannot execute tools
* fix: restore full server.ts and WeChat DESIGN.md from ad46d8cd commit
Restore files that were corrupted in PR #1083 head branch.
The WeChat DESIGN.md was reduced to a single line (filename only)
and server.ts was reduced to ~1 line. Both are restored to their
original ad46d8cd state with full content.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix: restore full server.ts and WeChat DESIGN.md from ad46d8cd
Restore files corrupted in PR #1083:
- apps/daemon/src/server.ts: restored 7106-line file
- design-systems/wechat/DESIGN.md: restored 301-line WeChat design spec
- skills/login-flow/SKILL.md: restored from local working state
- skills/login-flow/example.html: restored 351-line example HTML
* fix: only suppress tool_calls when streamFormat='plain' explicitly, remove nonexistent assets/template.html
1. streamFormat check now requires explicit 'plain' value instead of defaulting
to 'plain' when undefined. This prevents normal tool-using chat runs from
incorrectly inheriting the API/BYOK tool_calls suppression rule.
2. login-flow SKILL.md: removed reference to assets/template.html since that file
does not exist in the skill bundle and derivePreflight() would inject a hard
instruction to read it before any other tool, causing pre-flight to fail.
* fix: thread streamFormat to composeSystemPrompt in server.ts call
Previously the composeSystemPrompt call at line ~4940 omitted streamFormat,
causing the composer to default to 'plain' and suppress tool_calls even
for tool-using chat runs. Now streamFormat is passed through from the
adapter definition so the API mode rule only fires when streamFormat='plain'
is explicitly set.
* fix: WeChat category metadata, font-family, and login-flow example interactivity
WeChat DESIGN.md:
- Add Category: Social & Messaging metadata so it appears correctly in picker
- Fix font-family declaration: remove invalid -webkit-font-family prefix,
use standard font-family so downstream CSS generation works correctly
skills/login-flow/example.html:
- Add password toggle click handler so show/hide actually works
- Change Apple icon fill from hardcoded #fff to currentColor so it is
visible on light backgrounds
* fix: mirror streamFormat suppression in contracts composer and add WeChat i18n
1. packages/contracts/src/prompts/system.ts: Add streamFormat parameter to
ComposeInput and ComposeInput interface, mirroring the same suppression
rule from daemon prompts/system.ts. When streamFormat='plain' is passed,
a directive is appended telling models not to emit tool_calls and to only
output <artifact> HTML blocks.
2. apps/web/src/i18n/content.{ts,fr,ru}.ts: Add WeChat design system entries:
- Add 'wechat' to DE/FR/RU_DESIGN_SYSTEM_IDS_WITH_EN_FALLBACK arrays
- Add 'wechat' summary to DE/FR/RU_DESIGN_SYSTEM_SUMMARIES
- Add 'Social & Messaging' category to DE/FR/RU_DESIGN_SYSTEM_CATEGORIES
(matching the Category: Social & Messaging metadata in WeChat DESIGN.md)
* fix: thread streamFormat='plain' into web composeSystemPrompt for api mode
* test: focus localized content coverage on missing resources
---------
Co-authored-by: Open Design Contributor <z@open-design.dev>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Co-authored-by: mrcfps <mrc@powerformer.com>
* feat(design-systems): add Slack design system
* fix(i18n): cover slack design system in de/ru/fr fallback lists
The localized-content coverage test scans design-systems/*/DESIGN.md
and asserts every id appears in each locale's designSystems list.
Adding the slack design system without a locale fallback entry breaks
de/ru/fr CI.
---------
Co-authored-by: lefarcen <935902669@qq.com>
* feat: add Urdu Modern design system
* fix: address review comments (font mismatch, contrast, and i18n fallback)
* fix: address all review comments for Urdu design system
* fix: resolve i18n crash, font URL mismatch, and markdown syntax error
* fix: remove font URL space and update Quick Start font token
* docs: fix quick start link syntax and icon source order
* fix(i18n): cover urdu design system in de/ru/fr locale dictionaries
The localized-content coverage test scans design-systems/*/DESIGN.md and
asserts every id appears in each locale's designSystems list, and every
`> Category:` value is a key in designSystemCategories. Adding the new
`urdu` design system without these entries breaks de/ru/fr CI.
Add urdu to the EN-fallback id list and translate the new
'Editorial / Personal / Publication' category for all three locales.
* fix(i18n): cover mission-control design system in de/ru/fr fallback lists
Mission Control was added in #858 but its design-system id was never
added to the locale fallback arrays, so the localized-content coverage
test breaks once main and any open PR share the same merge ref.
---------
Co-authored-by: unknown <muhammadanas0261@gmail.com>
Co-authored-by: lefarcen <935902669@qq.com>
* feat(design-systems): add Mission Control design system
* fix(mission-control): address all reviewer comments - add font extraction labels, remove CSS duplication, fix T+/T- comment, add use case motivation, acknowledge light mode edge case
* feat(skills): add social-media-dashboard skill + Totality Festival design system
- New skill 'social-media-dashboard': single-screen creator analytics
dashboard with platform switcher (X / GitHub / LinkedIn / YouTube /
Instagram), KPI row, growth chart with annotations, top-post / top-PR
preview, trending topics, and top comments. Includes a self-contained
example.html (Totality Festival styled, X + GitHub tabs, live KPI
ticker, GitHub contributors grid, world-map audience geography).
- New design system 'totality-festival': cosmic-premium dark glassmorphic
system with amber corona highlights and cyan atmospheric accents.
Mirrors Google Labs' design.md spec example so skills can be
validated against an upstream reference.
- Fix swatches parser in apps/daemon/src/design-systems.ts so it
recognises the '- **Name:**' bold-with-inner-colon form used by
several existing systems (ant, totality-festival, ...). Previously
only the '**Name** (`#hex`)' form was matched, which left their
picker thumbnails empty.
* feat(skills): polish social-media-dashboard example + add PR preview
- Top Post media block: replace empty gold frame with an inline SVG
thumbnail (radial glow + ascending data curve + amber/cyan pulse dots
+ play icon + 'LIVE · 0:22' caption). Visually echoes the live-artifact
story the post copy is selling.
- Hoist the brand-mark linearGradient into a global SVG defs block at
the top of <body> so all three avatars (header, user, top-post) can
reference url(#brandRing) and render the teal arrow consistently.
Previously only the header SVG carried the gradient definition, so
the user and post avatars rendered as empty rings under headless
capture.
- Add hero.png preview to .preview/ for the PR description.
---------
Co-authored-by: Tuola Ge <gexingli@refly.ai>
* feat(skills): open-design-landing rename, kami skills, landing OG
- Rename editorial-collage skills to open-design-landing and -deck; refresh examples and compose script layout
- Add kami-deck and kami-landing skills with HTML examples
- Landing page: og.astro, index wiring, and style tweaks; package.json bump
- Web i18n: German and Russian copy for renamed and new skills
- Daemon test: update skill-asset-rewrite expectations for new paths
- Design systems: README and atelier-zero doc touch-ups
- Cross-skill SKILL.md reference updates
Co-authored-by: Cursor <cursoragent@cursor.com>
* docs(landing-page): document version-slot invariant and deprecation timeline
Address P3 review notes on PR #428:
- Note the `data-github-version` wrapper invariant (version string only)
near the canonical URL block in `app/page.tsx`.
- Expand the `formatVersion` helper comment in `app/pages/index.astro`
with concrete `release.name` / `tag_name` example shapes for each
branch of the regex fallback.
- Tighten the `EditorialCollageDeckInputs` deprecation in
`skills/open-design-landing-deck/schema.ts` to a specific removal
version (v0.4.0) and add a "Migrating from editorial-collage-deck"
section to the skill README.
Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)
* docs(landing-page, skills): clarify version slot script and rename migrations
- Describe GitHub version slots as driven by the inline enhancement script,
not React hydration.
- Add editorial-collage → open-design-landing migration notes; fix README
link copy (Astro static landing app).
- Extend deck README migration table with shared asset path renames.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(daemon): alias deprecated editorial-collage skill ids
The PR renames the editorial-collage / editorial-collage-deck skills
to open-design-landing / open-design-landing-deck, but the daemon
persists exact skill_id strings on projects and resolves them via
listSkills().find((s) => s.id === storedId). After the rename, any
project saved against an old id silently composes without the intended
skill prompt because the listing no longer exposes that id.
Add a SKILL_ID_ALIASES map in skills.ts plus a findSkillById() helper
that rewrites deprecated ids to their current canonical form, then
route every server-side lookup (skill detail, example HTML, asset
proxy, system-prompt composer) through it. Cover the alias map, the
resolver, and end-to-end resolution against a temp skills directory
with a regression test.
Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)
* fix(kami-deck): route host od:slide messages through local go()
The host bridge classifies kami-deck as class-driven because go() toggles
.slide.active, but the visible slide is moved by deck.style.transform
which the bridge cannot drive. Listen for od:slide messages and dispatch
them through the local go() so toolbar next/prev and initialSlideIndex
restore actually shift the deck.
Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)
* fix(kami-deck): sync deck transform with host-driven .active changes
The previous fix added a local od:slide listener but the host bridge in
apps/web/src/runtime/srcdoc.ts also listens for the same message and
calls setActive() (toggles .slide.active) without driving the deck
transform. Both listeners fired, the bridge re-read the just-toggled
active class, and overshot by one — and the bridge's restoreInitialSlide
path could move .active without a message at all, leaving the deck on
the original transform.
Stop the bridge from double-handling by calling stopImmediatePropagation
in the local listener (registered first because the bridge script is
appended to </body>), and add a MutationObserver that pulls the deck
transform onto whichever slide currently carries .active so the bridge's
direct setActive calls (notably the initial-slide restore) move the deck
too.
Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)
* fix(i18n): align French content with renamed/new skills
PR #434 (French localization) merged into main with French copy for the
old editorial-collage / editorial-collage-deck skill ids; this branch
renamed those to open-design-landing / open-design-landing-deck and
added kami-deck and kami-landing. Update content.fr.ts to track the
rename and add French copy for the new kami skills so the
LOCALIZED_CONTENT_IDS coverage test passes once main is merged.
Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)
* fix(open-design-landing-deck): sync deck transform with host-driven .active changes
Apply the same fix that landed in skills/kami-deck/example.html
(commits 96b255b, 8cbca30) to the open-design-landing-deck composer
runtime: the host bridge classifies this deck as class-driven because
go() toggles .slide.active, but the visible slide is moved by
deck.style.transform which the bridge can't drive. Add an od:slide
message listener that calls stopImmediatePropagation() and routes nav
through the local go(), plus a MutationObserver that pulls the deck
transform onto whichever slide carries .active so the bridge's direct
setActive calls (notably restoreInitialSlide) move the deck too.
Regenerates example.html via scripts/compose.ts; the regeneration also
picks up upstream nav-cta and brand-meta CSS additions in the sister
open-design-landing styles.css that the example had drifted from.
Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)
* docs(open-design-landing): align deploy story with Astro landing app
- Update SKILL contract: apps/landing-page is Astro static; clarify
nextjs-app output_format as a historical enum label and <out>/nextjs
as a legacy folder name.
- Replace optional-deploy section with fork + pnpm --filter landing-page build.
- Fix styles.css header and regenerate landing + deck example.html so
inlined comments match.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(deck-runtime): bypass interaction lock for host/observer slide sync
The slide deck runtimes for kami-deck and open-design-landing-deck
gate go() behind a 700ms `lock` so wheel/key/touch input bursts can't
overshoot the transform transition. But applying the same gate to the
host bridge's od:slide messages and the MutationObserver watching
`.slide.active` creates a startup race: go(0) at the end of init sets
lock=true, and any host-driven `.active` change inside that window
(notably restoreInitialSlide) fires the observer, which calls go(i),
which exits at the lock guard — leaving the visible deck on slide 1
while the host counter advances to N.
Split the actual state update into an unthrottled `applySlide(n)`
helper that updates transform, `.active`, dot nav, and the progress
bar. Keep `lock` only on the user-input path through `go()`. Route
the message listener, the MutationObserver, and the initial render
through `applySlide` directly so host-driven sync always reaches the
deck transform regardless of the throttle state.
Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(editorial-collage): introduce Atelier Zero style landing page assets and documentation
- Added new design system for Atelier Zero, including a detailed `DESIGN.md` file.
- Created an `editorial-collage` skill with associated assets for a magazine-grade landing page.
- Included example HTML and image assets for various sections (hero, about, capabilities, etc.).
- Updated README files to guide usage and customization of the new skill and design system.
- Introduced a new image generation prompt pack for consistent visual style across the landing page.
* fix(i18n): cover atelier-zero design system and editorial-collage skill in German content
Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)
* fix(editorial-collage): align manifest with shipped assets and address PR review
- Update image-manifest.json widths/heights/ratios to match the actual PNGs
on disk: hero/about/cap/testimonial/cta = 1024x1024 (1:1), method-1..4 =
816x816 (1:1), lab-1..5 and work-1..2 = 768x1024 (3:4). Mirror the new
dimensions in imagegen-prompts.md headings and in README.md.
- Mark testimonial.png as rekey_on_brand_change so the manifest agrees
with SKILL.md's "regenerate at minimum testimonial.png" guidance, and
add work-1/work-2 to the rekey list in SKILL.md and README.md.
- Add a Hero (I.) sec-rule and renumber every following section II..VIII
in example.html so the eight sections walk sequentially I -> VIII and
the page-of-008 counter starts at 001.
- Delete editorial-artifact-system/ (16 duplicate PNGs + index.html +
skills.md draft) — the canonical version is skills/editorial-collage/
and the duplicate had no consumer references.
- DESIGN.md: spell out which dimensions of each magazine reference
(Monocle/Apartamento/IDEA), document the rationale for single-accent
vs multi-accent, and extend the anti-pattern list with AI-image-gen
artifacts the system explicitly rejects.
- SKILL.md: add italic_words validation guidance (trim, cap at 4,
verb->noun rewrite, punctuation strip) and replace the broken-image
fallback with an inline SVG placeholder sized to the slot's
manifest aspect ratio.
Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)
* fix(daemon): serve skill example assets via stable API route
Skill example HTML such as `skills/editorial-collage/example.html`
references shipped images via `./assets/*.png`. The web app loads the
example into a sandboxed iframe via `srcdoc`, where relative URLs
resolve against `about:srcdoc` and the PNGs render as broken images in
the Examples preview.
Add a `GET /api/skills/:id/assets/*` route that serves files under the
skill's `assets/` directory with path-traversal guards, and rewrite
`src='./assets/<file>'` / `href='./assets/<file>'` in the example
response to point at that route. The disk preview keeps working
because the on-disk files are unchanged.
Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)
* feat(landing-page): add new static Next.js 16 site for Open Design marketing
- Introduced a new landing page application using Next.js 16, featuring a static export setup.
- Added essential files including `package.json`, `next.config.ts`, and TypeScript configuration.
- Implemented global styles in `globals.css` to match the Atelier Zero design system.
- Created a detailed `AGENTS.md` for module-level boundaries and purpose.
- Included various image assets for the landing page, ensuring a visually cohesive experience.
- Established a root layout and main page structure to support the marketing content.
* style(landing-page): enhance topbar layout and improve responsiveness
- Added nowrap styling to topbar elements to prevent text overflow.
- Introduced media query to hide mid text in the topbar for screen widths between 1200px and 1280px.
- Updated layout.tsx to suppress hydration warnings for better rendering consistency.
- Removed redundant "Compiled by Open Design" text from the page component.
* feat(landing-page): implement scroll-reveal animations for enhanced user experience
- Added a new `RevealRoot` component to manage scroll-triggered reveal animations.
- Updated `globals.css` with styles for elements using the `data-reveal` attribute, including opacity, translation, and scaling effects.
- Modified `layout.tsx` to include the `RevealRoot` component for managing animations.
- Enhanced `page.tsx` by adding `data-reveal` attributes to various elements for staggered reveal effects.
- Implemented reduced motion support to ensure accessibility for users with motion sensitivity.
* fix(landing-page): update import paths and enhance link styles
- Changed the import path in `next-env.d.ts` to reference the correct routes type definition.
- Enhanced `globals.css` with new styles for topbar links, work cards, and partner elements, improving hover effects and transitions.
- Updated `page.tsx` to include canonical project URLs and made various links point to these URLs for better navigation and accessibility.
* feat(landing-page): implement headroom-style sticky header with live GitHub star count
- Introduced a new `Header` component to manage sticky navigation behavior on scroll, enhancing user experience.
- Updated `globals.css` to style the sticky header, including transitions and visibility toggling based on scroll direction.
- Modified `page.tsx` to replace the static header with the new `Header` component, which fetches and displays the live GitHub star count.
- Ensured accessibility by providing a fallback for users who prefer reduced motion.
* feat(landing-page): enhance editorial landing page with global ticker and new styles
- Updated `next-env.d.ts` to reference the correct routes type definition for development.
- Enhanced `globals.css` with new styles for the global ticker, including responsive design and improved overflow handling.
- Introduced a new `WIRE_CITIES` and `WIRE_CONTRIBS` data structure in `page.tsx` to display a counter-scrolling marquee of cities and contributors.
- Added a ghost button style for the navigation call-to-action in the header.
- Updated various sections in `page.tsx` to integrate the new ticker and improve overall layout and accessibility.
* refactor(landing-page): update paper texture overlay and remove multica-ai link
- Enhanced comments in `globals.css` to clarify the purpose and behavior of the paper texture overlay.
- Adjusted z-index of the overlay to ensure proper layering with other elements.
- Removed the `multica-ai` partner link from `page.tsx` to streamline the partner section.
* feat(landing-page): implement dynamic contributor marquee with GitHub integration
- Added a new `Wire` component to display a counter-scrolling marquee of cities and contributors.
- The contributor list is fetched live from the GitHub API, ensuring up-to-date information.
- Updated `page.tsx` to integrate the `Wire` component, replacing the static contributor list with dynamic content.
- Enhanced comments for clarity regarding the functionality and purpose of the global wire.
* fix(i18n): add German display copy for editorial-collage-deck skill
The Validate workspace test asserts that GERMAN_CONTENT_IDS.skills covers
every curated skill on disk; the new editorial-collage-deck skill was
missing from DE_SKILL_COPY, causing src/i18n/content.test.ts to fail.
Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)
* feat(landing-page): migrate marketing site to Astro
* perf(landing-page): remove React client runtime
* perf(landing-page): serve images from Cloudflare resizing
* fix(pr): address landing page review feedback
---------
Co-authored-by: mrcfps <mrc@powerformer.com>
* feat(web): add brand design systems, card thumbnails, and DESIGN.md side-by-side preview
- Add 7 new brand design systems (arc, canva, discord, duolingo, github, huggingface, openai)
- Show live showcase HTML thumbnails on Design Systems cards
- Add toggleable DESIGN.md side panel in preview modal with syntax-highlighted spec view
- Make preview iframe responsive: render at fixed design viewport and scale to fit so opening the side panel never reflows showcases into broken breakpoints
- Add floating collapse/expand handles on the sidebar boundary for direct hide/show
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(web): guard ResizeObserver and re-fire sidebar lazy-load on content swap
- Guard `new ResizeObserver(...)` in PreviewModal so the modal mounts in
jsdom (the existing preview-modal-fullscreen test was failing with
`ReferenceError: ResizeObserver is not defined`) and in older embedded
WebViews. Fall back to a window resize listener when the constructor
is unavailable.
- Add a `contentKey` hint to PreviewSidebar so the lazy-load `onToggle`
callback re-fires when the underlying side-panel source swaps while
the sidebar stays open. Wire `system.id` through from
DesignSystemPreviewModal so swapping design systems with the spec
panel open primes a fresh DESIGN.md fetch instead of leaving it stuck.
Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)
* fix(web/i18n): add missing ds/preview keys to hu locale
The Validate workspace check failed after main's hu.ts landed
without the four i18n keys introduced by this PR (ds.specToggle,
ds.specLoading, preview.showSidebar, preview.hideSidebar).
Generated-By: looper 0.4.0 (runner=fixer, agent=claude-code)
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat(design-systems): integrate kami as editorial paper system + deck starter
- Add design-systems/kami/DESIGN.md adapting kami's tokens, ten invariants,
and type/color/component rules into the OD DESIGN.md spec. Lands under a
new "Editorial & Print" category in the picker.
- Add templates/kami-deck.html: a kami-flavored variant of deck-framework.html
(parchment canvas, ink-blue accent, single-weight serif) with five demo
slides — cover, agenda, metric row, two-column body+pull-quote, closing —
so it doubles as a worked example for slide and prototype work.
- Update design-systems/README.md and README.md to list and credit kami
(MIT, tw93/kami).
- Update apps/web/src/i18n/content.ts so the i18n coverage test passes:
add the German summary for 'kami' and the 'Editorial & Print' category.
* docs(design-systems/kami): address PR #226 review notes
Five P3 polish edits from @lefarcen's review (LGTM, non-blocking):
1. Add a "When to swap the stack" subsection in §3 spelling out how the
three CJK font stacks combine: set the dominant-language stack on
:root, scope per-section overrides for mixed-language artifacts,
never chain all three families inside one font-family declaration.
2. Reframe the brand as "kami / 紙 / 纸" so the system reads as
co-designed across EN, zh-CN, and ja from the start, not Japan-centric
with i18n bolted on. Title and §1 lede updated.
3. Reconcile the pt → px ratios into one table at the top of §3
"Hierarchy": print pt × ~1.33 for page artifacts, × 1.6 for slide
macro tokens, × 0.6 for slide micro tokens. Drop the duplicate
ratio bullets from §5 "Slides".
4. Keep the soft tag-brush gradient exception but make it real: add
the .tag.brush CSS + an inline <span class="tag brush"> example
in §4, and surface it once on slide 04 of the kami deck so agents
see exactly when the carve-out applies.
5. Add a "Tabular-nums contexts" subsection in §3 enumerating every
place numbers should opt into tabular-nums (metrics, footers,
section numbers, dates, financial tables, KPI grids, version
numbers, side-by-side comparisons) — and the rule for when not to
(single numbers in running prose).
* docs(xiaohongshu): address review feedback from #24
Ten review notes from #24, eight applied in this file, one tracked in PR
body, one explicitly deferred per reviewer guidance.
- §2: clarify the brand-red split — the +6 red-channel shift between
#FF2442 (token) and #FF2E4D (component layer) is documented as
intent-undocumented-upstream rather than left implicit.
- §2: add a heads-up that danger reuses --primary, so destructive
actions and primary CTAs are visually identical out of the box;
recommend outline + brand-red text or a leading destructive icon as
a defensive default.
- §2: state dark-mode trigger explicitly (prefers-color-scheme + manual
override; both :root[dark] and .force-dark honored).
- §5: explain *why* the masonry uses translate3d + ResizeObserver
rather than CSS Masonry — the latter is still flagged in most
browsers as of 2026.
- §6: add a dark-mode row to the elevation table; alpha-on-black
shadows are invisible on the #19191E canvas, so drop hover shadows
and replace modal shadow with a 1px hairline at rgba(255,255,255,.07).
- §7: forbid fabricating the 小红书 wordmark / RED logotype as artifact
output (tokens are not protectable, the wordmark is — emit a labelled
grey block instead).
- §7: forbid referencing RED Number standalone in generated CSS without
the PingFang fallback chain.
- §7: add a concrete shadow threshold to the heavy-shadows Don't —
alpha > 0.15 or spread > 16px is the cutoff.
- §9: new "Brand Red Disambiguation" subsection at the top of the Agent
Prompt Guide making the per-surface rule explicit (default: #FF2442;
pixel-replica only: #FF2E4D; never mix on one component).
Schema-drift between CONTRIBUTING.md and the bundled design-system
corpus is intentionally not addressed here — the reviewer flagged it as
a wider-scope cleanup affecting all ~70 systems and explicitly said
"no action requested in this PR" if treated as such.
* docs(xiaohongshu): correct channel-delta in brand-red rationale
Codex review bot caught a numerical error in #54: #FF2442 → #FF2E4D
is not "+6 on the red channel" — both colors share the same red
channel (FF = 255). The actual delta is +10 on green (24 → 2E) and
+11 on blue (42 → 4D), which together raise lightness slightly and
shift the hue a touch toward pink.
Document review badge: P2.
* feat(dev): add desktop tools-dev control plane
* refactor(sidecar): split Open Design contracts
Move Open Design-specific sidecar protocol definitions into @open-design/contracts so sidecar and platform can remain descriptor-driven primitives.
* refactor(daemon): organize package sources
Keep daemon app code, tests, and sidecar entrypoints in separate package directories so each layer can be built and verified independently.
* chore(repo): streamline maintenance entrypoints
Centralize agent guidance by directory and reduce root command chains while preserving the existing build scope.
* docs: translate agent guidance to English
* fix(sidecar): tolerate stale IPC sockets
Remove stale Unix socket files only after confirming no listener is active, so tools-dev can restart after unclean shutdowns.
- Adds design-systems/xiaohongshu/DESIGN.md. Lands under Media & Consumer.
- Color, typography, layout, component, and dark-mode tokens sampled
from production CSS at https://www.xiaohongshu.com/explore — the
inline :root,.force-light and :root[dark],.force-dark blocks.
- Brand primary captured as two values: #FF2442 (the --primary token)
and #FF2E4D (hard-coded on .reds-button-new.primary and .active-bar).
Both ship in the live UI.
- Danger / error reuses --primary; no independent error token in source.
- Bookmark / collect star (#FDBC5F) sampled from the inline
<symbol id="collected"> SVG path fill. Digits use the custom RED
Number family (Regular / Medium / Bold).
- Narrative copy in English per CONTRIBUTING.md; real product strings
(brand name, slogan, font name, follow-button labels, profile tab
labels) kept verbatim with English glosses, mirroring
pinterest/DESIGN.md preserving its Japanese font fallback names.
- Upstream VoltAgent/awesome-design-md does not currently include any
Chinese-internet brand, so this lands directly in the OD bundled set
rather than going to upstream first.
* Refactor project name from "Open Claude Design" to "Open Design"
- Updated project name in package.json, package-lock.json, and README files.
- Changed CLI commands and references from "ocd" to "od".
- Adjusted file structure references in documentation and code to reflect new naming conventions.
- Enhanced .gitignore to include new runtime data files.
- Updated metadata in LICENSE file to match new project name.
* Add contributing guidelines in English and Chinese
- Introduced CONTRIBUTING.md and CONTRIBUTING.zh-CN.md to provide clear instructions for contributors.
- Outlined contribution types, local setup instructions, and merging criteria for skills and design systems.
- Enhanced README files to reference the new contributing guidelines.
- Created .gitignore to exclude build artifacts and dependencies.
- Added index.html as the main entry point for the application.
- Included LICENSE file with Apache 2.0 terms.
- Initialized package.json and package-lock.json for project dependencies.
- Added pnpm-lock.yaml for package management.
- Created QUICKSTART.md for setup instructions.
- Added README.md and README.zh-CN.md for project documentation in English and Chinese.