@ericrisco/rsc 3.1.4 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/README.md +7 -6
  2. package/manifest.json +17 -68
  3. package/package.json +6 -1
  4. package/scripts/design-upstream.js +92 -0
  5. package/scripts/doctor.js +0 -24
  6. package/scripts/lib/default-skill-floor.js +5 -1
  7. package/scripts/lib/domains.js +2 -2
  8. package/scripts/lib/recommend.js +1 -3
  9. package/scripts/lib/retired-skills.js +7 -1
  10. package/skills/design/IMPECCABLE-LICENSE.txt +191 -0
  11. package/skills/design/SKILL.md +79 -328
  12. package/skills/design/THIRD_PARTY.md +26 -0
  13. package/skills/design/engine/LICENSE +21 -0
  14. package/skills/design/engine/RUN.md +515 -0
  15. package/skills/design/engine/UPSTREAM.json +4 -0
  16. package/skills/design/engine/assets/app.css +216 -0
  17. package/skills/design/engine/assets/base.css +105 -0
  18. package/skills/design/engine/assets/base.js +37 -0
  19. package/skills/design/engine/assets/charts.js +617 -0
  20. package/skills/design/engine/assets/scenes/stage.css +28 -0
  21. package/skills/design/engine/assets/scenes/stage.js +133 -0
  22. package/skills/design/engine/library/app.json +1327 -0
  23. package/skills/design/engine/library/directions.json +1078 -0
  24. package/skills/design/engine/library/heroes.json +1086 -0
  25. package/skills/design/engine/library/motions.json +92 -0
  26. package/skills/design/engine/library/palettes.json +1485 -0
  27. package/skills/design/engine/library/photos.json +7240 -0
  28. package/skills/design/engine/library/sections.json +4429 -0
  29. package/skills/design/engine/library/sites.json +8350 -0
  30. package/skills/design/engine/library/type.json +2024 -0
  31. package/skills/design/engine/references/app-screens.md +1199 -0
  32. package/skills/design/engine/references/colour.md +141 -0
  33. package/skills/design/engine/references/copy.md +177 -0
  34. package/skills/design/engine/references/critique.md +182 -0
  35. package/skills/design/engine/references/imagery.md +791 -0
  36. package/skills/design/engine/references/layout.md +292 -0
  37. package/skills/design/engine/references/motion.md +980 -0
  38. package/skills/design/engine/references/research.md +356 -0
  39. package/skills/design/engine/references/scenes.md +174 -0
  40. package/skills/design/engine/references/tells.md +115 -0
  41. package/skills/design/engine/references/type.md +170 -0
  42. package/skills/design/engine/scripts/assets.mjs +865 -0
  43. package/skills/design/engine/scripts/draw.mjs +584 -0
  44. package/skills/design/engine/scripts/inspect.mjs +303 -0
  45. package/skills/design/engine/scripts/lib/app-draw.mjs +203 -0
  46. package/skills/design/engine/scripts/lib/cdp.mjs +248 -0
  47. package/skills/design/engine/scripts/lib/probe.mjs +909 -0
  48. package/skills/design/engine/scripts/lib/rules.mjs +243 -0
  49. package/skills/design/engine/scripts/lint.mjs +119 -0
  50. package/skills/design/engine/scripts/scenes.mjs +124 -0
  51. package/skills/design/evals/cases.yaml +35 -46
  52. package/skills/design/references/design-md.md +49 -0
  53. package/skills/design/references/finish-review.md +46 -0
  54. package/skills/design/references/modes.md +51 -0
  55. package/skills/expo/SKILL.md +3 -4
  56. package/skills/marketing/references/landing-copy.md +2 -2
  57. package/skills/react/SKILL.md +2 -2
  58. package/skills/react-native/SKILL.md +3 -3
  59. package/skills/swift-ios/SKILL.md +1 -1
  60. package/skills/ui-engineering/SKILL.md +3 -4
  61. package/skills/ui-engineering/evals/cases.yaml +2 -2
  62. package/skills/variant-explorer/SKILL.md +4 -4
  63. package/skills/variant-explorer/evals/cases.yaml +1 -1
  64. package/targets/clone-bootstrap.mjs +1 -1
  65. package/scripts/lib/design-identity.js +0 -117
  66. package/scripts/lib/starting-point.js +0 -314
  67. package/skills/design/evals/README.md +0 -53
  68. package/skills/design/references/ai-tells.md +0 -75
  69. package/skills/design/references/brand-grounding.md +0 -197
  70. package/skills/design/references/copywriting-frameworks.md +0 -138
  71. package/skills/design/references/design-systems.md +0 -49
  72. package/skills/design/references/inspiration-sources.md +0 -96
  73. package/skills/design/references/landing-anatomy-and-cro.md +0 -202
  74. package/skills/design/references/motion-and-interaction.md +0 -232
  75. package/skills/design/references/research-method.md +0 -154
  76. package/skills/design/references/signature-and-craft.md +0 -148
  77. package/skills/design/references/starting-point.md +0 -75
  78. package/skills/design/references/trends-2026.md +0 -80
  79. package/skills/design/references/visual-system.md +0 -237
  80. package/skills/design/scripts/verify.sh +0 -357
  81. package/skills/design-dna/PROMPT.md +0 -211
  82. package/skills/design-dna/SKILL.md +0 -162
  83. package/skills/design-dna/design-dna.schema.json +0 -230
  84. package/skills/design-dna/evals/README.md +0 -64
  85. package/skills/design-dna/evals/cases.yaml +0 -68
  86. package/skills/design-dna/references/method.md +0 -436
  87. package/skills/design-dna/scripts/emit.py +0 -164
  88. package/skills/design-dna/templates/PROMPT.md.tmpl +0 -42
  89. package/skills/design-dna/templates/SKILL.md.tmpl +0 -42
  90. package/skills/design-dna/templates/check.py.tmpl +0 -143
  91. package/skills/design-loop/SKILL.md +0 -160
  92. package/skills/design-loop/evals/README.md +0 -56
  93. package/skills/design-loop/evals/cases.yaml +0 -60
  94. package/skills/motion-craft/SKILL.md +0 -125
  95. package/skills/motion-craft/evals/cases.yaml +0 -38
  96. package/skills/motion-craft/scripts/verify.sh +0 -75
@@ -1,232 +0,0 @@
1
- # Motion & Interaction
2
-
3
- Motion intent and budget, current-first. CSS is the default engine; reach for a JS library only when CSS cannot express the animation. Deep mechanics (springs, layout animations, `AnimatePresence` internals) live in the external *motion-ui* and *motion-foundations* references (not repo skills) — this skill owns intent + budget and defers mechanics outward.
4
-
5
- ## Purpose gate
6
-
7
- Every animation must do one of three things: **guide** attention, **communicate** state, or **preserve** continuity between views. If it does none, delete it. Decorative motion costs performance budget and attention while adding no information.
8
-
9
- ## Timing & easing tokens
10
-
11
- Define duration and easing as tokens; never hand-tune per element.
12
-
13
- ```css
14
- @theme {
15
- --dur-instant: 80ms; /* checkbox tick, instant feedback */
16
- --dur-fast: 180ms; /* hover, small state changes */
17
- --dur-normal: 280ms; /* entrances, panel open */
18
- --dur-slow: 600ms; /* large hero / staged sequences */
19
- --ease-out: cubic-bezier(0.23, 1, 0.32, 1); /* decelerate; the default for UI */
20
- --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1); /* on-screen movement, A to B */
21
- --ease-drawer: cubic-bezier(0.32, 0.72, 0, 1); /* iOS-like drawer / sheet (Ionic) */
22
- --ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1); /* playful overshoot, sparingly */
23
- }
24
- ```
25
-
26
- **Never `ease-in` on UI.** It starts slow, delaying the exact moment the user is watching most, so
27
- the interface feels sluggish — `ease-out` at 200ms *feels* faster than `ease-in` at 200ms. And the
28
- built-in CSS easings are too weak to read as intentional; the curves above are the ones to reach for.
29
- Need one that is not here? Take it from [easing.dev](https://easing.dev/), do not hand-roll it.
30
-
31
- The choice, in decision order: entering or exiting → `ease-out`; moving on screen → `ease-in-out`;
32
- hover or color → `ease`; constant motion (marquee, progress) → `linear`; unsure → `ease-out`.
33
- `../../motion-craft/SKILL.md` owns the duration ranges, the easing families and the never-animate list, and
34
- its diagnosis table maps the complaint — sluggish, cheap, janky — back to the cause.
35
-
36
- - **Enter vs exit asymmetry:** entrances are slower and softer (`--dur-normal`, `--ease-out`); exits are quicker and quieter (~150ms) so dismissals feel responsive.
37
- - **Press feedback:** `scale(0.97)` on `:active` gives a tactile button without distracting movement.
38
-
39
- ```css
40
- /* Button press — explicit properties, never `transition: all` */
41
- .button {
42
- transition-property: transform, background-color, box-shadow;
43
- transition-duration: 150ms;
44
- transition-timing-function: var(--ease-out);
45
- }
46
- .button:active { transform: scale(0.97); }
47
- ```
48
-
49
- ## Micro-interactions
50
-
51
- CSS-first, state-driven, interruptible (CSS transitions retarget mid-flight when intent changes).
52
-
53
- ```css
54
- /* Hover + focus affordance on a card */
55
- .card {
56
- transition-property: transform, box-shadow;
57
- transition-duration: 180ms;
58
- transition-timing-function: var(--ease-out);
59
- }
60
- .card:hover { transform: translateY(-2px); box-shadow: var(--shadow-card); }
61
- .card:focus-visible { outline: 2px solid var(--color-brand-500); outline-offset: 2px; }
62
- ```
63
-
64
- ```css
65
- /* Icon cross-fade — fade + scale instead of an instant visibility toggle */
66
- .icon-swap { transition: opacity 150ms var(--ease-out), transform 150ms var(--ease-out); }
67
- .icon-swap[data-state="off"] { opacity: 0; transform: scale(0.8); }
68
- ```
69
-
70
- ```css
71
- /* Skeleton shimmer for loading state */
72
- .skeleton {
73
- background: linear-gradient(90deg, oklch(0.9 0 0), oklch(0.95 0 0), oklch(0.9 0 0));
74
- background-size: 200% 100%;
75
- animation: shimmer 1.2s linear infinite;
76
- }
77
- @keyframes shimmer { from { background-position: 200% 0; } to { background-position: -200% 0; } }
78
- ```
79
-
80
- For **optimistic state** (toggle/like), flip the visual immediately on click and reconcile when the request resolves — the UI never waits on the network for feedback.
81
-
82
- ## Scroll-driven, CSS-first
83
-
84
- Native `animation-timeline: view()` and `scroll()` are the default for scroll-linked animation: zero JS, no main-thread scroll handler, no CLS. Use them before any library.
85
-
86
- Guard scroll-driven animation behind a `@supports (animation-timeline: view())` feature query so the fallback is **explicit and visible**, not accidental. Elements start fully visible (`opacity: 1`); only inside the feature query — and only when motion is allowed — do they start hidden and animate in. A browser without scroll-timeline support (or a reduced-motion user) never enters the query, so content is never stuck invisible.
87
-
88
- ```css
89
- /* Default: fully visible. No scroll-timeline support => content is never hidden. */
90
- .reveal { opacity: 1; }
91
-
92
- /* Progressive enhancement: only browsers WITH scroll-timeline opt in. */
93
- @supports (animation-timeline: view()) {
94
- @media (prefers-reduced-motion: no-preference) {
95
- .reveal {
96
- animation: reveal linear both;
97
- animation-timeline: view();
98
- animation-range: entry 0% cover 30%;
99
- }
100
- }
101
- }
102
- @keyframes reveal {
103
- from { opacity: 0; translate: 0 16px; }
104
- to { opacity: 1; translate: 0 0; }
105
- }
106
- ```
107
-
108
- ```css
109
- /* Parallax — element drifts as the page scrolls, driven by the scroll timeline */
110
- @supports (animation-timeline: scroll()) {
111
- @media (prefers-reduced-motion: no-preference) {
112
- .parallax {
113
- animation: drift linear both;
114
- animation-timeline: scroll(root block);
115
- }
116
- }
117
- }
118
- @keyframes drift { to { translate: 0 -40px; } }
119
- ```
120
-
121
- Browser support note (verified June 2026): scroll-driven timelines (`animation-timeline` with `scroll()`/`view()`) now ship in Chromium (Chrome/Edge 115+) and Safari (18+, full support in Safari 26). Firefox has it implemented but still behind a flag (`layout.css.scroll-driven-animations.enabled`), so it is off by default for most users. That gap is exactly why the `@supports (animation-timeline: view())` query is load-bearing, not cosmetic: where the feature is unsupported (Firefox today, older engines), the feature query is skipped entirely and the element renders in its default (visible, un-drifted) state — a graceful, non-broken fallback. Always gate scroll-driven effects behind that `@supports` guard.
122
-
123
- ## Performance budget
124
-
125
- - **Animate `transform`, `opacity`, `filter` only.** These run on the compositor and skip layout/paint.
126
- - **Never animate `width`, `height`, `top`, `left`, `margin`.** They trigger layout on every frame and jank.
127
- - **`will-change` sparingly** — only to fix a first-frame stutter on a compositor-friendly property, and remove it after. Never `will-change: all`.
128
- - **Scroll handlers cost INP.** Prefer scroll-driven CSS; if you must use JS, throttle and keep handlers passive.
129
- - **`content-visibility: auto`** on long offscreen sections skips their rendering work until they approach the viewport.
130
-
131
- ## Accessibility
132
-
133
- Honor `prefers-reduced-motion` at both layers.
134
-
135
- ```css
136
- /* CSS layer — kill non-essential motion globally */
137
- @media (prefers-reduced-motion: reduce) {
138
- *, *::before, *::after {
139
- animation-duration: 0.01ms !important;
140
- animation-iteration-count: 1 !important;
141
- transition-duration: 0.01ms !important;
142
- }
143
- }
144
- ```
145
-
146
- ```ts
147
- // JS layer — branch behavior when motion must be coded
148
- const reduce = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
149
- if (!reduce) {
150
- // run the orchestrated entrance
151
- }
152
- ```
153
-
154
- - **No motion-only meaning:** never convey state (error, success) by movement alone; pair it with color, icon, or text.
155
- - **Pause controls for loops:** any auto-playing or looping animation needs a way to stop it.
156
- - **Vestibular safety:** cut large translate and parallax for reduced-motion users — big movement triggers nausea for some people.
157
-
158
- ## When to escalate to motion/react
159
-
160
- Stay in CSS for hover, press, reveal, and parallax. Escalate to `motion/react` only for what CSS cannot express: orchestrated sequences, layout animations (`layout` prop), and exit animations of unmounting components.
161
-
162
- ```tsx
163
- "use client";
164
- import { motion, AnimatePresence } from "motion/react";
165
- // Use only for orchestration/exit that CSS can't express. Tokens + springs: motion-foundations.
166
-
167
- export function Toast({ open, message }: { open: boolean; message: string }) {
168
- return (
169
- <AnimatePresence>
170
- {open && (
171
- <motion.div
172
- initial={{ opacity: 0, y: 12 }}
173
- animate={{ opacity: 1, y: 0 }}
174
- exit={{ opacity: 0, y: 12 }}
175
- transition={{ duration: 0.18, ease: [0.22, 1, 0.36, 1] }}
176
- role="status"
177
- >
178
- {message}
179
- </motion.div>
180
- )}
181
- </AnimatePresence>
182
- );
183
- }
184
- ```
185
-
186
- Once you are in `motion/react`, defer the mechanics (spring config, variants, `layoutId` shared transitions) to the external *motion-foundations* and *motion-ui* references.
187
-
188
- ## Escalating past the native path
189
-
190
- Native `animation-timeline: view()` covers reveals, progress rails and parallax. Two effects it
191
- cannot express are **pinning** (a section holds still while its content advances) and a
192
- **horizontal pan** driven by vertical scroll. Those need a scroll library, and the improvised
193
- version is always wrong in the same three ways. Escalate deliberately:
194
-
195
- **Never listen to scroll directly.** `window.addEventListener('scroll')` fires off the main
196
- thread's budget, blows INP, and never gets a passive-listener or cleanup story right. The
197
- allowed inputs are `IntersectionObserver`, a scroll-driven CSS timeline, `useScroll()` from
198
- `motion/react`, or GSAP's ScrollTrigger. Nothing else.
199
-
200
- **Sticky stack** (pin a section, advance its layers):
201
-
202
- ```ts
203
- // 'use client' leaf only. One trigger per pinned section, killed on unmount.
204
- const st = ScrollTrigger.create({
205
- trigger: sectionRef.current,
206
- start: "top top", // pin the moment the section's top reaches the viewport top
207
- end: () => `+=${panels.length * window.innerHeight}`,
208
- pin: true,
209
- pinSpacing: true, // without this the next section slides under the pin
210
- scrub: 1, // 1 = follow scroll with a 1s catch-up, not a hard 1:1 jump
211
- invalidateOnRefresh: true, // recompute on resize, or the end point is stale on rotate
212
- });
213
- // cleanup is not optional: return () => st.kill();
214
- ```
215
-
216
- **Horizontal pan** is the same trigger with `end: () => "+=" + track.scrollWidth` and the
217
- track moved via `x`, not `left` — `transform` is compositor-only, `left` triggers layout.
218
-
219
- Both are opt-in above a motion budget, both stay inside
220
- `@media (prefers-reduced-motion: no-preference)`, and both collapse to a plain vertical stack
221
- below `768px` rather than pinning on a phone.
222
-
223
- A **pre-rendered video scrubbed by scroll** (a camera flying through scenes, Apple-style) is not a
224
- timeline animation. The clips, the seams between them and the scrub engine are
225
- `../../scroll-film/SKILL.md`.
226
-
227
- ## See Also
228
-
229
- - `visual-system.md` — the easing and duration tokens these animations consume.
230
- - *motion-ui* — production motion patterns and library mechanics (external reference, not a repo skill).
231
- - *motion-foundations* — spring physics and timing theory (external reference, not a repo skill).
232
- - `../../nextjs/SKILL.md` — Client vs Server Component boundaries for animated UI.
@@ -1,154 +0,0 @@
1
- # Research-First Design Method
2
-
3
- The engine that keeps design output current and non-generic. Run it before you prescribe type, color, layout, or copy — every time.
4
-
5
- ## Why re-research every project
6
-
7
- - **Trends churn quarterly.** What read as premium 18 months ago (neumorphism, heavy glassmorphism, blob backgrounds) now reads as dated. The reference set has a short half-life.
8
- - **Model taste skews to the AI-template median.** Your built-in aesthetic prior is the average of every scraped landing page — purple→blue gradients, centered hero over atmospheric mesh, oversized cards. That average is the slop you must escape.
9
- - **Competitors moved.** The benchmark is the current best work in *this* domain, not last year's. A dev tool that looked sharp against 2024 peers looks soft against 2026 peers.
10
- - **The domain dictates the reference set.** A fintech dashboard, a developer CLI, and a DTC skincare store have nothing in common. Pull references from the right neighborhood, not a generic "good design" bucket.
11
-
12
- Your built-in aesthetic prior is the problem this protocol fixes. Treat your first instinct as a hypothesis to be corrected by evidence, not as the answer.
13
-
14
- ## The loop
15
-
16
- 1. **Define 2–3 reference archetypes** from the DIRECTION BRIEF in `../SKILL.md`. Name them concretely: "Linear-grade dev tool, dark, type-led" beats "modern SaaS".
17
- 2. **WebSearch award galleries + tier-1 product sites.** Query the galleries by domain and year; query named competitors by page.
18
- 3. **WebFetch 3–5 exemplars,** prompting each for type, color, layout, motion, and copy voice. Demand concrete values, not adjectives.
19
- 4. **Extract a pattern table** — the shared moves (what every exemplar does) and the differentiators (where they diverge). Shared moves are table stakes; differentiators are where you choose.
20
- 5. **Synthesize a one-paragraph DESIGN DIRECTION** with citations: which URL contributed which decision.
21
- 6. **Build** against the direction.
22
- 7. **Re-check against references in QA** — open the exemplars side by side and confirm you matched the bar (density, type, motion restraint), not the pixels.
23
-
24
- ```text
25
- WebSearch: "best <domain> landing page 2026 site:awwwards.com OR site:godly.website"
26
- WebSearch: "<competitor> pricing page design"
27
- WebFetch(url, "Extract: typeface pairing, color palette (approx OKLCH/hex),
28
- layout system (grid/bento/asymmetry), motion (what animates, on what trigger),
29
- hero copy voice. List concrete details, not adjectives.")
30
- ```
31
-
32
- If WebSearch/WebFetch tools are unavailable in the current run, state that explicitly to the user, fall back to your strongest current knowledge of the named tier-1 sites, and flag the output as un-verified so it can be re-checked.
33
-
34
- ### What to extract per exemplar
35
-
36
- Force every fetch to produce concrete, comparable data. Vague notes ("clean", "modern") are useless; you cannot build from an adjective.
37
-
38
- | Field | Capture | Example |
39
- | --- | --- | --- |
40
- | Typeface pairing | display + text faces, weights | Geist Semibold / Inter Regular |
41
- | Type scale | base size + ratio | 16px base, ~1.25 ratio |
42
- | Palette | bg / fg / accent in OKLCH or hex | near-black bg, single blue accent |
43
- | Layout | grid system, max-width, measure | centered hero, bento below, 1024px |
44
- | Motion | what animates, on what trigger, duration | bento cells reveal on scroll, ~280ms |
45
- | Copy voice | sentence length, hype level, verbs | short, no hype, imperative |
46
- | Hero structure | what is shown above the fold | terminal recording + one CTA |
47
-
48
- ### Time-box the loop
49
-
50
- Research is a means, not the deliverable. Spend ~15–25 minutes: 3–5 exemplars, one pattern table, one synthesis paragraph. If you are still browsing after 30 minutes you are procrastinating the build — commit to a direction and start.
51
-
52
- ## Source map
53
-
54
- | Source | Mine for |
55
- | --- | --- |
56
- | awwwards.com | Bold direction, motion, art direction |
57
- | godly.website | Current premium web aesthetics |
58
- | land-book.com | Landing-page structure + section order |
59
- | mobbin.com | Real app UI flows and patterns |
60
- | Refactoring UI | Spacing, hierarchy, color rules |
61
- | Linear | Restraint, dark UI, dense product surfaces |
62
- | Stripe | Docs + marketing balance, gradients done right |
63
- | Vercel | Type-led minimalism, dev-tool voice |
64
- | Cursor / Resend | Dev-tool landing conventions |
65
-
66
- Pick sources by domain. For a developer tool, weight Linear / Vercel / Cursor / Resend heavily and skip the expressive Awwwards entries. For an editorial or portfolio piece, invert that weighting.
67
-
68
- ## Synthesis template
69
-
70
- Fill this block before writing markup. It is the contract the build must satisfy and the artifact QA checks against.
71
-
72
- ```text
73
- DESIGN DIRECTION
74
- Archetype ...... <e.g. "Linear-grade dev tool, dark, type-led">
75
- Type pairing ... display=<face> / text=<face>, scale ratio <1.25>
76
- Palette ........ bg/fg/brand/accent in OKLCH (list values)
77
- Layout ......... <12-col | bento | asymmetric editorial>, max-width <px>, measure <ch>
78
- Motion budget .. <reveals on entry only | none | expressive>, timings
79
- Copy voice ..... <direct/compressed | warm | technical>; one-line value prop
80
- Citations ...... <url 1>, <url 2>, <url 3> (what each contributed)
81
- ```
82
-
83
- ## Worked example
84
-
85
- Brief: a developer-tool landing page for **Driftway**, a fictional CLI that deploys preview environments from a Git branch in one command. Audience: backend and platform engineers. Tone: technical, dense, quiet.
86
-
87
- References fetched and what each contributed:
88
-
89
- - `https://linear.app` — dark, near-monochrome surface; tight type with a single accent; restraint as the whole aesthetic.
90
- - `https://vercel.com` — type-led hero with the product (a terminal) shown immediately; minimal motion; high-contrast mono code blocks.
91
- - `https://resend.com` — dev-tool voice in copy (verbs, no hype); a clean bento for feature → benefit; annual-default pricing.
92
-
93
- Extracted pattern table:
94
-
95
- | Dimension | Shared move | Differentiator chosen |
96
- | --- | --- | --- |
97
- | Type | One sans display + mono for code | Geist display, Geist Mono for CLI snippets |
98
- | Color | Dark bg, one cool accent | bg near-black, single blue brand accent |
99
- | Layout | Hero shows the product, then bento proof | Terminal recording as the hero visual |
100
- | Motion | Subtle entry reveals only | Scroll-reveal on bento cells, ≤ 280ms |
101
- | Copy | Outcome + "no X" phrasing | "Preview every branch — no staging queue" |
102
-
103
- Resulting filled direction (token values match the `@theme` block in `visual-system.md`):
104
-
105
- ```text
106
- DESIGN DIRECTION
107
- Archetype ...... Linear-grade dev tool, dark, type-led, terminal-forward
108
- Type pairing ... display=Geist / text=Inter (mono=Geist Mono for code), scale ratio 1.25
109
- Palette ........ bg=oklch(0.17 0.01 256) fg=oklch(0.96 0.01 256)
110
- brand=oklch(0.62 0.19 256) accent=oklch(0.78 0.13 256)
111
- Layout ......... asymmetric bento under a centered hero, max-width 1024px, measure 65ch
112
- Motion budget .. entry reveals only via animation-timeline: view(), enter 280ms / exit 150ms
113
- Copy voice ..... direct, compressed, technical; value prop = "Preview every branch — no staging queue"
114
- Citations ...... linear.app (restraint + dark surface), vercel.com (product-forward hero),
115
- resend.com (dev voice + bento + annual pricing)
116
- ```
117
-
118
- That direction now drives `visual-system.md` (tokens), `landing-anatomy-and-cro.md` (section order), and `copywriting-frameworks.md` (voice) with zero guesswork.
119
-
120
- ## Anti-pattern
121
-
122
- Copying a reference pixel-for-pixel reproduces someone else's product constraints, not yours — and it shows. Extract *principles* (restraint, product-forward hero, one accent) and re-derive the specifics for your domain.
123
-
124
- ```text
125
- Bad — Clone Linear's exact gradient, spacing, and copy onto a skincare store.
126
- Good — Take Linear's PRINCIPLE (radical restraint, one accent, product-forward)
127
- and re-derive a warm, editorial skincare palette + layout from it.
128
- ```
129
-
130
- A second failure mode is **research theater**: fetching five sites, then ignoring them and building your default gradient hero anyway. The synthesis paragraph and its citations are the guardrail — if the built page does not visibly trace back to a cited decision, the research did not happen. In QA, open the exemplars beside the result and confirm each major decision (type, palette, layout, motion restraint) has a source.
131
-
132
- ## Feeding the result into the build
133
-
134
- The filled DESIGN DIRECTION block is not a document for humans; it is the input to the rest of the skill:
135
-
136
- - **Palette + type + radius + shadow** → become the `@theme` tokens in `visual-system.md`. Do not invent new values at build time; promote the direction's values into tokens verbatim.
137
- - **Layout + section order** → drive the section stack in `landing-anatomy-and-cro.md`. The archetype decides whether you lead with a product shot (dev tool) or an editorial headline (portfolio).
138
- - **Copy voice + value prop** → seed the VOICE block and headline work in `copywriting-frameworks.md`.
139
- - **Motion budget** → sets the timing tokens and the reveal-or-not decision in `motion-and-interaction.md`.
140
-
141
- When the direction changes mid-project (new competitor, pivot), re-run the loop rather than patching the old tokens — a stale direction silently reintroduces the generic default you escaped.
142
-
143
- ## See Also
144
-
145
- - `visual-system.md` — turn the filled direction into tokens.
146
- - `../../nextjs/SKILL.md` — implement the chosen direction on the App Router stack.
147
- - *frontend-design-direction* — product-domain direction judgment (external reference, not a repo skill).
148
-
149
- ## Where to look
150
-
151
- `inspiration-sources.md` is the dated registry of where to browse: whole pages to beat, SaaS and
152
- conversion surfaces, real product flows (Mobbin, Page Flows — the bucket most people skip), single
153
- patterns like footers and empty states, and the design systems that are specification rather than
154
- inspiration. Extract principles, not pixels, and come back with a named page rather than a gallery.
@@ -1,148 +0,0 @@
1
- # Signature & Craft — manufacturing the distinctive idea, then the finish that sells it
2
-
3
- A page that obeys every constraint in this skill and still feels generic is the default failure mode.
4
- Constraints get you to *competent*. They do not get you to *premium*. The difference is a **visual
5
- concept** — one defensible idea the whole surface commits to — plus the **craft moves** that make the
6
- rendered artifact read as authored rather than assembled. This reference is the method for both. Use it
7
- whenever the output has to be genuinely good, not merely compliant.
8
-
9
- ## Why compliant output still scores ~7.7
10
-
11
- The checklist tells you the page *ships*. It cannot tell you the page is *good*, because every defect it
12
- catches is an absence (no missing `<h1>`, no `transition: all`, contrast passes). Premium is a presence:
13
- a point of view. The common shortfalls that keep correct work at "competent" are predictable — fix these
14
- and the output moves up a band:
15
-
16
- | Symptom of generic output | Root cause | The move |
17
- | --- | --- | --- |
18
- | "Looks like a nice template" | No visual concept; defaults filled every slot | Commit to ONE signature idea (below) |
19
- | Tonally flat — everything medium-sized | No scale contrast; safe type ramp | Force a dominant element 3–5× the body (below) |
20
- | Sections blur into one stripe | No rhythm; identical `py`, identical card grids | Vary section format + background + density (below) |
21
- | Hero is a centered headline + gradient | The default the model reaches for under-specified | Show the product doing the job; earn the layout |
22
- | Correct but forgettable color | Brand hue used like everyone's brand hue | One owned accent move, applied with restraint |
23
- | Everything is rounded cards on white | One container idiom repeated | Mix surface treatments; let some content breathe edge-to-edge |
24
-
25
- ## Step 1 — Choose a visual concept (do this before any markup)
26
-
27
- A visual concept is a single sentence the entire page can be checked against. It is NOT a color or a font;
28
- it is an organizing idea that dictates layout, type, color, motion, and imagery together. Write it down,
29
- then make every section answer to it.
30
-
31
- > Concept = `[adjective of feeling]` + `[structural metaphor]` for `[audience doing job]`.
32
- > e.g. "Quiet, instrument-panel precision for ops engineers who live in this all day."
33
- > e.g. "Confident editorial broadsheet for a brand that wants to feel like a publication, not an app."
34
- > e.g. "Tactile, mechanical-keyboard heft for a dev tool that should feel engineered."
35
-
36
- Pick the concept from the DIRECTION BRIEF + brand study + research exemplars — never from your prior. If
37
- you cannot say in one sentence what makes this surface different from the median SaaS page, you have not
38
- chosen a concept yet, and the output will default to generic.
39
-
40
- ## Step 2 — Manufacture the signature element (the "ONE idea")
41
-
42
- Every premium page has one element you would describe first to a friend. The brief asks for it; this is how
43
- to actually generate it instead of defaulting to a gradient. Pick **exactly one** primary signature (a
44
- second, quieter echo is fine; three competing signatures is noise). Choose from this vocabulary, biased by
45
- the concept and domain:
46
-
47
- - **A hero that demonstrates, not describes** — the product mid-task: a real terminal session, a live
48
- chart updating, an actual diff, a populated dashboard. The single highest-leverage move for dev tools and
49
- SaaS; it passes the 5s test by *showing* the value instead of claiming it.
50
- - **An owned type moment** — one oversized display setting (a 96–160px headline, a tight-tracked all-caps
51
- eyebrow, a serif/grotesk pairing with real contrast) that no template ships by default.
52
- - **A structural signature** — an unexpected but legible layout: a horizontal-scroll feature rail, an
53
- asymmetric split hero, a numbered editorial index, a sticky side-rail that tracks the section.
54
- - **A material signature** — a consistent, restrained physical treatment: hairline grid lines, a single
55
- grain/noise pass, a duotone photographic style, a precise mono-spaced data aesthetic.
56
- - **A motion signature** — one purposeful move that recurs (a scroll-driven reveal cadence, a hover that
57
- uncovers state) — only if it earns its INP/CLS budget.
58
- - **A data/proof signature** — a real number rendered as the visual centerpiece (a live metric, a benchmark
59
- bar, a before/after). Strongest when the proof IS the product's claim.
60
-
61
- Rule: the signature must be *true to the product*. A fintech dashboard's signature is precision and density;
62
- a creative tool's is expression. A signature borrowed from the wrong domain reads as costume. Cite which
63
- research exemplar inspired the move (e.g. "feature rail per linear.app/changelog") so it is grounded, not
64
- invented.
65
-
66
- ## Step 3 — Force scale contrast (the fastest fix for "flat")
67
-
68
- Generic pages are tonally flat: the headline, the section titles, and the body are all within ~1.5× of each
69
- other, so nothing dominates and the eye has nowhere to land. Premium pages have a **dramatic range**.
70
-
71
- - Establish a clear **hero dominant**: the largest single element on the page (a headline or product visual)
72
- should be **3–5× the body size**, not 2×. Commit to it.
73
- - Then **demote ruthlessly**: eyebrows, labels, and metadata go *smaller and quieter* (13–14px, muted,
74
- tracked) than you instinctively want. Contrast is created by the small things being genuinely small.
75
- - One **focal point per viewport**. If two things compete for "biggest", neither wins — shrink one.
76
- - Apply the same logic to weight (one heavy display weight against a regular body), and to color (the 10%
77
- accent appears once or twice per viewport, never spread thin).
78
-
79
- If a section feels flat, the fix is almost always *more* contrast, not more elements.
80
-
81
- ## Step 4 — Give the page rhythm (sections must not blur)
82
-
83
- A landing page that is ten identical white sections with `py-24` and a 3-up card grid reads as one long
84
- stripe. Authored pages have a **beat**: the eye is paced. Vary, section to section, at least one of:
85
-
86
- - **Format** — full-bleed vs. contained; centered vs. asymmetric; grid vs. single statement; media-left vs.
87
- media-right (alternate, don't repeat one side).
88
- - **Background** — alternate base / subtly tinted / inverted (a dark section between two light ones is a
89
- classic rhythm device and creates a natural CTA anchor).
90
- - **Density** — a breathing, near-empty statement section after a dense feature grid resets the eye.
91
- - **Container idiom** — don't make *everything* a bordered card on white. Let a hero visual run edge-to-edge;
92
- let one statement sit in open space with no container at all.
93
-
94
- Spacing rhythm is load-bearing here: section padding should step on the scale (e.g. 64 → 96px), and the
95
- *gap between sections* should be visibly larger than the gap *within* a section, so groups read as groups.
96
- A flat `py` on every section is the tell of generated output.
97
-
98
- ## Step 5 — The craft finish (compounding micro-decisions)
99
-
100
- These are in the SKILL's "Premium details" table; apply them as a deliberate pass, not by accident:
101
-
102
- - Concentric radius (`outer = inner + padding`); never same-radius nesting.
103
- - Layered transparent OKLCH shadows; hairline `fg/10` borders for separation, shadow only for true float.
104
- - `text-wrap: balance` on headings, `pretty` on body; `tabular-nums` on any changing number/price.
105
- - Optical alignment: trust the eye over the math for icon centering and cap-height padding.
106
- - Restraint: glass on floating surfaces only; gradient as seasoning on one surface; one accent, used rarely.
107
-
108
- ## Step 6 — Self-critique before you claim done (the senior-designer pass)
109
-
110
- Before shipping, interrogate your own output with the questions a senior designer would ask in a crit. Answer
111
- them honestly in your own head (or out loud to the user); if any answer is weak, iterate before delivering.
112
-
113
- 1. **What is the one idea here?** If you cannot name it in a sentence, there is no concept — go to Step 1.
114
- 2. **Would this place on Awwwards / Godly, or just pass review?** If "just pass", it is at ~7; name the
115
- single most generic element and replace it.
116
- 3. **What's the most generic thing on this page right now?** (Usually: the hero, the gradient, the 3-up card
117
- grid, or the stock-feeling copy.) Fix that one thing first — it has the highest leverage.
118
- 4. **Where does the eye land first, and is that the thing that should win?** If not, fix scale contrast.
119
- 5. **If I deleted the logo, would anyone know whose product this is?** If not, the concept/signature is too
120
- timid.
121
- 6. **Does every section earn its place, or is one there out of habit?** Cut the weakest section entirely;
122
- removal is a design decision.
123
- 7. **Is the copy carrying a specific, verifiable claim, or vibes?** Swap one vague benefit for a concrete,
124
- quantified one.
125
-
126
- The point of the pass is not to pass it — it is to make at least one concrete change as a result. A surface
127
- that survives this crit unchanged on the first try usually means the crit was not honest.
128
-
129
- ## Worked example — generic → signature (dev-tool hero)
130
-
131
- **Generic (≈7, competent):** centered `<h1>` "Ship faster with our developer platform", subhead, two buttons,
132
- purple→blue gradient blob behind it, 3-up feature cards below, all sections `py-24` on white.
133
-
134
- **Signature (≈9, premium):**
135
- - *Concept:* "Engineered precision — this tool should feel like instrumentation."
136
- - *Signature element:* the hero IS a live, syntax-highlighted terminal session running the actual command,
137
- output streaming — the product demonstrates the value (Step 2, "demonstrate not describe").
138
- - *Scale contrast:* a tight-tracked 13px mono eyebrow ("v2.4 — now with preview environments"), a 72px
139
- display headline with one concrete claim ("Spin up a preview in 4s"), demoted everywhere else (Step 3).
140
- - *Rhythm:* light hero → dark proof section with a real benchmark bar → light asymmetric feature split
141
- (media alternating sides) → dark final CTA (Step 4).
142
- - *Finish:* hairline grid lines as the material signature, mono `tabular-nums` on the benchmark, concentric
143
- radius on the terminal chrome, one accent used only on the active prompt and the primary CTA (Step 5).
144
- - *Crit result:* "the live terminal" is the one idea; logo-removed it still reads as this product; eye lands
145
- on the streaming output, which is the value (Step 6 passed honestly).
146
-
147
- Same constraints, same tokens, same stack — the difference is concept + signature + contrast + rhythm +
148
- honest crit. That is the gap between 7.7 and premium.
@@ -1,75 +0,0 @@
1
- # Reference — proposing a starting point
2
-
3
- Three places promise to propose one: `../../design-loop/SKILL.md` phase 1 when the user says *skip*,
4
- the closing line of `brand-grounding.md` when a visual dimension has no direction, and
5
- `../../design-dna/SKILL.md`'s REUSE mode. This file is what they propose *from*. Without it the
6
- fallback is your own prior, which is the AI-template median — the thing the whole area exists to escape.
7
-
8
- ## 0. What the project already owns wins
9
-
10
- **Look before you offer.** Run it; do not reason about it:
11
-
12
- ```bash
13
- npx @ericrisco/rsc doctor --json # read `designStartingPoint`
14
- ```
15
-
16
- | State | What it means | What you do |
17
- | --- | --- | --- |
18
- | `owned` | An identity article or at least one legible style record exists | Propose **that**, by name, first. Offer nothing external until the user rejects it. More than one record → all of them are candidates, ordered as reported. Never pick one silently. |
19
- | `none` | Looked in both scopes, found nothing | Go to §1. |
20
- | `inconclusive` | Something could not be read | Say what, and ask for another route to it. **Do not propose past a blind spot** — a proposal made without looking is the defect this file exists to remove. |
21
-
22
- If the owned identity **contradicts** what the user is now asking for, name the conflicting rule and let
23
- them decide which wins. Same rule the loop's preflight already applies to a bar from outside.
24
-
25
- A record that `doctor` reports with a pair below its contrast floor is not offered as a starting point.
26
-
27
- ## 1. What are you building → which bar
28
-
29
- At most **three** candidates. Each one gets a name, one line on why it fits *this* product, and one line
30
- on when it would be the wrong choice. Then **wait**. No answer → take the most demanding one and say so.
31
-
32
- Sources are in `inspiration-sources.md`; the tier-1 set and the dated-looking list are in
33
- `trends-2026.md`. **Only propose what you can actually open** — that registry marks several sources as
34
- bot-blocked, and a bar that cannot be fetched dies in the loop's preflight.
35
-
36
- | Building | Candidate bars | Wrong choice when |
37
- | --- | --- | --- |
38
- | SaaS marketing | Stripe · [SaaS Landing Page](https://saaslandingpage.com) browsed by section · Linear | The product is a daily tool, not a purchase decision — a marketing skin on a workhorse |
39
- | Dev tool | Linear · Vercel · Resend · [Primer](https://primer.style) | The audience is not technical: dev-tool restraint reads as unfinished to them |
40
- | Dashboard / internal tool | [Carbon](https://carbondesignsystem.com) · [Polaris](https://polaris.shopify.com) · [Mobbin](https://mobbin.com) flows | It is a landing page with a chart on it — density is not the job |
41
- | Portfolio / editorial | [Awwwards](https://www.awwwards.com) · [Recent](https://recent.design) · [One Page Love](https://onepagelove.com) | Anything with a conversion target: award craft routinely costs LCP and the 5s test |
42
- | E-commerce | [Minimal Gallery](https://minimal.gallery) for restraint · [Nicely Done](https://nicelydone.club) for real product surfaces | The catalogue is huge and the real problem is search and filtering, not the hero |
43
- | Docs | [Stripe docs](https://docs.stripe.com) · [Material 3](https://m3.material.io) on states | Reading is not the job — it is a reference table, so density beats calm |
44
-
45
- Nothing here fits what they are building? **Say so and interview.** Do not stretch the nearest row: a bar
46
- chosen because it was closest is the vague bar that makes the loop approve everything on round one.
47
-
48
- ## 2. A proposal is not an answer
49
-
50
- 1. **Open the reference.** No value is proposed from a page you did not fetch. Blocked → say so, pick
51
- another. Never substitute a description from memory.
52
- 2. **Measure it** — the loop's teardown already does this and writes 5 to 7 mechanisms. Those measured
53
- values *are* the researched default this file was missing. They are not invented, and they come from
54
- a page that already ships.
55
- 3. **Check colour before writing it.** Any text pairing must measure **≥ 4.5:1** (≥ 3:1 for large text
56
- and UI). Below that, it is **not proposed** — not proposed-with-a-warning.
57
- 4. **Write it marked `propuesto`, naming the reference it came from.** Never as a confirmed value.
58
- 5. A dimension that is proposed and not yet confirmed **does not count as complete** against
59
- `brand-grounding.md`'s checklist. The hard STOP stays up for it. Otherwise the prefill becomes the
60
- way to cross the gate with nobody having confirmed anything.
61
- 6. Only what the user confirms becomes the project's identity.
62
-
63
- ## 3. The base is the floor, not the concept
64
-
65
- A starting point gets you a defensible floor in one exchange. It does **not** satisfy the ONE signature
66
- element (`signature-and-craft.md` §2), and it never will: every project that picked the same bar would
67
- converge on the same page. If the only thing making this surface distinctive is the bar it started from,
68
- there is no concept yet.
69
-
70
- ## See Also
71
-
72
- - `inspiration-sources.md` — the source registry, dated, with the bot-blocked entries marked.
73
- - `trends-2026.md` — the tier-1 set, and what currently reads as a template.
74
- - `brand-grounding.md` — the checklist this fills in, and the STOP it does not lift.
75
- - `signature-and-craft.md` — the part a starting point cannot give you.