@autono/create-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.
- package/README.md +6 -3
- package/dist/cli.js +1 -1
- package/package.json +1 -1
- package/template/.agents/skills/apply-comments/SKILL.md +4 -4
- package/template/.agents/skills/create-page/SKILL.md +26 -8
- package/template/.agents/skills/create-theme/SKILL.md +137 -150
- package/template/.agents/skills/current-page/SKILL.md +1 -1
- package/template/.agents/skills/page-authoring/SKILL.md +97 -42
- package/template/.agents/skills/page-authoring/references/interactivity.md +71 -23
- package/template/.agents/skills/page-authoring/references/layout-and-responsive.md +38 -17
- package/template/.agents/skills/page-authoring/references/typography-and-color.md +50 -32
- package/template/.agents/skills/shadcn/SKILL.md +277 -0
- package/template/.agents/skills/shadcn/assets/shadcn-small.png +0 -0
- package/template/.agents/skills/shadcn/assets/shadcn.png +0 -0
- package/template/.agents/skills/shadcn/cli.md +290 -0
- package/template/.agents/skills/shadcn/customization.md +209 -0
- package/template/.agents/skills/shadcn/mcp.md +105 -0
- package/template/.agents/skills/shadcn/registry.md +277 -0
- package/template/.agents/skills/shadcn/rules/base-vs-radix.md +306 -0
- package/template/.agents/skills/shadcn/rules/chat.md +224 -0
- package/template/.agents/skills/shadcn/rules/composition.md +213 -0
- package/template/.agents/skills/shadcn/rules/forms.md +192 -0
- package/template/.agents/skills/shadcn/rules/icons.md +101 -0
- package/template/.agents/skills/shadcn/rules/styling.md +185 -0
- package/template/AGENTS.md +7 -4
- package/template/README.md +21 -4
- package/template/components.json +9 -0
- package/template/hooks/use-mobile.ts +19 -0
- package/template/lib/utils.ts +6 -0
- package/template/package.json +27 -5
- package/template/pages/getting-started/index.tsx +51 -45
- package/template/styles/globals.css +118 -0
- package/template/tsconfig.json +13 -2
- package/template/ui/accordion.tsx +64 -0
- package/template/ui/alert-dialog.tsx +196 -0
- package/template/ui/alert.tsx +66 -0
- package/template/ui/aspect-ratio.tsx +11 -0
- package/template/ui/attachment.tsx +204 -0
- package/template/ui/avatar.tsx +107 -0
- package/template/ui/badge.tsx +48 -0
- package/template/ui/breadcrumb.tsx +109 -0
- package/template/ui/bubble.tsx +125 -0
- package/template/ui/button-group.tsx +83 -0
- package/template/ui/button.tsx +64 -0
- package/template/ui/calendar.tsx +218 -0
- package/template/ui/card.tsx +92 -0
- package/template/ui/carousel.tsx +241 -0
- package/template/ui/chart.tsx +374 -0
- package/template/ui/checkbox.tsx +32 -0
- package/template/ui/collapsible.tsx +31 -0
- package/template/ui/combobox.tsx +308 -0
- package/template/ui/command.tsx +182 -0
- package/template/ui/context-menu.tsx +252 -0
- package/template/ui/dialog.tsx +156 -0
- package/template/ui/direction.tsx +22 -0
- package/template/ui/drawer.tsx +133 -0
- package/template/ui/dropdown-menu.tsx +257 -0
- package/template/ui/empty.tsx +104 -0
- package/template/ui/field.tsx +246 -0
- package/template/ui/form.tsx +167 -0
- package/template/ui/hover-card.tsx +42 -0
- package/template/ui/input-group.tsx +170 -0
- package/template/ui/input-otp.tsx +77 -0
- package/template/ui/input.tsx +21 -0
- package/template/ui/item.tsx +193 -0
- package/template/ui/kbd.tsx +28 -0
- package/template/ui/label.tsx +22 -0
- package/template/ui/marker.tsx +69 -0
- package/template/ui/menubar.tsx +276 -0
- package/template/ui/message-scroller.tsx +128 -0
- package/template/ui/message.tsx +92 -0
- package/template/ui/native-select.tsx +62 -0
- package/template/ui/navigation-menu.tsx +168 -0
- package/template/ui/pagination.tsx +127 -0
- package/template/ui/popover.tsx +87 -0
- package/template/ui/progress.tsx +31 -0
- package/template/ui/radio-group.tsx +43 -0
- package/template/ui/resizable.tsx +53 -0
- package/template/ui/scroll-area.tsx +56 -0
- package/template/ui/select.tsx +190 -0
- package/template/ui/separator.tsx +26 -0
- package/template/ui/sheet.tsx +143 -0
- package/template/ui/sidebar.tsx +726 -0
- package/template/ui/skeleton.tsx +13 -0
- package/template/ui/slider.tsx +61 -0
- package/template/ui/sonner.tsx +40 -0
- package/template/ui/spinner.tsx +16 -0
- package/template/ui/switch.tsx +33 -0
- package/template/ui/table.tsx +116 -0
- package/template/ui/tabs.tsx +89 -0
- package/template/ui/textarea.tsx +18 -0
- package/template/ui/toggle-group.tsx +81 -0
- package/template/ui/toggle.tsx +47 -0
- package/template/ui/tooltip.tsx +55 -0
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Icons
|
|
2
|
+
|
|
3
|
+
**Always use the project's configured `iconLibrary` for imports.** Check the `iconLibrary` field from project context: `lucide` → `lucide-react`, `tabler` → `@tabler/icons-react`, etc. Never assume `lucide-react`.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Icons in Button use data-icon attribute
|
|
8
|
+
|
|
9
|
+
Add `data-icon="inline-start"` (prefix) or `data-icon="inline-end"` (suffix) to the icon. No sizing classes on the icon.
|
|
10
|
+
|
|
11
|
+
**Incorrect:**
|
|
12
|
+
|
|
13
|
+
```tsx
|
|
14
|
+
<Button>
|
|
15
|
+
<SearchIcon className="mr-2 size-4" />
|
|
16
|
+
Search
|
|
17
|
+
</Button>
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Correct:**
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
<Button>
|
|
24
|
+
<SearchIcon data-icon="inline-start"/>
|
|
25
|
+
Search
|
|
26
|
+
</Button>
|
|
27
|
+
|
|
28
|
+
<Button>
|
|
29
|
+
Next
|
|
30
|
+
<ArrowRightIcon data-icon="inline-end"/>
|
|
31
|
+
</Button>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## No sizing classes on icons inside components
|
|
37
|
+
|
|
38
|
+
Components handle icon sizing via CSS. Don't add `size-4`, `w-4 h-4`, or other sizing classes to icons inside `Button`, `DropdownMenuItem`, `Alert`, `Sidebar*`, or other shadcn components. Unless the user explicitly asks for custom icon sizes.
|
|
39
|
+
|
|
40
|
+
**Incorrect:**
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
<Button>
|
|
44
|
+
<SearchIcon className="size-4" data-icon="inline-start" />
|
|
45
|
+
Search
|
|
46
|
+
</Button>
|
|
47
|
+
|
|
48
|
+
<DropdownMenuItem>
|
|
49
|
+
<SettingsIcon className="mr-2 size-4" />
|
|
50
|
+
Settings
|
|
51
|
+
</DropdownMenuItem>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Correct:**
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
<Button>
|
|
58
|
+
<SearchIcon data-icon="inline-start" />
|
|
59
|
+
Search
|
|
60
|
+
</Button>
|
|
61
|
+
|
|
62
|
+
<DropdownMenuItem>
|
|
63
|
+
<SettingsIcon />
|
|
64
|
+
Settings
|
|
65
|
+
</DropdownMenuItem>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Pass icons as component objects, not string keys
|
|
71
|
+
|
|
72
|
+
Use `icon={CheckIcon}`, not a string key to a lookup map.
|
|
73
|
+
|
|
74
|
+
**Incorrect:**
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
const iconMap = {
|
|
78
|
+
check: CheckIcon,
|
|
79
|
+
alert: AlertIcon,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function StatusBadge({ icon }: { icon: string }) {
|
|
83
|
+
const Icon = iconMap[icon]
|
|
84
|
+
return <Icon />
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
<StatusBadge icon="check" />
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Correct:**
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
// Import from the project's configured iconLibrary (e.g. lucide-react, @tabler/icons-react).
|
|
94
|
+
import { CheckIcon } from "lucide-react"
|
|
95
|
+
|
|
96
|
+
function StatusBadge({ icon: Icon }: { icon: React.ComponentType }) {
|
|
97
|
+
return <Icon />
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
<StatusBadge icon={CheckIcon} />
|
|
101
|
+
```
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# Styling & Customization
|
|
2
|
+
|
|
3
|
+
See [customization.md](../customization.md) for theming, CSS variables, and adding custom colors.
|
|
4
|
+
|
|
5
|
+
## Contents
|
|
6
|
+
|
|
7
|
+
- Semantic colors
|
|
8
|
+
- Built-in variants first
|
|
9
|
+
- className for layout only
|
|
10
|
+
- No space-x-* / space-y-*
|
|
11
|
+
- Prefer size-* over w-* h-* when equal
|
|
12
|
+
- Prefer truncate shorthand
|
|
13
|
+
- No manual dark: color overrides
|
|
14
|
+
- Use cn() for conditional classes
|
|
15
|
+
- No manual z-index on overlay components
|
|
16
|
+
- Use shimmer / scroll-fade utilities, not custom animations
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Semantic colors
|
|
21
|
+
|
|
22
|
+
**Incorrect:**
|
|
23
|
+
|
|
24
|
+
```tsx
|
|
25
|
+
<div className="bg-blue-500 text-white">
|
|
26
|
+
<p className="text-gray-600">Secondary text</p>
|
|
27
|
+
</div>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
**Correct:**
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
<div className="bg-primary text-primary-foreground">
|
|
34
|
+
<p className="text-muted-foreground">Secondary text</p>
|
|
35
|
+
</div>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## No raw color values for status/state indicators
|
|
41
|
+
|
|
42
|
+
For positive, negative, or status indicators, use Badge variants, semantic tokens like `text-destructive`, or define custom CSS variables — don't reach for raw Tailwind colors.
|
|
43
|
+
|
|
44
|
+
**Incorrect:**
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
<span className="text-emerald-600">+20.1%</span>
|
|
48
|
+
<span className="text-green-500">Active</span>
|
|
49
|
+
<span className="text-red-600">-3.2%</span>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Correct:**
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
<Badge variant="secondary">+20.1%</Badge>
|
|
56
|
+
<Badge>Active</Badge>
|
|
57
|
+
<span className="text-destructive">-3.2%</span>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
If you need a success/positive color that doesn't exist as a semantic token, use a Badge variant or ask the user about adding a custom CSS variable to the theme (see [customization.md](../customization.md)).
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Built-in variants first
|
|
65
|
+
|
|
66
|
+
**Incorrect:**
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
<Button className="border border-input bg-transparent hover:bg-accent">
|
|
70
|
+
Click me
|
|
71
|
+
</Button>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Correct:**
|
|
75
|
+
|
|
76
|
+
```tsx
|
|
77
|
+
<Button variant="outline">Click me</Button>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## className for layout only
|
|
83
|
+
|
|
84
|
+
Use `className` for layout (e.g. `max-w-md`, `mx-auto`, `mt-4`), **not** for overriding component colors or typography. To change colors, use semantic tokens, built-in variants, or CSS variables.
|
|
85
|
+
|
|
86
|
+
**Incorrect:**
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
<Card className="bg-blue-100 text-blue-900 font-bold">
|
|
90
|
+
<CardContent>Dashboard</CardContent>
|
|
91
|
+
</Card>
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Correct:**
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
<Card className="max-w-md mx-auto">
|
|
98
|
+
<CardContent>Dashboard</CardContent>
|
|
99
|
+
</Card>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
To customize a component's appearance, prefer these approaches in order:
|
|
103
|
+
1. **Built-in variants** — `variant="outline"`, `variant="destructive"`, etc.
|
|
104
|
+
2. **Semantic color tokens** — `bg-primary`, `text-muted-foreground`.
|
|
105
|
+
3. **CSS variables** — define custom colors in the global CSS file (see [customization.md](../customization.md)).
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## No space-x-* / space-y-*
|
|
110
|
+
|
|
111
|
+
Use `gap-*` instead. `space-y-4` → `flex flex-col gap-4`. `space-x-2` → `flex gap-2`.
|
|
112
|
+
|
|
113
|
+
```tsx
|
|
114
|
+
<div className="flex flex-col gap-4">
|
|
115
|
+
<Input />
|
|
116
|
+
<Input />
|
|
117
|
+
<Button>Submit</Button>
|
|
118
|
+
</div>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Prefer size-* over w-* h-* when equal
|
|
124
|
+
|
|
125
|
+
`size-10` not `w-10 h-10`. Applies to icons, avatars, skeletons, etc.
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Prefer truncate shorthand
|
|
130
|
+
|
|
131
|
+
`truncate` not `overflow-hidden text-ellipsis whitespace-nowrap`.
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## No manual dark: color overrides
|
|
136
|
+
|
|
137
|
+
Use semantic tokens — they handle light/dark via CSS variables. `bg-background text-foreground` not `bg-white dark:bg-gray-950`.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Use cn() for conditional classes
|
|
142
|
+
|
|
143
|
+
Use the `cn()` utility from the project for conditional or merged class names. Don't write manual ternaries in className strings.
|
|
144
|
+
|
|
145
|
+
**Incorrect:**
|
|
146
|
+
|
|
147
|
+
```tsx
|
|
148
|
+
<div className={`flex items-center ${isActive ? "bg-primary text-primary-foreground" : "bg-muted"}`}>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Correct:**
|
|
152
|
+
|
|
153
|
+
```tsx
|
|
154
|
+
import { cn } from "@/lib/utils"
|
|
155
|
+
|
|
156
|
+
<div className={cn("flex items-center", isActive ? "bg-primary text-primary-foreground" : "bg-muted")}>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## No manual z-index on overlay components
|
|
162
|
+
|
|
163
|
+
`Dialog`, `Sheet`, `Drawer`, `AlertDialog`, `DropdownMenu`, `Popover`, `Tooltip`, `HoverCard` handle their own stacking. Never add `z-50` or `z-[999]`.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Use shimmer / scroll-fade utilities, not custom animations
|
|
168
|
+
|
|
169
|
+
For a live "thinking…" or loading-text shimmer, apply the `shimmer` utility. Don't author a custom `@keyframes` or a `bg-clip-text` gradient sweep.
|
|
170
|
+
|
|
171
|
+
For scroll-aware edge fading on a scroll container, use `scroll-fade` (and the axis variants `scroll-fade-x` / `scroll-fade-b`). Don't hand-roll mask gradients. The chat components already apply these internally: `Attachment` shimmers its title during upload, and `MessageScrollerViewport` fades its edges.
|
|
172
|
+
|
|
173
|
+
**Incorrect:**
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
<span className="animate-pulse bg-gradient-to-r from-muted-foreground/40 via-foreground/70 to-muted-foreground/40 bg-clip-text text-transparent [animation:shimmer_1.6s_infinite]">
|
|
177
|
+
Thinking…
|
|
178
|
+
</span>
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Correct:**
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
<span className="shimmer">Thinking…</span>
|
|
185
|
+
```
|
package/template/AGENTS.md
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
# open-pages — Agent Guide
|
|
2
2
|
|
|
3
|
-
You are authoring **web pages** in this repo. Every page is a React component rendered as a real web page —
|
|
3
|
+
You are authoring **web pages** in this repo. Every page is a React component rendered as a real web page — composed from the shadcn/ui components under `ui/`, styled with Tailwind via `className`, with hooks, state, and browser APIs available. A page folder can hold an `index.html` instead when plain HTML is the better fit.
|
|
4
4
|
|
|
5
5
|
## Hard rules
|
|
6
6
|
|
|
7
7
|
- Put your page under `pages/<kebab-case-id>/`.
|
|
8
8
|
- The entry is `pages/<id>/index.tsx` (or `pages/<id>/index.html`).
|
|
9
9
|
- A page is its entry plus optional `components/`, `styles.css`, and `assets/` (images, fonts) inside its folder. Shared assets live in the root `assets/` folder (import via `@assets/...`).
|
|
10
|
-
-
|
|
11
|
-
- Do not
|
|
10
|
+
- Use the shadcn components first: `import { Button } from '@/ui/button'`, `cn` from `@/lib/utils`. Use the semantic token classes (`bg-background`, `text-muted-foreground`, `bg-primary`) so themes apply.
|
|
11
|
+
- Do **not** edit files under `ui/`, `lib/`, or `hooks/` for one page. They are shared by every page; wrap or extend a component inside the page instead.
|
|
12
|
+
- Do **not** touch `package.json`, `open-pages.config.ts`, `components.json`, `styles/globals.css`, or other pages.
|
|
13
|
+
- Do not add dependencies beyond what is installed. `npx shadcn@latest add` is fine for blocks and registry items.
|
|
12
14
|
|
|
13
15
|
## Which skill to use
|
|
14
16
|
|
|
15
17
|
- **Drafting a new page** — use the `create-page` skill. It walks through scoping questions, structure, and hand-off.
|
|
16
18
|
- **Applying inspector comments** (`@page-comment` markers in a page) — use the `apply-comments` skill.
|
|
17
|
-
- **Creating or extracting a theme** — use the `create-theme` skill.
|
|
19
|
+
- **Creating or extracting a theme** — use the `create-theme` skill. A theme is `themes/<id>.md` plus `themes/<id>.css` (shadcn token overrides) and a `<id>.demo.tsx` preview; `create-page` reads it before authoring and a page opts in with `meta.theme`.
|
|
20
|
+
- **shadcn CLI, registries, presets, component docs** — the bundled `shadcn` skill (the official one) covers `npx shadcn@latest search / view / docs / add / apply`.
|
|
18
21
|
- **Resolving "this page" / "this element"** — when the user references the current page or selection without naming it, consult the `current-page` skill. It reads the dev server's `node_modules/.open-pages/current.json` to find which page and inspector-picked element they mean.
|
|
19
22
|
- **Any other page edit** — read the `page-authoring` skill before writing. It is the technical reference for everything inside `pages/<id>/`: file contract, styling with Tailwind, layout and responsiveness, interactivity, assets and fonts, self-review checklist. `create-page` and `apply-comments` both defer to it for the *how*.
|
|
20
23
|
|
package/template/README.md
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
# open-pages workspace
|
|
2
2
|
|
|
3
|
-
Web pages as React components. Each page lives under `pages/<id>/index.tsx` and default-exports one component
|
|
3
|
+
Web pages as React components. Each page lives under `pages/<id>/index.tsx` and default-exports one component, composed from the shadcn/ui set that ships under `ui/`. The `@autono/open-pages` runtime handles Vite, React, the live preview, and the inspector — you just write the page.
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
pages/ one folder per page
|
|
7
|
+
ui/ all shadcn/ui components (import from @/ui/*)
|
|
8
|
+
lib/utils.ts cn()
|
|
9
|
+
hooks/ use-mobile
|
|
10
|
+
styles/globals.css Tailwind v4 + shadcn tokens (:root / .dark)
|
|
11
|
+
themes/ <id>.md + <id>.css + <id>.demo.tsx
|
|
12
|
+
assets/ shared assets (import via @assets/...)
|
|
13
|
+
components.json shadcn config
|
|
14
|
+
```
|
|
4
15
|
|
|
5
16
|
## Getting started
|
|
6
17
|
|
|
@@ -27,6 +38,7 @@ Then open `http://localhost:5173`, edit `pages/getting-started/index.tsx`, or cr
|
|
|
27
38
|
```tsx
|
|
28
39
|
// pages/my-page/index.tsx
|
|
29
40
|
import type { PageMeta } from '@autono/open-pages';
|
|
41
|
+
import { Button } from '@/ui/button';
|
|
30
42
|
|
|
31
43
|
export const meta: PageMeta = {
|
|
32
44
|
title: 'My page',
|
|
@@ -35,15 +47,16 @@ export const meta: PageMeta = {
|
|
|
35
47
|
|
|
36
48
|
export default function MyPage() {
|
|
37
49
|
return (
|
|
38
|
-
<main className="
|
|
50
|
+
<main className="min-h-screen bg-background px-6 py-24 text-foreground">
|
|
39
51
|
<h1 className="text-4xl font-bold tracking-tight">Hello</h1>
|
|
40
|
-
<p className="mt-4 text-
|
|
52
|
+
<p className="mt-4 text-muted-foreground">shadcn components, Tailwind, hooks, all of it.</p>
|
|
53
|
+
<Button className="mt-8">Get started</Button>
|
|
41
54
|
</main>
|
|
42
55
|
);
|
|
43
56
|
}
|
|
44
57
|
```
|
|
45
58
|
|
|
46
|
-
A page is a real web page: Tailwind v4 utilities via `className` work out of the box, `import './styles.css'` for custom CSS, hooks and event handlers for interactivity. Put images and fonts under `pages/<id>/assets/` and import them; shared assets go in the root `assets/` folder and import via `@assets/...`.
|
|
59
|
+
A page is a real web page: every shadcn component is importable from `@/ui/<name>`, Tailwind v4 utilities via `className` work out of the box (prefer the token classes: `bg-background`, `text-muted-foreground`, `bg-primary`), `import './styles.css'` for custom CSS, hooks and event handlers for interactivity. `npx shadcn@latest add <block>` still works for blocks and other registries. Put images and fonts under `pages/<id>/assets/` and import them; shared assets go in the root `assets/` folder and import via `@assets/...`.
|
|
47
60
|
|
|
48
61
|
A folder holding an `index.html` (with sibling CSS/JS) instead of `index.tsx` works too. It is served as-is and exported the same way.
|
|
49
62
|
|
|
@@ -74,3 +87,7 @@ export default openPagesConfig;
|
|
|
74
87
|
```
|
|
75
88
|
|
|
76
89
|
Supported fields: `pagesDir`, `themesDir`, `assetsDir`, `port`, `base`, `allowedHosts`, `build`.
|
|
90
|
+
|
|
91
|
+
## Themes
|
|
92
|
+
|
|
93
|
+
A theme is `themes/<id>.md` (direction for the agent), `themes/<id>.css` (`:root` / `.dark` overrides of the shadcn tokens, optionally a Google Fonts `@import`), and `themes/<id>.demo.tsx` (a demo page). Set `meta.theme: '<id>'` on a page and the runtime injects that CSS into its preview and export. `npx shadcn@latest apply <code> --only theme,font` from [ui.shadcn.com/create](https://ui.shadcn.com/create) is a quick way to produce the tokens.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
+
"style": "new-york",
|
|
4
|
+
"rsc": false,
|
|
5
|
+
"tsx": true,
|
|
6
|
+
"tailwind": { "config": "", "css": "styles/globals.css", "baseColor": "neutral", "cssVariables": true, "prefix": "" },
|
|
7
|
+
"iconLibrary": "lucide",
|
|
8
|
+
"aliases": { "components": "@/components", "ui": "@/ui", "lib": "@/lib", "utils": "@/lib/utils", "hooks": "@/hooks" }
|
|
9
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
const MOBILE_BREAKPOINT = 768
|
|
4
|
+
|
|
5
|
+
export function useIsMobile() {
|
|
6
|
+
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
|
|
7
|
+
|
|
8
|
+
React.useEffect(() => {
|
|
9
|
+
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
|
|
10
|
+
const onChange = () => {
|
|
11
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
|
12
|
+
}
|
|
13
|
+
mql.addEventListener("change", onChange)
|
|
14
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
|
15
|
+
return () => mql.removeEventListener("change", onChange)
|
|
16
|
+
}, [])
|
|
17
|
+
|
|
18
|
+
return !!isMobile
|
|
19
|
+
}
|
package/template/package.json
CHANGED
|
@@ -13,12 +13,34 @@
|
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@autono/open-pages": "^0.0.6",
|
|
16
|
-
"react": "^
|
|
17
|
-
"react-dom": "^
|
|
16
|
+
"react": "^19.2.0",
|
|
17
|
+
"react-dom": "^19.2.0",
|
|
18
|
+
"@base-ui/react": "^1.7.0",
|
|
19
|
+
"@hookform/resolvers": "^5.9.1",
|
|
20
|
+
"@shadcn/react": "^0.3.0",
|
|
21
|
+
"class-variance-authority": "^0.7.1",
|
|
22
|
+
"clsx": "^2.1.1",
|
|
23
|
+
"cmdk": "^1.1.1",
|
|
24
|
+
"date-fns": "^4.4.0",
|
|
25
|
+
"embla-carousel-react": "^8.6.0",
|
|
26
|
+
"input-otp": "^1.5.0",
|
|
27
|
+
"lucide-react": "^1.35.0",
|
|
28
|
+
"next-themes": "^0.4.6",
|
|
29
|
+
"radix-ui": "^1.6.7",
|
|
30
|
+
"react-day-picker": "^10.0.1",
|
|
31
|
+
"react-hook-form": "^7.86.0",
|
|
32
|
+
"react-resizable-panels": "^4.12.3",
|
|
33
|
+
"recharts": "3.8.0",
|
|
34
|
+
"sonner": "^2.0.8",
|
|
35
|
+
"tailwind-merge": "^3.6.0",
|
|
36
|
+
"vaul": "^1.1.2",
|
|
37
|
+
"zod": "^4.5.1"
|
|
18
38
|
},
|
|
19
39
|
"devDependencies": {
|
|
20
|
-
"@types/react": "^
|
|
21
|
-
"@types/react-dom": "^
|
|
22
|
-
"vite": "^
|
|
40
|
+
"@types/react": "^19.2.0",
|
|
41
|
+
"@types/react-dom": "^19.2.0",
|
|
42
|
+
"vite": "^6.4.3",
|
|
43
|
+
"tailwindcss": "^4.2.2",
|
|
44
|
+
"typescript": "^5.9.3"
|
|
23
45
|
}
|
|
24
46
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { PageMeta } from '@autono/open-pages';
|
|
2
|
-
import {
|
|
2
|
+
import { Badge } from '@/ui/badge';
|
|
3
|
+
import { Button } from '@/ui/button';
|
|
4
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/ui/card';
|
|
5
|
+
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/ui/tabs';
|
|
3
6
|
|
|
4
7
|
export const meta: PageMeta = {
|
|
5
8
|
title: 'Welcome to open-pages',
|
|
@@ -9,81 +12,84 @@ export const meta: PageMeta = {
|
|
|
9
12
|
|
|
10
13
|
const steps = [
|
|
11
14
|
{
|
|
15
|
+
id: 'describe',
|
|
12
16
|
title: 'Describe',
|
|
13
17
|
body: 'Tell your agent what the page is. It runs /create-page and writes the React.',
|
|
14
18
|
},
|
|
15
19
|
{
|
|
20
|
+
id: 'preview',
|
|
16
21
|
title: 'Preview',
|
|
17
|
-
body: 'This workspace renders the real page in a real browser
|
|
22
|
+
body: 'This workspace renders the real page in a real browser frame on every save.',
|
|
18
23
|
},
|
|
19
24
|
{
|
|
25
|
+
id: 'annotate',
|
|
20
26
|
title: 'Annotate',
|
|
21
27
|
body: 'Press i, click anything, leave a note. It lands in the source as a comment marker.',
|
|
22
28
|
},
|
|
23
29
|
{
|
|
30
|
+
id: 'ship',
|
|
24
31
|
title: 'Ship',
|
|
25
32
|
body: 'Your agent runs /apply-comments. open-pages export writes a static folder you can deploy anywhere.',
|
|
26
33
|
},
|
|
27
34
|
];
|
|
28
35
|
|
|
29
36
|
export default function GettingStarted() {
|
|
30
|
-
const [active, setActive] = useState(0);
|
|
31
|
-
|
|
32
37
|
return (
|
|
33
|
-
<main className="min-h-screen bg-
|
|
38
|
+
<main className="min-h-screen bg-background text-foreground antialiased">
|
|
34
39
|
<section className="mx-auto max-w-3xl px-6 pt-24 pb-16">
|
|
35
|
-
<
|
|
36
|
-
open-pages
|
|
37
|
-
</span>
|
|
40
|
+
<Badge variant="secondary">open-pages</Badge>
|
|
38
41
|
<h1 className="mt-4 text-5xl font-bold leading-[1.05] tracking-tight">
|
|
39
42
|
The web page framework built for agents
|
|
40
43
|
</h1>
|
|
41
|
-
<p className="mt-6 max-w-xl text-lg leading-relaxed text-
|
|
44
|
+
<p className="mt-6 max-w-xl text-lg leading-relaxed text-muted-foreground">
|
|
42
45
|
This page is a React component at{' '}
|
|
43
|
-
<code className="rounded bg-
|
|
46
|
+
<code className="rounded bg-muted px-1.5 py-0.5 font-mono text-[0.9em]">
|
|
44
47
|
pages/getting-started/index.tsx
|
|
45
48
|
</code>
|
|
46
|
-
.
|
|
47
|
-
|
|
49
|
+
. Every shadcn/ui component is already installed under <code>ui/</code>. Your agent
|
|
50
|
+
composes them, the workspace previews the result live, and the export is plain HTML, CSS,
|
|
51
|
+
and JS.
|
|
48
52
|
</p>
|
|
53
|
+
<div className="mt-8 flex gap-3">
|
|
54
|
+
<Button>Primary action</Button>
|
|
55
|
+
<Button variant="outline">Secondary</Button>
|
|
56
|
+
<Button variant="ghost">Ghost</Button>
|
|
57
|
+
</div>
|
|
49
58
|
</section>
|
|
50
59
|
|
|
51
60
|
<section className="mx-auto max-w-3xl px-6 pb-24">
|
|
52
|
-
<
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
key={step.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
>
|
|
65
|
-
<span className="block font-mono text-xs opacity-60">0{i + 1}</span>
|
|
66
|
-
<span className="mt-1 block font-semibold">{step.title}</span>
|
|
67
|
-
</button>
|
|
61
|
+
<Tabs defaultValue="describe">
|
|
62
|
+
<TabsList>
|
|
63
|
+
{steps.map((step, i) => (
|
|
64
|
+
<TabsTrigger key={step.id} value={step.id}>
|
|
65
|
+
<span className="font-mono text-xs opacity-60">0{i + 1}</span>
|
|
66
|
+
{step.title}
|
|
67
|
+
</TabsTrigger>
|
|
68
|
+
))}
|
|
69
|
+
</TabsList>
|
|
70
|
+
{steps.map((step) => (
|
|
71
|
+
<TabsContent key={step.id} value={step.id}>
|
|
72
|
+
<p className="mt-4 min-h-[3.5rem] text-base leading-relaxed">{step.body}</p>
|
|
73
|
+
</TabsContent>
|
|
68
74
|
))}
|
|
69
|
-
</
|
|
70
|
-
<p className="mt-6 min-h-[3.5rem] text-base leading-relaxed text-slate-700">
|
|
71
|
-
{steps[active].body}
|
|
72
|
-
</p>
|
|
75
|
+
</Tabs>
|
|
73
76
|
|
|
74
|
-
<
|
|
75
|
-
<
|
|
76
|
-
Try the loop
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
<
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
77
|
+
<Card className="mt-16">
|
|
78
|
+
<CardHeader>
|
|
79
|
+
<CardTitle>Try the loop</CardTitle>
|
|
80
|
+
<CardDescription>Three things to do in the next two minutes.</CardDescription>
|
|
81
|
+
</CardHeader>
|
|
82
|
+
<CardContent>
|
|
83
|
+
<ol className="space-y-2 text-muted-foreground">
|
|
84
|
+
<li>1. Change any text in this file and watch the preview update.</li>
|
|
85
|
+
<li>2. Switch the viewport to mobile in the toolbar. The layout is responsive.</li>
|
|
86
|
+
<li>
|
|
87
|
+
3. Ask your agent for something bigger: a landing page, a pricing table, a whole new
|
|
88
|
+
page with <code className="font-mono">/create-page</code>.
|
|
89
|
+
</li>
|
|
90
|
+
</ol>
|
|
91
|
+
</CardContent>
|
|
92
|
+
</Card>
|
|
87
93
|
</section>
|
|
88
94
|
</main>
|
|
89
95
|
);
|