@autono/create-open-pages 0.1.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.
@@ -0,0 +1,77 @@
1
+ # Interactivity
2
+
3
+ Pages are real React 18 components running in the browser, wrapped in
4
+ `StrictMode`. Everything React can do is available; the constraints below
5
+ keep pages preview-safe, export-safe, and inspectable.
6
+
7
+ ## State
8
+
9
+ ```tsx
10
+ const [tab, setTab] = useState<'monthly' | 'yearly'>('monthly');
11
+
12
+ <button
13
+ type="button"
14
+ onClick={() => setTab('yearly')}
15
+ aria-pressed={tab === 'yearly'}
16
+ className={tab === 'yearly' ? 'bg-slate-900 text-white' : 'text-slate-600'}
17
+ >
18
+ Yearly
19
+ </button>
20
+ ```
21
+
22
+ - Keep state local and small: tabs, toggles, accordions, filters, form values.
23
+ - Derive, do not duplicate: compute filtered lists with `useMemo` (or inline)
24
+ from the source array and the filter state.
25
+ - Toggle/tab buttons carry `aria-pressed` or `role="tablist"` semantics;
26
+ disclosure buttons carry `aria-expanded` and `aria-controls`.
27
+
28
+ ## Forms
29
+
30
+ - Real `<form>` with `onSubmit={(e) => { e.preventDefault(); … }}`.
31
+ - Every input has a `<label htmlFor>` (or `aria-label`), a `name`, and a
32
+ sensible `type`/`inputMode`/`autoComplete`.
33
+ - No backend exists in the workspace or the export. Either mirror submitted
34
+ values into local state ("Thanks, we'll be in touch"), or point the form at
35
+ a URL the user supplies (`action="https://formspree.io/…" method="post"`).
36
+ Never invent an endpoint.
37
+
38
+ ## Network and browser APIs
39
+
40
+ - `fetch`, `localStorage`, `IntersectionObserver`, `matchMedia` are fine —
41
+ inside effects or handlers, with loading and error states.
42
+ - Assume the exported page may run from `file://` or a static host with no
43
+ API: gate network features behind a URL the user supplied, and render
44
+ something meaningful without it.
45
+ - Access `window`/`document` only inside `useEffect` or event handlers.
46
+ Module-top-level `window.innerWidth` breaks the module import and the
47
+ export build.
48
+
49
+ ## Effects and StrictMode
50
+
51
+ - Effects run twice in development (StrictMode). Every subscription,
52
+ observer, timer, and listener must be cleaned up in the effect's return.
53
+ - No side effects in render. No `Date.now()` / `Math.random()` in render for
54
+ layout-affecting values; seed them in state via a lazy initializer.
55
+
56
+ ## Progressive enhancement
57
+
58
+ - Content must be visible with JavaScript disabled or before hydration: no
59
+ empty shells that only fill from an effect.
60
+ - Hover-only affordances need a keyboard/touch equivalent.
61
+ - Animations: `motion-safe:transition-*`; respect `prefers-reduced-motion`.
62
+
63
+ ## Routing inside a page
64
+
65
+ - Simple multi-view pages: a `view` state and conditional rendering, with
66
+ `<a href="#section">` anchors for in-page navigation.
67
+ - Hash routing is acceptable when the user asks for "pages" inside one export
68
+ (`window.location.hash`, read in an effect). Path-based routing needs a
69
+ host with rewrites — mention this to the user before choosing it.
70
+
71
+ ## Anti-patterns
72
+
73
+ - ❌ `useEffect` to compute something derivable from props/state.
74
+ - ❌ Fetching from an endpoint nobody set up.
75
+ - ❌ `document.querySelector` to mutate the DOM React owns.
76
+ - ❌ Global listeners without cleanup; timers that outlive the component.
77
+ - ❌ Interactive `<div>`s. Use `<button>`, `<a>`, `<input>`, `<select>`.
@@ -0,0 +1,71 @@
1
+ # Layout and responsive design
2
+
3
+ The viewer previews every page at three widths — **Desktop** (the full
4
+ viewport), **Tablet** (820px), and **Mobile** (390px). A page is done when all
5
+ three look intentional. Tailwind is mobile-first: unprefixed utilities are the
6
+ phone layout; `sm:` (640px), `md:` (768px), `lg:` (1024px), `xl:` (1280px)
7
+ layer larger layouts on top.
8
+
9
+ ## Containers
10
+
11
+ ```tsx
12
+ <section className="mx-auto max-w-6xl px-6 py-16 sm:py-24">…</section>
13
+ ```
14
+
15
+ - Center content with `mx-auto max-w-*`; keep horizontal padding (`px-6`) so
16
+ text never touches the viewport edge on mobile.
17
+ - Reading columns: `max-w-2xl` / `max-w-[65ch]` for prose. Marketing grids:
18
+ `max-w-5xl`–`max-w-7xl`.
19
+ - Vertical rhythm: `py-16` between sections on mobile, `sm:py-24` on desktop.
20
+ Sections separate by space or a hairline (`border-t border-slate-200`), not
21
+ both.
22
+
23
+ ## Grids and stacks
24
+
25
+ ```tsx
26
+ <div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
27
+ {features.map((f) => <FeatureCard key={f.title} {...f} />)}
28
+ </div>
29
+ ```
30
+
31
+ - Default to a single column, add columns at `sm:`/`lg:`.
32
+ - `flex flex-col gap-4 sm:flex-row sm:items-center` for header rows that must
33
+ stack on phones.
34
+ - Use `gap-*`, not margins on children, for spacing inside grids and flex rows.
35
+
36
+ ## Navigation
37
+
38
+ - Desktop nav links: `hidden sm:flex gap-8`. On mobile either show a compact
39
+ set of links, or a `<button aria-expanded>` that toggles a stacked menu with
40
+ `useState`. Never let a nav overflow horizontally.
41
+ - Sticky headers: `sticky top-0 z-10 bg-white/90 backdrop-blur` — give them a
42
+ background so content does not bleed through.
43
+
44
+ ## Hero
45
+
46
+ - Heading `text-4xl sm:text-6xl lg:text-7xl`, `leading-[1.05] tracking-tight`.
47
+ - Constrain the heading (`max-w-3xl`) and the lede (`max-w-xl`) independently.
48
+ - CTA row: `flex flex-col gap-3 sm:flex-row` so buttons stack on mobile.
49
+
50
+ ## Full-viewport pages (dashboards, app UIs)
51
+
52
+ - Root: `min-h-screen` (not `h-screen`) so content can scroll.
53
+ - Sidebars: `hidden lg:block w-64` plus a mobile alternative (top tabs or a
54
+ toggle). Content area: `min-w-0 flex-1` so tables and code blocks can shrink.
55
+ - Wide content (tables, charts) scrolls inside its own `overflow-x-auto`
56
+ wrapper; the page body must never scroll horizontally.
57
+
58
+ ## Checklist
59
+
60
+ - [ ] Mobile: no horizontal scrollbar, every grid stacks, headings shrink.
61
+ - [ ] Tablet: two-column layouts where three would cramp.
62
+ - [ ] Desktop: content is capped by a `max-w-*`, not stretched edge to edge.
63
+ - [ ] Touch targets ≥ 40px tall on mobile (`py-2.5` on buttons and links).
64
+
65
+ ## Anti-patterns
66
+
67
+ - ❌ Fixed pixel widths on layout containers (`w-[1200px]`).
68
+ - ❌ `absolute` positioning for layout (fine for badges, overlays, decoration).
69
+ - ❌ `h-screen` on scrolling pages; `overflow-hidden` on `body`/root.
70
+ - ❌ Grids with no mobile fallback (`grid-cols-4` alone).
71
+ - ❌ Text sized only for desktop (`text-7xl` with no smaller base).
@@ -0,0 +1,60 @@
1
+ # Typography and color
2
+
3
+ ## Type scale (web)
4
+
5
+ | Role | Tailwind | Notes |
6
+ | --- | --- | --- |
7
+ | Hero heading | `text-5xl sm:text-7xl font-bold leading-[1.02] tracking-tight` | one per page |
8
+ | Page / section heading | `text-3xl sm:text-4xl font-bold tracking-tight` | |
9
+ | Subsection | `text-xl font-semibold` | |
10
+ | Lede | `text-lg sm:text-xl text-<muted>` | under the hero heading |
11
+ | Body | `text-base leading-relaxed` (16px) | never smaller for running copy |
12
+ | Secondary | `text-sm text-<muted>` | captions, metadata, table cells |
13
+ | Eyebrow / label | `text-xs font-semibold uppercase tracking-[0.2em]` | above headings |
14
+ | Code | `font-mono text-[0.9em]` with a subtle background | |
15
+
16
+ - Line-height: tight (`leading-[1.05]`–`leading-tight`) for display sizes,
17
+ `leading-relaxed` (1.625) for body.
18
+ - Measure: cap prose at `max-w-[65ch]` / `max-w-2xl`.
19
+ - Numbers in tables and prices: `tabular-nums`.
20
+ - Fonts: the system stack is the default and is fine. Register a display or
21
+ brand font only when the user names one — see `assets-and-fonts.md`.
22
+
23
+ ## Palette structure
24
+
25
+ One page, one palette. Name the roles up front and reuse them literally:
26
+
27
+ | Role | Light example | Dark example |
28
+ | --- | --- | --- |
29
+ | background | `bg-white` | `bg-[#0b0b10]` |
30
+ | surface | `bg-slate-50` / `bg-white` cards with `border-slate-200` | `bg-white/[0.04]` with `border-white/10` |
31
+ | text | `text-slate-900` | `text-white` |
32
+ | muted | `text-slate-600` (never lighter than `slate-500` on white) | `text-white/60` |
33
+ | accent | one hue, one shade for fills (`bg-indigo-600`) and one for text (`text-indigo-600`) | `bg-emerald-400 text-black` |
34
+ | border | `border-slate-200` | `border-white/10` |
35
+
36
+ - Define the palette as repeated utilities or as a small `const` map of class
37
+ strings when a page uses many surfaces. Do not build class names at runtime.
38
+ - Accent is for actions and one highlight per screen. Two accents means no
39
+ accent.
40
+ - Dark pages: prefer near-black (`#0b0b10`, `#111`) over pure black; lift
41
+ surfaces with translucent white (`bg-white/[0.03]`), not grey hex soup.
42
+
43
+ ## Contrast
44
+
45
+ - Body text ≥ 4.5:1 against its background; large headings ≥ 3:1.
46
+ - Muted text on white: `slate-500` is the floor. On dark: `white/60` is the
47
+ floor; `white/40` only for decorative metadata.
48
+ - Accent text on white must be a 600+ shade (`indigo-600`, `emerald-700`).
49
+ `emerald-400` text on white fails.
50
+ - Links inside prose: underline or a clearly different color, not color alone
51
+ at low contrast.
52
+
53
+ ## Anti-patterns
54
+
55
+ - ❌ Body text under 16px, or `text-xs` for anything the user must read.
56
+ - ❌ Three font families. Two is the ceiling (display + body).
57
+ - ❌ Pure black on pure white for long text (`text-slate-900` on white reads
58
+ better); pure white on pure black for dark pages.
59
+ - ❌ Gradient text, drop shadows, and glows on every heading. One flourish, once.
60
+ - ❌ Palette drift: a new grey shade every section.
@@ -0,0 +1,31 @@
1
+ # open-pages — Agent Guide
2
+
3
+ You are authoring **web pages** in this repo. Every page is a React component rendered as a real web page — HTML JSX 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
+
5
+ ## Hard rules
6
+
7
+ - Put your page under `pages/<kebab-case-id>/`.
8
+ - The entry is `pages/<id>/index.tsx` (or `pages/<id>/index.html`).
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
+ - Do **not** touch `package.json`, `open-pages.config.ts`, or other pages.
11
+ - Do not add dependencies. Use only `react`, `react-dom`, and standard web APIs.
12
+
13
+ ## Which skill to use
14
+
15
+ - **Drafting a new page** — use the `create-page` skill. It walks through scoping questions, structure, and hand-off.
16
+ - **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. Themes live as markdown under `themes/<id>.md` (with a `<id>.demo.tsx` preview) and are read by `create-page` before authoring.
18
+ - **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
+ - **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
+
21
+ Keep this file short: hard rules only. All deeper guidance lives in the skills above.
22
+
23
+ ## Updating skills
24
+
25
+ The skills above are managed by `@autono/open-pages`. Do not edit them in place. To pull the latest versions:
26
+
27
+ ```
28
+ npm run update
29
+ ```
30
+
31
+ `npm run dev` will also detect drift on startup and offer to sync. `npx open-pages sync:skills --dry-run` previews changes without writing.
@@ -0,0 +1,76 @@
1
+ # open-pages workspace
2
+
3
+ Web pages as React components. Each page lives under `pages/<id>/index.tsx` and default-exports one component. The `@autono/open-pages` runtime handles Vite, React, Tailwind, the live preview, and the inspector — you just write the page.
4
+
5
+ ## Getting started
6
+
7
+ ```bash
8
+ npm install
9
+ npm run dev
10
+ ```
11
+
12
+ Then open `http://localhost:5173`, edit `pages/getting-started/index.tsx`, or create a new page at `pages/<your-page>/index.tsx`. Each page previews at `http://localhost:5173/p/<id>`.
13
+
14
+ ## Scripts
15
+
16
+ | Command | Description |
17
+ | --- | --- |
18
+ | `npm run dev` | Start the dev server with live preview and hot reload. |
19
+ | `npm run build` | Build the whole workspace viewer as a static site. |
20
+ | `npm run export` | Build pages into `export/<id>/`, one deployable folder per page. |
21
+ | `npm run preview` | Preview the built workspace locally. |
22
+ | `npm run sync:skills` | Sync the bundled agent skills into the workspace. |
23
+ | `npm run update` | Update `@autono/open-pages` and sync skills. |
24
+
25
+ ## Authoring a page
26
+
27
+ ```tsx
28
+ // pages/my-page/index.tsx
29
+ import type { PageMeta } from '@autono/open-pages';
30
+
31
+ export const meta: PageMeta = {
32
+ title: 'My page',
33
+ createdAt: '2026-08-28T00:00:00.000Z',
34
+ };
35
+
36
+ export default function MyPage() {
37
+ return (
38
+ <main className="mx-auto max-w-2xl px-6 py-24">
39
+ <h1 className="text-4xl font-bold tracking-tight">Hello</h1>
40
+ <p className="mt-4 text-slate-600">Tailwind via className, hooks, state, all of it.</p>
41
+ </main>
42
+ );
43
+ }
44
+ ```
45
+
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/...`.
47
+
48
+ 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
+
50
+ See [`AGENTS.md`](./AGENTS.md) for the rules your agent follows.
51
+
52
+ ## The viewer
53
+
54
+ - Toolbar toggles between desktop, tablet (820px), and mobile (390px) widths.
55
+ - `i` toggles Inspect mode: click any element to see its source line and leave a comment for your agent.
56
+ - **Open** shows the page by itself in a new tab.
57
+
58
+ ## Agent integration
59
+
60
+ This workspace ships agent skills under `.agents/skills/` (symlinked into `.claude/skills/`). Ask your agent to "make a landing page for X" and the `create-page` skill takes over. Leave comments in Inspect mode and ask for `apply-comments` to iterate.
61
+
62
+ ## Config
63
+
64
+ Optional `open-pages.config.ts` at the workspace root:
65
+
66
+ ```ts
67
+ import type { OpenPagesConfig } from '@autono/open-pages';
68
+
69
+ const openPagesConfig: OpenPagesConfig = {
70
+ port: 5173,
71
+ };
72
+
73
+ export default openPagesConfig;
74
+ ```
75
+
76
+ Supported fields: `pagesDir`, `themesDir`, `assetsDir`, `port`, `base`, `allowedHosts`, `build`.
File without changes
@@ -0,0 +1,4 @@
1
+ [[redirects]]
2
+ from = "/*"
3
+ to = "/index.html"
4
+ status = 200
@@ -0,0 +1,5 @@
1
+ import type { OpenPagesConfig } from '@autono/open-pages';
2
+
3
+ const openPagesConfig: OpenPagesConfig = {};
4
+
5
+ export default openPagesConfig;
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "playground",
3
+ "private": true,
4
+ "version": "0.0.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "open-pages dev",
8
+ "build": "open-pages build",
9
+ "export": "open-pages export",
10
+ "preview": "open-pages preview",
11
+ "sync:skills": "open-pages sync:skills",
12
+ "update": "open-pages update"
13
+ },
14
+ "dependencies": {
15
+ "@autono/open-pages": "^0.0.6",
16
+ "react": "^18.3.1",
17
+ "react-dom": "^18.3.1"
18
+ },
19
+ "devDependencies": {
20
+ "@types/react": "^18.3.12",
21
+ "@types/react-dom": "^18.3.1",
22
+ "vite": "^5.4.10"
23
+ }
24
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ "folders": [],
3
+ "assignments": {}
4
+ }
@@ -0,0 +1,90 @@
1
+ import type { PageMeta } from '@autono/open-pages';
2
+ import { useState } from 'react';
3
+
4
+ export const meta: PageMeta = {
5
+ title: 'Welcome to open-pages',
6
+ description: 'The web page framework built for agents.',
7
+ createdAt: '2026-08-28T00:00:00.000Z',
8
+ };
9
+
10
+ const steps = [
11
+ {
12
+ title: 'Describe',
13
+ body: 'Tell your agent what the page is. It runs /create-page and writes the React.',
14
+ },
15
+ {
16
+ title: 'Preview',
17
+ body: 'This workspace renders the real page in a real browser tab on every save.',
18
+ },
19
+ {
20
+ title: 'Annotate',
21
+ body: 'Press i, click anything, leave a note. It lands in the source as a comment marker.',
22
+ },
23
+ {
24
+ title: 'Ship',
25
+ body: 'Your agent runs /apply-comments. open-pages export writes a static folder you can deploy anywhere.',
26
+ },
27
+ ];
28
+
29
+ export default function GettingStarted() {
30
+ const [active, setActive] = useState(0);
31
+
32
+ return (
33
+ <main className="min-h-screen bg-white text-slate-900 antialiased">
34
+ <section className="mx-auto max-w-3xl px-6 pt-24 pb-16">
35
+ <span className="text-xs font-semibold uppercase tracking-[0.2em] text-indigo-600">
36
+ open-pages
37
+ </span>
38
+ <h1 className="mt-4 text-5xl font-bold leading-[1.05] tracking-tight">
39
+ The web page framework built for agents
40
+ </h1>
41
+ <p className="mt-6 max-w-xl text-lg leading-relaxed text-slate-600">
42
+ This page is a React component at{' '}
43
+ <code className="rounded bg-slate-100 px-1.5 py-0.5 font-mono text-[0.9em]">
44
+ pages/getting-started/index.tsx
45
+ </code>
46
+ . Your coding agent writes it, the workspace previews it live, and the export is plain
47
+ HTML, CSS, and JS.
48
+ </p>
49
+ </section>
50
+
51
+ <section className="mx-auto max-w-3xl px-6 pb-24">
52
+ <div className="grid gap-3 sm:grid-cols-4">
53
+ {steps.map((step, i) => (
54
+ <button
55
+ key={step.title}
56
+ type="button"
57
+ onClick={() => setActive(i)}
58
+ aria-pressed={active === i}
59
+ className={
60
+ active === i
61
+ ? 'rounded-lg border border-indigo-600 bg-indigo-600 px-4 py-3 text-left text-white'
62
+ : 'rounded-lg border border-slate-200 px-4 py-3 text-left transition-colors hover:border-slate-400'
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>
68
+ ))}
69
+ </div>
70
+ <p className="mt-6 min-h-[3.5rem] text-base leading-relaxed text-slate-700">
71
+ {steps[active].body}
72
+ </p>
73
+
74
+ <div className="mt-16 rounded-xl bg-slate-50 p-6">
75
+ <h2 className="text-sm font-semibold uppercase tracking-wider text-slate-500">
76
+ Try the loop
77
+ </h2>
78
+ <ol className="mt-3 space-y-2 text-slate-700">
79
+ <li>1. Change any text in this file and watch the preview update.</li>
80
+ <li>2. Switch the viewport to mobile in the toolbar. The layout is responsive.</li>
81
+ <li>
82
+ 3. Ask your agent for something bigger: a landing page, a pricing table, a whole new
83
+ page with <code className="font-mono">/create-page</code>.
84
+ </li>
85
+ </ol>
86
+ </div>
87
+ </section>
88
+ </main>
89
+ );
90
+ }
File without changes
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "jsx": "react-jsx",
8
+ "resolveJsonModule": true,
9
+ "isolatedModules": true,
10
+ "moduleDetection": "force",
11
+ "noEmit": true,
12
+ "strict": true,
13
+ "skipLibCheck": true,
14
+ "types": ["@autono/open-pages/env"]
15
+ },
16
+ "include": ["pages/**/*", "open-pages.config.ts"]
17
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "rewrites": [{ "source": "/(.*)", "destination": "/index.html" }]
3
+ }