diff --git a/.changeset/claude-design-align.md b/.changeset/claude-design-align.md new file mode 100644 index 0000000..cb14041 --- /dev/null +++ b/.changeset/claude-design-align.md @@ -0,0 +1,10 @@ +--- +'@open-codesign/core': patch +--- + +Align system prompt content with Claude Design conventions extracted from real artifact analysis (research docs §11.4, §1.2, §2, §6, §11.3): + +- EDITMODE protocol: empty `{}` block is now valid — signals tweak-aware artifacts to the host. +- Design methodology: token-density target 9 ± 3 oklch tokens per artifact. +- Craft directives: typography ladder defaults to two font families (mono only when needed); add four-animation CSS keyframe budget (`fadeUp` / `breathe` / `pulse-ring` / `spin`). +- Progressive disclosure: marketing/landing/case-study prompts now surface a Fraunces typography hint as a Layer 2 routing addition. diff --git a/packages/core/src/generate.test.ts b/packages/core/src/generate.test.ts index 83030f9..cd24fe1 100644 --- a/packages/core/src/generate.test.ts +++ b/packages/core/src/generate.test.ts @@ -1441,6 +1441,20 @@ describe('composeSystemPrompt() — progressive disclosure', () => { expect(p).toContain('Customer quotes deserve distinguished treatment'); }); + it('marketing prompt includes Fraunces hint', () => { + const p = composeSystemPrompt({ + mode: 'create', + userPrompt: 'indie marketing landing page', + }); + expect(p).toContain('Fraunces'); + expect(p).toContain('Marketing typography hint'); + }); + + it('dashboard prompt does NOT include Fraunces hint', () => { + const p = composeSystemPrompt({ mode: 'create', userPrompt: '做个数据看板' }); + expect(p).not.toContain('Marketing typography hint'); + }); + it('no-keyword prompt: falls back to FULL craft directives', () => { const p = composeSystemPrompt({ mode: 'create', userPrompt: '随便做点东西' }); // Full craft directives includes ALL ten subsections — verify several signal ones diff --git a/packages/core/src/prompts/craft-directives.v1.txt b/packages/core/src/prompts/craft-directives.v1.txt index 342f330..0e6fe3c 100644 --- a/packages/core/src/prompts/craft-directives.v1.txt +++ b/packages/core/src/prompts/craft-directives.v1.txt @@ -46,12 +46,13 @@ Do not bury headline metrics in body paragraphs. ## Typography ladder -A polished single-page artifact combines three type families: -- Display / editorial — headlines, hero numbers, section openers -- Workhorse sans — body, navigation, captions -- Mono — data, code, tabular numbers, timestamps, kbd-style accents +Default: **two font families** — display/editorial for hero, headlines, numbers; workhorse sans for body, nav, captions. A third (mono) is used ONLY when the design needs timestamps, code, or tabular numerics — not by default. -Use the mono family sparingly (10–15 % of text surface) so it reads as intentional. Pair selection follows the anti-slop preferred-fonts list. +- Display / editorial: hero numbers, section openers +- Workhorse sans: body, navigation, captions +- Mono (when needed): data, timestamps, code accents — sparingly + +Use the bundled display serif (Fraunces) for editorial / case-study / report types; use Geist or another preferred sans for landing / dashboard / pricing. ## Dark themes need warmth @@ -98,3 +99,14 @@ For dashboard / data / analytics artifacts, include these "live system" cues to - KPI cards get a 4px vertical accent bar on the left side. Color varies by metric category (revenue=teal, growth=amber, retention=violet, regions=green) — pick from the artifact palette, not arbitrary. Slide decks substitute: cover → 3-7 content slides with strong hierarchy each → closing slide. + +## Animation budget + +Cap your CSS keyframe library at **four named animations** per artifact. The Claude Design canon: + +- `fadeUp` — entrance (translateY + opacity) +- `breathe` — ambient pulsing (scale 1↔1.08, opacity 0.7↔1) +- `pulse-ring` — emphasis (scale + opacity → 0) +- `spin` — rotation + +Apply with staggered `animation-delay` (0.1s, 0.2s, 0.3s) for section-by-section reveal. Never script a JS animation loop — CSS only. diff --git a/packages/core/src/prompts/design-methodology.v1.txt b/packages/core/src/prompts/design-methodology.v1.txt index 90d6fa7..b663cbf 100644 --- a/packages/core/src/prompts/design-methodology.v1.txt +++ b/packages/core/src/prompts/design-methodology.v1.txt @@ -32,3 +32,14 @@ Each revision should make the design more itself, not more generic. If a revisio - Body text: 16–18 px base (1rem–1.125rem), line-height 1.5–1.7. - Whitespace: err on the side of generous. A design with too much space looks confident; one with too little looks anxious. - Section rhythm: vary height and density. Not every section should be a tight 3-column card grid. + +## Token density + +Aim for 9 ± 3 design tokens per artifact, declared as a flat object at the top of the script: + +- 1 background, 1 surface, 1 high-contrast text, 1 muted text, 1 border/line +- 1 accent + 1 light pair (e.g. `green` + `greenL`) +- Optional: 1 secondary accent + light pair +- All in `oklch()`, with `/ alpha` for transparency (`oklch(1 0 0 / 0.82)`) + +Brutal minimalism. A 9-token palette is the entire design system for one artifact. diff --git a/packages/core/src/prompts/editmode-protocol.v1.txt b/packages/core/src/prompts/editmode-protocol.v1.txt index 956f167..bcab427 100644 --- a/packages/core/src/prompts/editmode-protocol.v1.txt +++ b/packages/core/src/prompts/editmode-protocol.v1.txt @@ -26,6 +26,16 @@ The host environment will: - Reference the parameters from your code via the named constant (`TWEAK_DEFAULTS.accentColor`). - Pick 3-6 parameters that meaningfully change the artifact's look. Don't expose every CSS variable. +## Empty block is valid + +Even if your artifact has no tunable parameters yet, you may emit an empty block — it signals to the host that this artifact is tweak-aware: + +```js +const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{}/*EDITMODE-END*/; +``` + +The host scans for the markers regardless of contents. + ## Type detection | Value pattern | Renders as | diff --git a/packages/core/src/prompts/index.ts b/packages/core/src/prompts/index.ts index 15655c2..3ea03bf 100644 --- a/packages/core/src/prompts/index.ts +++ b/packages/core/src/prompts/index.ts @@ -168,7 +168,18 @@ Each revision should make the design more itself, not more generic. If a revisio - Headings: large enough to anchor the page, not so large they crowd content. - Body text: 16–18 px base (1rem–1.125rem), line-height 1.5–1.7. - Whitespace: err on the side of generous. A design with too much space looks confident; one with too little looks anxious. -- Section rhythm: vary height and density. Not every section should be a tight 3-column card grid.`; +- Section rhythm: vary height and density. Not every section should be a tight 3-column card grid. + +## Token density + +Aim for 9 ± 3 design tokens per artifact, declared as a flat object at the top of the script: + +- 1 background, 1 surface, 1 high-contrast text, 1 muted text, 1 border/line +- 1 accent + 1 light pair (e.g. \`green\` + \`greenL\`) +- Optional: 1 secondary accent + light pair +- All in \`oklch()\`, with \`/ alpha\` for transparency (\`oklch(1 0 0 / 0.82)\`) + +Brutal minimalism. A 9-token palette is the entire design system for one artifact.`; const EDITMODE_PROTOCOL = `# EDITMODE protocol — declaring tweakable parameters @@ -198,6 +209,16 @@ The host environment will: - Reference the parameters from your code via the named constant (\`TWEAK_DEFAULTS.accentColor\`). - Pick 3-6 parameters that meaningfully change the artifact's look. Don't expose every CSS variable. +## Empty block is valid + +Even if your artifact has no tunable parameters yet, you may emit an empty block — it signals to the host that this artifact is tweak-aware: + +\`\`\`js +const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{}/*EDITMODE-END*/; +\`\`\` + +The host scans for the markers regardless of contents. + ## Type detection | Value pattern | Renders as | @@ -434,12 +455,13 @@ Do not bury headline metrics in body paragraphs. ## Typography ladder -A polished single-page artifact combines three type families: -- Display / editorial — headlines, hero numbers, section openers -- Workhorse sans — body, navigation, captions -- Mono — data, code, tabular numbers, timestamps, kbd-style accents +Default: **two font families** — display/editorial for hero, headlines, numbers; workhorse sans for body, nav, captions. A third (mono) is used ONLY when the design needs timestamps, code, or tabular numerics — not by default. + +- Display / editorial: hero numbers, section openers +- Workhorse sans: body, navigation, captions +- Mono (when needed): data, timestamps, code accents — sparingly -Use the mono family sparingly (10–15 % of text surface) so it reads as intentional. Pair selection follows the anti-slop preferred-fonts list. +Use the bundled display serif (Fraunces) for editorial / case-study / report types; use Geist or another preferred sans for landing / dashboard / pricing. ## Dark themes need warmth @@ -485,7 +507,18 @@ For dashboard / data / analytics artifacts, include these "live system" cues to - A live clock in the top-right of the page header: HH:MM:SS in tabular-nums font, updated each second via a single \`setInterval(updateClock, 1000)\`. This is the ONE permitted JS interval — do not chain other animations onto it. Clear it on unmount if your code supports lifecycle. - KPI cards get a 4px vertical accent bar on the left side. Color varies by metric category (revenue=teal, growth=amber, retention=violet, regions=green) — pick from the artifact palette, not arbitrary. -Slide decks substitute: cover → 3-7 content slides with strong hierarchy each → closing slide.`; +Slide decks substitute: cover → 3-7 content slides with strong hierarchy each → closing slide. + +## Animation budget + +Cap your CSS keyframe library at **four named animations** per artifact. The Claude Design canon: + +- \`fadeUp\` — entrance (translateY + opacity) +- \`breathe\` — ambient pulsing (scale 1↔1.08, opacity 0.7↔1) +- \`pulse-ring\` — emphasis (scale + opacity → 0) +- \`spin\` — rotation + +Apply with staggered \`animation-delay\` (0.1s, 0.2s, 0.3s) for section-by-section reveal. Never script a JS animation loop — CSS only.`; const CHART_RENDERING = `# Chart rendering contract @@ -753,6 +786,10 @@ Do not produce these. Each one is the tell of an unconsidered, generated-feeling These patterns are forbidden when combined without a distinctive visual angle that makes them feel intentional rather than assembled from a component kit.`; +const MARKETING_FONT_HINT = `# Marketing typography hint + +Marketing / landing / case-study artifacts: prefer **Fraunces** (variable font, optical-size 9..144) for the display family — its 72pt+ optical size unlocks subtle character better than fixed-size DM Serif Display. Pair with **DM Sans** or **Geist** for body, and **JetBrains Mono** for any code / timestamp accents.`; + // Split CRAFT_DIRECTIVES into a Map so the // progressive-disclosure composer can include only the subsections relevant to // the user's prompt. The intro paragraph (everything before the first `## `) @@ -798,6 +835,7 @@ export const PROMPT_SECTIONS: Record = { iosStarterTemplate: IOS_STARTER_TEMPLATE, antiSlop: ANTI_SLOP, antiSlopDigest: ANTI_SLOP_DIGEST, + marketingFontHint: MARKETING_FONT_HINT, safety: SAFETY, }; @@ -815,6 +853,7 @@ export const PROMPT_SECTION_FILES: Record iosStarterTemplate: 'ios-starter-template.v1.txt', antiSlop: 'anti-slop.v1.txt', antiSlopDigest: 'anti-slop-digest.v1.txt', + marketingFontHint: 'marketing-font-hint.v1.txt', safety: 'safety.v1.txt', }; @@ -960,6 +999,7 @@ function planKeywordMatches(userPrompt: string): KeywordMatchPlan { topLevel.push(IOS_STARTER_TEMPLATE); } if (KEYWORDS_MARKETING.test(userPrompt)) { + topLevel.push(MARKETING_FONT_HINT); craftSubsectionNames.push( 'Single-page structure ladder', 'Big numbers get dedicated visual blocks', diff --git a/packages/core/src/prompts/marketing-font-hint.v1.txt b/packages/core/src/prompts/marketing-font-hint.v1.txt new file mode 100644 index 0000000..3a000d4 --- /dev/null +++ b/packages/core/src/prompts/marketing-font-hint.v1.txt @@ -0,0 +1,3 @@ +# Marketing typography hint + +Marketing / landing / case-study artifacts: prefer **Fraunces** (variable font, optical-size 9..144) for the display family — its 72pt+ optical size unlocks subtle character better than fixed-size DM Serif Display. Pair with **DM Sans** or **Geist** for body, and **JetBrains Mono** for any code / timestamp accents.