@autono/open-pages 0.1.0 → 0.4.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 (73) hide show
  1. package/README.md +8 -5
  2. package/dist/{build-TP72kiw7.js → build-L50pau9v.js} +3 -3
  3. package/dist/cli/bin.js +4 -4
  4. package/dist/{config-L0IbktJ0.js → config-CDUdFE8N.js} +34 -7
  5. package/dist/{dev-I2IyEh5W.js → dev-CzJYXFOO.js} +2 -2
  6. package/dist/export-BsK6OCpc.js +4 -0
  7. package/dist/{export-ic28osQP.js → export-DbVwSmKW.js} +10 -3
  8. package/dist/{open-pages-plugin-D_DN_zjh.js → open-pages-plugin-C0poXLsx.js} +52 -7
  9. package/dist/{preview-BrDuvgAN.js → preview-CPufRmuj.js} +2 -2
  10. package/dist/vite/index.js +2 -2
  11. package/package.json +6 -6
  12. package/skills/apply-comments/SKILL.md +4 -4
  13. package/skills/create-page/SKILL.md +26 -8
  14. package/skills/create-theme/SKILL.md +137 -150
  15. package/skills/current-page/SKILL.md +1 -1
  16. package/skills/page-authoring/SKILL.md +97 -42
  17. package/skills/page-authoring/references/interactivity.md +71 -23
  18. package/skills/page-authoring/references/layout-and-responsive.md +38 -17
  19. package/skills/page-authoring/references/typography-and-color.md +50 -32
  20. package/skills/shadcn/SKILL.md +277 -0
  21. package/skills/shadcn/assets/shadcn-small.png +0 -0
  22. package/skills/shadcn/assets/shadcn.png +0 -0
  23. package/skills/shadcn/cli.md +290 -0
  24. package/skills/shadcn/customization.md +209 -0
  25. package/skills/shadcn/mcp.md +105 -0
  26. package/skills/shadcn/registry.md +277 -0
  27. package/skills/shadcn/rules/base-vs-radix.md +306 -0
  28. package/skills/shadcn/rules/chat.md +224 -0
  29. package/skills/shadcn/rules/composition.md +213 -0
  30. package/skills/shadcn/rules/forms.md +192 -0
  31. package/skills/shadcn/rules/icons.md +101 -0
  32. package/skills/shadcn/rules/styling.md +185 -0
  33. package/src/app/components/asset-view.tsx +11 -11
  34. package/src/app/components/command/command-menu.tsx +6 -6
  35. package/src/app/components/command/command.tsx +2 -2
  36. package/src/app/components/command/home-command-menu.tsx +2 -2
  37. package/src/app/components/icon-tooltip.tsx +1 -1
  38. package/src/app/components/language-toggle.tsx +7 -7
  39. package/src/app/components/sidebar/folder-item.tsx +5 -5
  40. package/src/app/components/sidebar/icon-picker.tsx +3 -3
  41. package/src/app/components/sidebar/sidebar-footer.tsx +4 -4
  42. package/src/app/components/sidebar/sidebar.tsx +6 -6
  43. package/src/app/components/theme-toggle.tsx +6 -6
  44. package/src/app/components/themes/theme-detail.tsx +4 -4
  45. package/src/app/components/themes/themes-gallery.tsx +1 -1
  46. package/src/app/components/ui/badge.tsx +1 -1
  47. package/src/app/components/ui/button.tsx +1 -1
  48. package/src/app/components/ui/card.tsx +1 -1
  49. package/src/app/components/ui/context-menu.tsx +1 -1
  50. package/src/app/components/ui/dialog.tsx +2 -2
  51. package/src/app/components/ui/dropdown-menu.tsx +1 -1
  52. package/src/app/components/ui/input.tsx +1 -1
  53. package/src/app/components/ui/label.tsx +1 -1
  54. package/src/app/components/ui/popover.tsx +1 -1
  55. package/src/app/components/ui/progress.tsx +1 -1
  56. package/src/app/components/ui/scroll-area.tsx +1 -1
  57. package/src/app/components/ui/select.tsx +1 -1
  58. package/src/app/components/ui/separator.tsx +1 -1
  59. package/src/app/components/ui/slider.tsx +1 -1
  60. package/src/app/components/ui/tabs.tsx +1 -1
  61. package/src/app/components/ui/textarea.tsx +1 -1
  62. package/src/app/components/ui/toggle-group.tsx +2 -2
  63. package/src/app/components/ui/toggle.tsx +1 -1
  64. package/src/app/components/ui/tooltip.tsx +1 -1
  65. package/src/app/frame/main.tsx +3 -1
  66. package/src/app/lib/themes.ts +1 -0
  67. package/src/app/lib/use-restart-server.ts +1 -1
  68. package/src/app/routes/home-shell.tsx +7 -7
  69. package/src/app/routes/home.tsx +5 -5
  70. package/src/app/routes/page.tsx +2 -2
  71. package/src/app/routes/themes.tsx +1 -1
  72. package/src/app/virtual.d.ts +3 -0
  73. package/dist/export-B-kBRWB1.js +0 -4
@@ -1,49 +1,106 @@
1
1
  ---
2
2
  name: create-theme
3
- description: Use this skill when the user wants to create, draft, author, or extract a page theme in this open-pages repo. Triggers on phrases like "create a theme", "make a theme called X", "extract a theme from <page>", "build a design system from these screenshots", "match our brand". Produces two paired files under `themes/` — `<id>.md` (palette, typography, layout, fixed components) and `<id>.demo.tsx` (a runnable demo page the workspace's Themes panel previews live). Do NOT use for editing real pages — only for authoring the theme bundle.
3
+ description: Use this skill when the user wants to create, draft, author, or extract a theme in this open-pages repo. Triggers on phrases like "create a theme", "make a theme called X", "extract a theme from <page>", "match our brand", "build a design system from these screenshots", "apply this shadcn preset". Produces a three-file bundle under `themes/` — `<id>.md` (direction, fonts, component notes, token table), `<id>.css` (the shadcn token overrides), and `<id>.demo.tsx` (a demo page composed from `ui/` components that the workspace's Themes panel previews live). Do NOT use for editing real pages — only for authoring the theme bundle.
4
4
  ---
5
5
 
6
- # Create a page theme
6
+ # Create a theme
7
7
 
8
- This skill produces a **theme bundle** under `themes/`: two paired files that together describe a reusable visual identity for web pages.
8
+ A theme is a **token set**. Every workspace ships the full shadcn/ui set under `ui/`, and every component reads its colors, radius, and fonts from the CSS variables in `styles/globals.css` (`--background`, `--primary`, `--radius`, …). A theme overrides those variables; every component and every token-styled page restyles at once. Nothing is copied into pages.
9
9
 
10
- 1. `themes/<id>.md` — agent-facing documentation: palette, typography, layout, fixed components (nav, hero, section wrapper, buttons, card, footer). This is what `create-page` reads when an author picks the theme.
11
- 2. `themes/<id>.demo.tsx` — a runnable demo page (same module shape as `pages/<id>/index.tsx`: **one default-exported component**) that shows the theme on a single scrolling page. The workspace's Themes panel renders it live, exactly like a real page.
10
+ The bundle is three files sharing one stem under `themes/`:
12
11
 
13
- Both files share the same stem so the runtime can pair them automatically.
12
+ 1. `themes/<id>.md` — agent-facing direction: aesthetic, fonts, how to use the components in this theme, and a table of token → value. This is what `create-page` reads when an author picks the theme.
13
+ 2. `themes/<id>.css` — **only** `:root { … }` and `.dark { … }` blocks overriding the shadcn tokens (plus an optional Google Fonts `@import url(…)` at the very top). No `@theme` block, no Tailwind import, no selectors beyond those two.
14
+ 3. `themes/<id>.demo.tsx` — a runnable page module (same shape as `pages/<id>/index.tsx`, **one default-exported component**) composed from `@/ui/*` components so the tokens are shown on real parts. The Themes panel renders it with `<id>.css` injected automatically; the demo does not set `meta.theme`.
14
15
 
15
- The theme markdown is authoring-time direction — `create-page` copies its palette, utilities, and components into a real page's source. The demo `.tsx` is a self-contained preview, not a real page — it does not appear in the pages list.
16
+ A page opts in with `meta.theme: '<id>'`; the runtime injects `themes/<id>.css` into that page's preview frame and into its export.
16
17
 
17
- You only write `themes/<id>.md` and `themes/<id>.demo.tsx`. Never modify real pages or configuration. The styling rules and web defaults that themes override live in the **`page-authoring`** skill — read it before writing the theme so your overrides are stated explicitly.
18
+ You only write the three theme files. Never modify pages, `ui/`, `styles/globals.css`, or configuration. The token names and how pages consume them live in the **`page-authoring`** skill (`references/typography-and-color.md`) — read it first. Component props and variants: the **`shadcn`** skill.
18
19
 
19
20
  ## Step 1 — Identify the input source
20
21
 
21
- A theme can be derived from any combination of three input shapes:
22
+ A theme can be derived from any combination of:
22
23
 
23
- - **Image references** — paths or URLs to screenshots, mood-board images, brand assets.
24
+ - **A shadcn preset** — a code or URL from https://ui.shadcn.com/create. `npx shadcn@latest preset decode <code>` prints its tokens; or run `npx shadcn@latest apply <code> --only theme,font` in a scratch copy and lift the resulting `:root`/`.dark` values. Never run `apply` against the workspace's `styles/globals.css` directly — that changes the default for every page.
25
+ - **Image references / brand guidelines** — paths or URLs to screenshots, mood boards, logo files, a brand PDF. You will translate them into OKLCH tokens.
24
26
  - **Free-text description** — prose describing the desired palette, weight, feel.
25
- - **An existing page** — `pages/<id>/index.tsx` whose visual identity should be lifted out into a reusable theme.
27
+ - **An existing page** — `pages/<id>/index.tsx` whose look should become reusable.
26
28
 
27
- If the user's original message already specifies the inputs unambiguously, skip the question and proceed. Otherwise call `AskUserQuestion` (multi-select) so they can pick one or more sources, and ask follow-ups (paths, page id, prose) only as needed.
29
+ If the user's original message already specifies the inputs unambiguously, skip the question and proceed. Otherwise call `AskUserQuestion` (multi-select) so they can pick one or more sources, and ask follow-ups (paths, preset code, page id, prose) only as needed.
28
30
 
29
31
  ## Step 2 — Gather raw inputs
30
32
 
31
- - **Images**: read each path with the `Read` tool (it accepts images). Note dominant colors as hex, type weight and family feel, corner radius, surface treatment (flat vs. cards vs. borders), density, and recurring chrome (nav style, footer).
32
- - **Text**: extract explicit tokens (hex codes, font names, tone words) and resolve vague language into concrete decisions before writing.
33
- - **Existing page**: read `pages/<id>/index.tsx` (and `components/`) and pull:
34
- - The Tailwind color utilities used consistently (`bg-…`, `text-…`, accent classes) → Palette section.
35
- - Type sizes and any font loading (`<link>` to Google Fonts, `font-[…]`) → Typography section.
36
- - Container widths, section padding, breakpoints used → Layout section.
37
- - Recurring helper components (nav, hero, cards, buttons, footer) → Fixed components section.
38
- - The aesthetic feel implied → Aesthetic paragraph.
33
+ - **Preset**: take its tokens as the baseline; adjust only what the user asked to change.
34
+ - **Images**: read each path with the `Read` tool (it accepts images). Note dominant colors (write them as hex, then convert to OKLCH), type family feel, corner radius, surface treatment (flat vs. cards vs. borders), light or dark default, and chrome (nav style, footer).
35
+ - **Text**: extract explicit values (hex codes, font names, "rounded", "sharp", "dense") and resolve vague language into concrete decisions before writing.
36
+ - **Existing page**: read `pages/<id>/index.tsx` (and `components/`) and pull any raw palette classes or hex values into token roles (the page's `bg-[#0b0b10]` root → `--background`; its CTA fill → `--primary`; its card border → `--border`), plus fonts and radius.
39
37
 
40
- When inputs disagree (e.g. images use blue but the description says green), ask the user which to honor.
38
+ Every color ends up as `oklch(L C H)` — the same format as `styles/globals.css`. When inputs disagree (images use blue but the description says green), ask the user which to honor.
41
39
 
42
40
  ## Step 3 — Pick a theme id
43
41
 
44
42
  Use **kebab-case**, short, descriptive. Examples: `dark-launch`, `clean-saas`, `editorial-warm`, `ops-console`. Check `themes/` to avoid collisions.
45
43
 
46
- ## Step 4 — Write `themes/<id>.md`
44
+ ## Step 4 — Write `themes/<id>.css`
45
+
46
+ Override the full token list for both modes, even when a value equals the default, so the file is self-describing:
47
+
48
+ ```css
49
+ @import url('https://fonts.googleapis.com/css2?family=Inter+Tight:wght@500;700&family=Inter:wght@400;500&display=swap');
50
+
51
+ :root {
52
+ --font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif;
53
+ --font-heading: 'Inter Tight', var(--font-sans);
54
+ --radius: 0.75rem;
55
+ --background: oklch(1 0 0);
56
+ --foreground: oklch(0.145 0 0);
57
+ --card: oklch(1 0 0);
58
+ --card-foreground: oklch(0.145 0 0);
59
+ --popover: oklch(1 0 0);
60
+ --popover-foreground: oklch(0.145 0 0);
61
+ --primary: oklch(0.55 0.2 265);
62
+ --primary-foreground: oklch(0.985 0 0);
63
+ --secondary: oklch(0.97 0 0);
64
+ --secondary-foreground: oklch(0.205 0 0);
65
+ --muted: oklch(0.97 0 0);
66
+ --muted-foreground: oklch(0.5 0 0);
67
+ --accent: oklch(0.97 0 0);
68
+ --accent-foreground: oklch(0.205 0 0);
69
+ --destructive: oklch(0.577 0.245 27.325);
70
+ --border: oklch(0.922 0 0);
71
+ --input: oklch(0.922 0 0);
72
+ --ring: oklch(0.55 0.2 265);
73
+ --chart-1: oklch(0.55 0.2 265);
74
+ --chart-2: oklch(0.6 0.118 184.704);
75
+ --chart-3: oklch(0.398 0.07 227.392);
76
+ --chart-4: oklch(0.828 0.189 84.429);
77
+ --chart-5: oklch(0.769 0.188 70.08);
78
+ --sidebar: oklch(0.985 0 0);
79
+ --sidebar-foreground: oklch(0.145 0 0);
80
+ --sidebar-primary: oklch(0.55 0.2 265);
81
+ --sidebar-primary-foreground: oklch(0.985 0 0);
82
+ --sidebar-accent: oklch(0.97 0 0);
83
+ --sidebar-accent-foreground: oklch(0.205 0 0);
84
+ --sidebar-border: oklch(0.922 0 0);
85
+ --sidebar-ring: oklch(0.55 0.2 265);
86
+ }
87
+
88
+ .dark {
89
+ --background: oklch(0.13 0.01 265);
90
+ --foreground: oklch(0.985 0 0);
91
+ /* … every token again, dark values … */
92
+ }
93
+ ```
94
+
95
+ Rules:
96
+
97
+ - Exactly the shadcn token names (`--background` … `--sidebar-ring`, `--radius`), plus optionally `--font-sans` / `--font-heading` and the font `@import`. Unknown names do nothing; misspelled names silently fall back to the default.
98
+ - `*-foreground` must contrast with its surface (≥ 4.5:1 for body pairs). Check `--muted-foreground` on `--background` and `--primary-foreground` on `--primary` explicitly.
99
+ - A dark-first theme still defines `:root` for light; a page that wants dark puts `dark` on its root element. If the theme is dark-only, make both blocks the dark values.
100
+ - `--radius` sets every radius (`rounded-sm` … `rounded-2xl` scale from it): `0` sharp, `0.5rem` default-ish, `1rem` soft.
101
+ - Fonts load from Google Fonts via `@import url(…)` at the top of this file, or from a self-hosted file the theme tells `create-page` to place under `assets/` (then `@font-face` goes in the page's `styles.css`, not here).
102
+
103
+ ## Step 5 — Write `themes/<id>.md`
47
104
 
48
105
  Produce a file with this exact section order. Section bodies adapt to the theme; the headings stay consistent across all themes.
49
106
 
@@ -55,169 +112,99 @@ description: <one-line elevator pitch>
55
112
 
56
113
  # <Theme name>
57
114
 
58
- ## Palette
115
+ ## Tokens
59
116
 
60
- | Role | Tailwind | Hex | Notes |
117
+ | Token | Light | Dark | Role in pages |
61
118
  | --- | --- | --- | --- |
62
- | background | `bg-[#0b0b10]` | #0b0b10 | page root |
63
- | surface | `bg-white/[0.04] border-white/10` | — | cards, panels |
64
- | text | `text-white` | #ffffff | headings, body |
65
- | muted | `text-white/60` | — | secondary copy, labels |
66
- | accent | `bg-emerald-400 text-black` / `text-emerald-400` | #34d399 | primary CTA, eyebrows |
67
- | border | `border-white/10` | — | dividers, card edges |
119
+ | `--background` / `--foreground` | `oklch(1 0 0)` / `oklch(0.145 0 0)` | … | page root (`bg-background text-foreground`) |
120
+ | `--primary` / `--primary-foreground` | … | … | the one accent: CTAs, active tabs, links |
121
+ | `--card`, `--muted`, `--accent`, `--secondary` | … | … | surfaces |
122
+ | `--border`, `--input`, `--ring` | … | … | rules, fields, focus |
123
+ | `--destructive` | … | … | delete, errors |
124
+ | `--chart-1…5` | … | … | chart series order |
125
+ | `--radius` | `0.75rem` | | rounded-lg cards, pill buttons via `rounded-full` |
126
+
127
+ The full set lives in `themes/<id>.css`; this table is the reference for what each value is *for*.
68
128
 
69
129
  ## Typography
70
130
 
71
- - Font: system stack, or a named family with how to load it (Google Fonts `<link>` rendered in the page, or a self-hosted file the page must place under `assets/`).
72
- - Type-scale overrides (only list what differs from `page-authoring` defaults):
73
- - Hero heading: `text-5xl sm:text-7xl font-bold leading-[1.02] tracking-tight`
74
- - Section heading: `text-3xl font-bold tracking-tight`
75
- - Body: `text-lg text-white/60`
76
- - Eyebrow: `text-xs font-semibold uppercase tracking-[0.25em] text-emerald-400`
131
+ - Fonts: `--font-sans` / `--font-heading` set in the CSS (how they load: Google Fonts `@import`, or a self-hosted file under `assets/`).
132
+ - Type-scale overrides (only what differs from `page-authoring` defaults): hero `text-5xl sm:text-7xl font-heading tracking-tight`; body `text-lg`; eyebrow `<Badge variant="secondary">`.
77
133
 
78
134
  ## Layout
79
135
 
80
- - Container: `mx-auto max-w-6xl px-6`.
81
- - Section rhythm: `py-20`, sections separated by `border-t border-white/10`.
82
- - Breakpoints: single column by default; `sm:grid-cols-3` for feature and pricing grids; nav links `hidden sm:flex`.
83
- - Radius: `rounded-full` for buttons, `rounded-2xl` for cards.
84
-
85
- ## Fixed components
86
-
87
- These are paste-ready React JSX with `className`. Copy them verbatim into a page that uses this theme.
88
-
89
- ### Nav
90
-
91
- ```tsx
92
- const Nav = ({ brand, links, cta }: { brand: string; links: { label: string; href: string }[]; cta: { label: string; href: string } }) => (
93
- <header className="mx-auto flex max-w-6xl items-center justify-between px-6 py-6">
94
- <span className="font-semibold tracking-tight">{brand}</span>
95
- <nav className="hidden gap-8 text-sm text-white/70 sm:flex">
96
- {links.map((l) => (
97
- <a key={l.href} href={l.href} className="hover:text-white">{l.label}</a>
98
- ))}
99
- </nav>
100
- <a href={cta.href} className="rounded-full bg-white px-4 py-2 text-sm font-medium text-black hover:bg-white/90">{cta.label}</a>
101
- </header>
102
- );
103
- ```
104
-
105
- ### Hero
106
-
107
- ```tsx
108
- const Hero = ({ eyebrow, title, lede, children }: { eyebrow: string; title: string; lede: string; children?: React.ReactNode }) => (
109
- <section className="mx-auto max-w-6xl px-6 pt-20 pb-24 text-center">
110
- <p className="text-xs font-semibold uppercase tracking-[0.25em] text-emerald-400">{eyebrow}</p>
111
- <h1 className="mx-auto mt-6 max-w-3xl text-5xl font-bold leading-[1.02] tracking-tight sm:text-7xl">{title}</h1>
112
- <p className="mx-auto mt-6 max-w-xl text-lg text-white/60">{lede}</p>
113
- <div className="mt-10 flex flex-col justify-center gap-3 sm:flex-row">{children}</div>
114
- </section>
115
- );
116
- ```
117
-
118
- ### Section
119
-
120
- ```tsx
121
- const Section = ({ id, children }: { id?: string; children: React.ReactNode }) => (
122
- <section id={id} className="border-t border-white/10">
123
- <div className="mx-auto max-w-6xl px-6 py-20">{children}</div>
124
- </section>
125
- );
126
- ```
136
+ - Container: `mx-auto max-w-6xl px-6`; section rhythm `py-20`; separators `border-t border-border`.
137
+ - Default mode: light | dark (`dark` on the page root).
138
+ - Density: airy | standard | dense — how much `gap-*` and padding pages should use.
127
139
 
128
- ### Buttons
140
+ ## Components in this theme
129
141
 
130
- ```tsx
131
- const PrimaryButton = ({ href, children }: { href: string; children: React.ReactNode }) => (
132
- <a href={href} className="rounded-full bg-emerald-400 px-6 py-3 font-medium text-black hover:bg-emerald-300">{children}</a>
133
- );
134
- const SecondaryButton = ({ href, children }: { href: string; children: React.ReactNode }) => (
135
- <a href={href} className="rounded-full border border-white/20 px-6 py-3 font-medium text-white/80 hover:border-white/40">{children}</a>
136
- );
137
- ```
142
+ Notes on how to use the `ui/` set so pages feel like this theme — which variants to prefer, what to avoid:
138
143
 
139
- ### Card
140
-
141
- ```tsx
142
- const Card = ({ title, children }: { title: string; children: React.ReactNode }) => (
143
- <div className="rounded-2xl border border-white/10 bg-white/[0.03] p-6">
144
- <h3 className="font-semibold">{title}</h3>
145
- <div className="mt-2 text-white/60">{children}</div>
146
- </div>
147
- );
148
- ```
149
-
150
- ### Footer
151
-
152
- ```tsx
153
- const Footer = ({ left, right }: { left: string; right: string }) => (
154
- <footer className="border-t border-white/10">
155
- <div className="mx-auto flex max-w-6xl items-center justify-between px-6 py-8 text-sm text-white/40">
156
- <span>{left}</span>
157
- <span>{right}</span>
158
- </div>
159
- </footer>
160
- );
161
- ```
144
+ - Buttons: primary CTA `<Button size="lg">`; secondary `<Button size="lg" variant="outline">`; pill shape via `className="rounded-full"` (or not).
145
+ - Cards: `<Card>` with `border-border`, no shadow | `shadow-sm`.
146
+ - Nav: `<NavigationMenu>` on desktop, `<Sheet>` on mobile; sticky with `bg-background/90 backdrop-blur`.
147
+ - Data: `<Table>` + `<Badge>` for status; charts use `--chart-*` in order.
148
+ - Feedback: `<Alert>`, `sonner` toasts.
149
+ - Avoid: gradients | shadows | more than one accent | … (whatever the theme forbids).
162
150
 
163
151
  ## Aesthetic
164
152
 
165
- One paragraph. What it feels like, the references it draws on, what to avoid (e.g. "no gradients; one accent only; borders over shadows; motion limited to hover color changes"). Commit to a single direction.
153
+ One paragraph. What it feels like, the references it draws on, what to avoid. Commit to a single direction.
166
154
 
167
155
  ## Example usage
168
156
 
169
157
  ```tsx
170
- <main className="min-h-screen bg-[#0b0b10] text-white antialiased">
171
- <Nav brand="Meridian" links={links} cta={{ label: 'Get started', href: '#pricing' }} />
172
- <Hero eyebrow="Now in public beta" title="Your analytics, turned into decisions" lede="…">
173
- <PrimaryButton href="#pricing">Start free</PrimaryButton>
174
- <SecondaryButton href="#features">See how it works</SecondaryButton>
175
- </Hero>
176
- {/* … */}
177
- <Footer left="© 2026 Meridian" right="Built with open-pages" />
158
+ export const meta: PageMeta = { title: '…', theme: '<id>', createdAt: '…' };
159
+
160
+ <main className="min-h-screen bg-background text-foreground antialiased">
161
+ <header className="mx-auto flex max-w-6xl items-center justify-between px-6 py-6">…<Button>Get started</Button></header>
162
+ <section className="mx-auto max-w-6xl px-6 py-20">…</section>
178
163
  </main>
179
164
  ```
180
165
  ````
181
166
 
182
- ## Step 4b — Write `themes/<id>.demo.tsx`
167
+ The markdown never contains color values that are not also in the CSS, and never contains paste-ready components with raw colors — pages compose `ui/` and the tokens do the rest.
168
+
169
+ ## Step 6 — Write `themes/<id>.demo.tsx`
183
170
 
184
- The demo is a normal page module — same shape as `pages/<id>/index.tsx`, just sitting under `themes/` so the runtime knows it's preview-only.
171
+ The demo is a normal page module — same shape as `pages/<id>/index.tsx`, sitting under `themes/` so the runtime knows it's preview-only.
185
172
 
186
173
  Contract:
187
174
 
188
- - `import type { PageMeta } from '@autono/open-pages';` and React hooks as needed.
189
- - **One default-exported component** — a single scrolling page that exercises the theme: nav, hero with both buttons, a section with a card grid, a footer.
190
- - Inline the **same** fixed components defined in the theme markdown — verbatim, no abstractions. Demo and markdown must stay in lockstep so what `create-page` pastes matches what the demo shows.
191
- - Root element sets `min-h-screen`, the theme background, and text color. Must look right at Mobile (390px) as well as Desktop.
192
- - Content should be plausible and realistic, not lorem ipsum. Self-contained: no `@/` imports, no page-local assets; if the theme names a Google Font, render the `<link>` tag in the demo too.
175
+ - `import type { PageMeta } from '@autono/open-pages';`, `@/ui/*` imports, React hooks as needed. No `meta.theme` (the runtime injects `<id>.css` for demos).
176
+ - **One default-exported component** — a single scrolling page that exercises the tokens on real components: a header with `<Button>`s, a hero, a `<Card>` grid, a `<Tabs>` or `<Accordion>`, a `<Table>` with `<Badge>` status, an `<Input>` + `<Button>` form row, and a footer. Include one dark section (`<div className="dark bg-background text-foreground">`) if the theme is light-first, or one light section if dark-first, so both blocks of the CSS are visible.
177
+ - Root element: `min-h-screen bg-background text-foreground` (with `dark` if the theme is dark by default). Everything token-styled — the demo is the proof that pages need no raw colors.
178
+ - Realistic content, not lorem ipsum. Must look right at Mobile (390px) as well as Desktop. Self-contained: no page-local assets.
193
179
 
194
- ## Step 5 — Self-review
180
+ ## Step 7 — Self-review
195
181
 
196
- - [ ] Palette table covers background / surface / text / muted / accent / border as Tailwind utilities, with hex where fixed.
197
- - [ ] Frontmatter has `name` and `description` only (the runtime reads nothing else).
198
- - [ ] Typography names only fonts the theme explains how to load (or the system stack).
199
- - [ ] Layout specifies container width, section rhythm, and breakpoints.
200
- - [ ] Fixed components are paste-ready React JSX (`className`, typed props, no `@/` imports) and cover nav, hero, section, buttons, card, footer.
201
- - [ ] Aesthetic paragraph names a single coherent direction.
202
- - [ ] Both files written: `themes/<id>.md` and `themes/<id>.demo.tsx`. No page changes, no config changes.
203
- - [ ] Demo `.tsx` default-exports one component and inlines the same fixed components as the markdown; contrast holds; nothing overflows on mobile.
182
+ - [ ] `themes/<id>.css` overrides every shadcn token in both `:root` and `.dark`, in OKLCH, with only those two selectors (plus an optional font `@import`).
183
+ - [ ] Every `*-foreground` passes contrast on its surface; `--muted-foreground` is readable on `--background`.
184
+ - [ ] Frontmatter in the `.md` has `name` and `description` only (the runtime reads nothing else).
185
+ - [ ] Typography names only fonts the CSS loads (or the system stack).
186
+ - [ ] "Components in this theme" gives variant guidance for buttons, cards, nav, data, feedback.
187
+ - [ ] Demo `.tsx` default-exports one component, imports only `@/ui/*`, uses semantic tokens only, shows both modes, nothing overflows on mobile.
188
+ - [ ] All three files written with the same stem. No page changes, no `ui/` changes, no `styles/globals.css` changes.
204
189
 
205
- ## Step 6 — Hand off
190
+ ## Step 8 — Hand off
206
191
 
207
192
  Tell the user:
208
193
 
209
- - The theme id and the two file paths.
194
+ - The theme id and the three file paths.
210
195
  - That the Themes panel in the workspace (`http://localhost:5173/themes`) previews the demo live, and `/create-page` will list the theme as a picker option on its next run.
211
- - A one-line summary of the look (palette + aesthetic).
196
+ - That any existing page can adopt it by setting `meta.theme: '<id>'` — no other change.
197
+ - A one-line summary of the look (accent, mode, radius, fonts).
212
198
 
213
199
  Do not run the dev server. Do not modify real pages — the demo `.tsx` is the demonstration.
214
200
 
215
201
  ## Anti-patterns
216
202
 
217
- - ❌ Writing executable code in `themes/<id>.md` outside the labeled component snippets — the markdown is documentation.
218
- - ❌ Producing only the markdown without the demo, or only the demo without the markdown. A theme is the **bundle** — both files, every time.
219
- - ❌ Desktop-only components: a nav with no mobile behaviour, grids with no stacking fallback.
220
- - ❌ Naming font families the theme never explains how to load.
221
- - ❌ Inventing palette / styling when the user supplied images or an existing page. Extract, don't fabricate.
222
- - ❌ Editing `pages/`, `packages/`, `package.json`, or `open-pages.config.ts`.
223
- - ❌ Skipping Fixed components. Nav, hero, buttons, and footer are the most common reuse targets — they must be paste-ready.
203
+ - ❌ Pasting token values into pages, or theme markdown full of `bg-[#hex]` snippets. Tokens live in the CSS; pages stay semantic.
204
+ - ❌ `@theme inline`, `@import "tailwindcss"`, `@source`, or selectors other than `:root`/`.dark` in `themes/<id>.css`.
205
+ - ❌ Editing `styles/globals.css` or running `npx shadcn apply` against the workspace — that silently rethemes every page.
206
+ - ❌ Producing one or two of the three files. A theme is the **bundle** — `.md`, `.css`, `.demo.tsx`, every time.
207
+ - ❌ A demo with raw colors or hand-rolled buttons — it must prove the tokens carry the look through `ui/`.
208
+ - ❌ Naming font families the CSS never loads.
209
+ - ❌ Inventing values when the user supplied a preset, images, or an existing page. Extract, don't fabricate.
210
+ - ❌ Editing `pages/`, `ui/`, `packages/`, `package.json`, or `open-pages.config.ts`.
@@ -49,7 +49,7 @@ Path is relative to the project root (the user's `cwd`, the directory that conta
49
49
  - `view` — `"pages"` when the user is viewing the page, `"assets"` when they are browsing that page's files in the asset manager rather than the page itself.
50
50
  - `selection` — `null` if nothing is selected. Otherwise, the JSX element the user picked in the inspector:
51
51
  - `line` (1-indexed) and `column` (0-indexed) point to the JSX opening tag in the page source. This is the canonical handle — match against the source line.
52
- - `tagName` is the rendered HTML tag, lowercased (`"h1"`, `"div"`, `"button"`).
52
+ - `tagName` is the rendered HTML tag, lowercased (`"h1"`, `"div"`, `"button"`). The source line it points at may be a shadcn component rather than that tag — a `"button"` selection usually lands on a `<Button>` line in the page, because `ui/` components spread the inspector tag onto their root. Edit the page line; never follow it into `ui/*.tsx`.
53
53
  - `text` is a trimmed text snippet (≤120 chars) of the element's content — a sanity check that you're looking at the right node.
54
54
  - Selection auto-clears whenever the user navigates to a different page or clears it in the viewer. HTML pages never produce a selection.
55
55
  - `updatedAt` — ISO timestamp of the last navigation or selection change. Use it to detect staleness.