proto-plugin 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.
- package/AGENTS.md +350 -0
- package/README.md +279 -0
- package/components.json +18 -0
- package/package.json +73 -0
- package/scripts/download-mobbin-reference-images.mjs +112 -0
- package/scripts/lib/host-config.example.sh +48 -0
- package/scripts/lib/host-config.sh +25 -0
- package/scripts/lib/resolve-host-root.mjs +18 -0
- package/scripts/lib/source-path.sh +49 -0
- package/scripts/link-source-db.sh +128 -0
- package/scripts/link-source.sh +40 -0
- package/scripts/publish-package.sh +147 -0
- package/scripts/share-prototype.sh +279 -0
- package/scripts/sync-from-source.sh +74 -0
- package/scripts/verify-prototype-component-ids.mjs +151 -0
- package/scripts/verify-prototype-preview-states.mjs +135 -0
- package/src/app.ts +4 -0
- package/src/components/platform-ui/code-block.tsx +21 -0
- package/src/components/platform-ui/controls-panel-options.tsx +71 -0
- package/src/components/platform-ui/controls-panel-select.tsx +438 -0
- package/src/components/platform-ui/empty-state.tsx +15 -0
- package/src/components/platform-ui/icon-button.tsx +18 -0
- package/src/components/platform-ui/panel-select.tsx +123 -0
- package/src/components/platform-ui/panel.tsx +97 -0
- package/src/components/platform-ui/review-dropdown-menu.tsx +35 -0
- package/src/components/platform-ui/sidebar.tsx +293 -0
- package/src/components/platform-ui/toolbar-icon-button.tsx +34 -0
- package/src/components/platform-ui/toolbar.tsx +37 -0
- package/src/components/prototype-gallery-client.tsx +57 -0
- package/src/components/prototype-provider.tsx +20 -0
- package/src/components/prototypes/mini-pill-label.tsx +37 -0
- package/src/components/prototypes/prototype-change-log-panel.tsx +207 -0
- package/src/components/prototypes/prototype-comment-provider.tsx +61 -0
- package/src/components/prototypes/prototype-comment-toolbar.tsx +65 -0
- package/src/components/prototypes/prototype-control.tsx +31 -0
- package/src/components/prototypes/prototype-controls.tsx +553 -0
- package/src/components/prototypes/prototype-create-exploration-modal.tsx +117 -0
- package/src/components/prototypes/prototype-create-state-modal.tsx +117 -0
- package/src/components/prototypes/prototype-default-state-map-page.tsx +66 -0
- package/src/components/prototypes/prototype-design-brief-modal.tsx +128 -0
- package/src/components/prototypes/prototype-design-brief-panel.tsx +525 -0
- package/src/components/prototypes/prototype-design-context-panel.tsx +65 -0
- package/src/components/prototypes/prototype-floating-pill.module.scss +1341 -0
- package/src/components/prototypes/prototype-mobbin-gallery.tsx +330 -0
- package/src/components/prototypes/prototype-reference-docs.tsx +222 -0
- package/src/components/prototypes/prototype-review-chrome.module.scss +630 -0
- package/src/components/prototypes/prototype-review-chrome.tsx +1241 -0
- package/src/components/prototypes/prototype-review-dropdown-menu-item.tsx +1 -0
- package/src/components/prototypes/prototype-review-dropdown-menu-separator.tsx +1 -0
- package/src/components/prototypes/prototype-review-panel-menu-item.tsx +1 -0
- package/src/components/prototypes/prototype-review-panel-menu-separator.tsx +1 -0
- package/src/components/prototypes/prototype-review-panel-select.tsx +4 -0
- package/src/components/prototypes/prototype-review-sidebar.tsx +167 -0
- package/src/components/prototypes/prototype-share-link-restore.tsx +75 -0
- package/src/components/prototypes/prototype-share-mode.tsx +206 -0
- package/src/components/prototypes/prototype-spec-panel-content.tsx +538 -0
- package/src/components/prototypes/prototype-state-canvas-overlay.module.scss +336 -0
- package/src/components/prototypes/prototype-state-canvas-overlay.tsx +1023 -0
- package/src/components/prototypes/prototype-state-canvas.tsx +38 -0
- package/src/components/prototypes/prototype-state-screenshot-preview.tsx +47 -0
- package/src/components/prototypes/prototype-target.tsx +120 -0
- package/src/components/prototypes/prototype-tweak-highlight.tsx +132 -0
- package/src/components/prototypes/prototype-tweaks.tsx +48 -0
- package/src/components/prototypes/prototype-variant-explorer.tsx +347 -0
- package/src/components/prototypes/prototype-variant-rationale-panel.tsx +49 -0
- package/src/components/prototypes/prototype-variant-tabs.tsx +207 -0
- package/src/components/prototypes/prototype-vercel-preview-modal.tsx +120 -0
- package/src/components/prototypes/state-map-annotation-tooltip.module.scss +89 -0
- package/src/components/prototypes/state-map-annotation-tooltip.tsx +137 -0
- package/src/components/prototypes/state-map-wireframe-highlight.module.scss +25 -0
- package/src/components/prototypes/state-map-wireframe-highlight.tsx +82 -0
- package/src/components/shell/prototype-gallery-shell.tsx +79 -0
- package/src/components/shell/prototype-screenshot-capture.tsx +45 -0
- package/src/components/shell/prototype-shell.module.scss +194 -0
- package/src/components/shell/prototype-shell.tsx +160 -0
- package/src/components/shell/prototype-state-screenshot-capture.tsx +68 -0
- package/src/components/ui/button.tsx +58 -0
- package/src/components/ui/dialog.module.scss +81 -0
- package/src/components/ui/dialog.tsx +127 -0
- package/src/components/ui/dropdown-menu.tsx +200 -0
- package/src/components/ui/input.tsx +22 -0
- package/src/components/ui/label.tsx +26 -0
- package/src/components/ui/option-select.tsx +81 -0
- package/src/components/ui/scroll-area.tsx +48 -0
- package/src/components/ui/separator.tsx +31 -0
- package/src/components/ui/slider.tsx +28 -0
- package/src/components/ui/switch.tsx +29 -0
- package/src/components/ui/tabs.tsx +55 -0
- package/src/components/ui/toggle-group.tsx +80 -0
- package/src/components/ui/tooltip.tsx +32 -0
- package/src/config/create-prototype-gallery-page.tsx +65 -0
- package/src/config/create-prototype-host-app.tsx +121 -0
- package/src/config/create-prototype-page.tsx +41 -0
- package/src/config/create-prototype-site-layout.tsx +28 -0
- package/src/config/define-prototype-config.ts +7 -0
- package/src/config/prototype-icon.tsx +25 -0
- package/src/config/prototype-site-layout-client.tsx +35 -0
- package/src/config/with-prototype.ts +20 -0
- package/src/index.ts +303 -0
- package/src/lib/pr-split/build-pr-agent-prompt.ts +68 -0
- package/src/lib/pr-split/build-pr-split-prototype-url.ts +12 -0
- package/src/lib/pr-split/pr-split-highlight.ts +6 -0
- package/src/lib/pr-split/pr-split-types.ts +58 -0
- package/src/lib/pr-split/resolve-source-preview-url.ts +45 -0
- package/src/lib/pr-split/use-pr-vercel-previews.ts +69 -0
- package/src/lib/prototype-comments/core/annotation-channel.ts +41 -0
- package/src/lib/prototype-comments/core/annotation-status.ts +60 -0
- package/src/lib/prototype-comments/core/annotation-target.ts +567 -0
- package/src/lib/prototype-comments/core/capture-theme.ts +41 -0
- package/src/lib/prototype-comments/core/capture.ts +11 -0
- package/src/lib/prototype-comments/core/comment-capture-blocked.ts +47 -0
- package/src/lib/prototype-comments/core/comment-threads.ts +52 -0
- package/src/lib/prototype-comments/core/element-identification.ts +615 -0
- package/src/lib/prototype-comments/core/export.ts +35 -0
- package/src/lib/prototype-comments/core/freeze-animations.ts +266 -0
- package/src/lib/prototype-comments/core/identify-element.ts +76 -0
- package/src/lib/prototype-comments/core/normalize-viewport.ts +35 -0
- package/src/lib/prototype-comments/core/react-detection.ts +704 -0
- package/src/lib/prototype-comments/core/restore.ts +7 -0
- package/src/lib/prototype-comments/core/screenshot.ts +428 -0
- package/src/lib/prototype-comments/core/source-location.ts +906 -0
- package/src/lib/prototype-comments/core/storage.ts +80 -0
- package/src/lib/prototype-comments/core/types.ts +79 -0
- package/src/lib/prototype-comments/core/validation.ts +17 -0
- package/src/lib/prototype-comments/hooks/useLayoutShift.ts +61 -0
- package/src/lib/prototype-comments/index.ts +58 -0
- package/src/lib/prototype-comments/react/CommentCaptureToolbar.tsx +1398 -0
- package/src/lib/prototype-comments/react/CommentProvider.tsx +298 -0
- package/src/lib/prototype-comments/scss.d.ts +10 -0
- package/src/lib/prototype-comments/ui/CommentAnnotationOverlay.tsx +253 -0
- package/src/lib/prototype-comments/ui/CommentDetailPage.tsx +56 -0
- package/src/lib/prototype-comments/ui/CommentHeaderCount.tsx +28 -0
- package/src/lib/prototype-comments/ui/CommentThread.tsx +331 -0
- package/src/lib/prototype-comments/ui/CommentsGrid.tsx +780 -0
- package/src/lib/prototype-comments/ui/CommentsListPage.tsx +25 -0
- package/src/lib/prototype-comments/ui/CommentsSidebar.tsx +77 -0
- package/src/lib/prototype-comments/ui/annotation-marker/index.tsx +200 -0
- package/src/lib/prototype-comments/ui/annotation-marker/styles.module.scss +194 -0
- package/src/lib/prototype-comments/ui/annotation-popup/index.tsx +335 -0
- package/src/lib/prototype-comments/ui/annotation-popup/styles.module.scss +469 -0
- package/src/lib/prototype-comments/ui/capture-styles.module.scss +2225 -0
- package/src/lib/prototype-comments/ui/comment-highlight.ts +48 -0
- package/src/lib/prototype-comments/ui/comment-thread.module.scss +203 -0
- package/src/lib/prototype-comments/ui/comments-grid-card.module.scss +253 -0
- package/src/lib/prototype-comments/ui/comments-sidebar.module.scss +123 -0
- package/src/lib/prototype-comments/ui/icon-transitions.module.scss +51 -0
- package/src/lib/prototype-comments/ui/icons.tsx +1086 -0
- package/src/lib/prototype-comments/ui/is-comment-detail-path.ts +7 -0
- package/src/lib/prototypes/capture-prototype-viewport.ts +32 -0
- package/src/lib/prototypes/changelog-meta-context.tsx +162 -0
- package/src/lib/prototypes/changelog-meta-storage.ts +62 -0
- package/src/lib/prototypes/changelog-meta.ts +95 -0
- package/src/lib/prototypes/create-prototype-registry.ts +74 -0
- package/src/lib/prototypes/create-state-screenshot-thumbnail.ts +46 -0
- package/src/lib/prototypes/design-exploration-default-storage.ts +68 -0
- package/src/lib/prototypes/design-exploration-default.ts +51 -0
- package/src/lib/prototypes/design-exploration-types.ts +203 -0
- package/src/lib/prototypes/prototype-comment-registry.tsx +145 -0
- package/src/lib/prototypes/prototype-comment-review-bridge.tsx +40 -0
- package/src/lib/prototypes/prototype-comment-review-state.ts +57 -0
- package/src/lib/prototypes/prototype-component-registry.ts +40 -0
- package/src/lib/prototypes/prototype-config-types.ts +34 -0
- package/src/lib/prototypes/prototype-preview-state-registry.ts +443 -0
- package/src/lib/prototypes/prototype-preview-state-types.ts +89 -0
- package/src/lib/prototypes/prototype-review-context.tsx +905 -0
- package/src/lib/prototypes/prototype-review-url.ts +134 -0
- package/src/lib/prototypes/prototype-share-link.ts +175 -0
- package/src/lib/prototypes/prototype-state-canvas-constants.ts +118 -0
- package/src/lib/prototypes/prototype-state-canvas-types.ts +159 -0
- package/src/lib/prototypes/prototype-state-screenshot.ts +39 -0
- package/src/lib/prototypes/prototype-tweak-registry.ts +96 -0
- package/src/lib/prototypes/prototype-tweak-types.ts +31 -0
- package/src/lib/prototypes/reference-docs.ts +137 -0
- package/src/lib/prototypes/screenshot-manifest.ts +33 -0
- package/src/lib/prototypes/screenshot-src.ts +7 -0
- package/src/lib/prototypes/share-command.ts +8 -0
- package/src/lib/prototypes/state-map-annotation.ts +70 -0
- package/src/lib/prototypes/use-design-exploration-default.ts +114 -0
- package/src/lib/prototypes/use-persisted-local-state.ts +140 -0
- package/src/lib/prototypes/use-prototype-comments.ts +63 -0
- package/src/lib/prototypes/use-prototype-mobile-viewport-frame.ts +46 -0
- package/src/lib/prototypes/use-prototype-state-screenshot-src.ts +71 -0
- package/src/lib/prototypes/use-prototype-tool-theme.tsx +115 -0
- package/src/lib/prototypes/use-prototype-viewport-frame.ts +34 -0
- package/src/lib/prototypes/use-register-prototype-reference-docs.ts +16 -0
- package/src/lib/prototypes/use-snap-corner-position.ts +417 -0
- package/src/lib/prototypes/use-toolbar-hover-panel.ts +98 -0
- package/src/lib/prototypes/variant-set-lucide-icon.tsx +55 -0
- package/src/lib/tool-portal.ts +33 -0
- package/src/lib/use-copy-to-clipboard.ts +81 -0
- package/src/lib/utils.ts +6 -0
- package/src/lib/vercel-preview/parse-vercel-github-comment.ts +81 -0
- package/src/server/create-host-api-route.ts +100 -0
- package/src/server/create-prototype-api-routes.ts +428 -0
- package/src/server/gallery/create-gallery-api.ts +56 -0
- package/src/server/gallery/folders-route.ts +156 -0
- package/src/server/gallery/gallery-env.ts +39 -0
- package/src/server/gallery/gallery-route.ts +150 -0
- package/src/server/gallery/gallery-types.ts +15 -0
- package/src/server/gallery/image-route.ts +59 -0
- package/src/server/gallery/item-route.ts +92 -0
- package/src/server/pr-vercel-preview-route.ts +162 -0
- package/src/server/redis/client.ts +55 -0
- package/src/server/redis/prototype-changelog-meta.ts +31 -0
- package/src/server/redis/prototype-comments.ts +92 -0
- package/src/server/redis/prototype-design-exploration-default.ts +32 -0
- package/src/server.ts +51 -0
- package/src/styles/globals.css +624 -0
- package/tsconfig.json +19 -0
package/AGENTS.md
ADDED
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Instructions for AI agents working with `prototype` and host-app prototypes.
|
|
4
|
+
|
|
5
|
+
## Scope in host repos
|
|
6
|
+
|
|
7
|
+
Unless `DEVELOPER=true` is set in `.env.local`, agent work scope in a **host app** (e.g. `your-host-app`) is `**src/prototypes/<slug>/` only**. Do not modify prototype package code (`packages/prototype/`), app routing, or shared UI unless explicitly developing the prototype package.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Architecture
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
| Layer | Location | Notes |
|
|
15
|
+
| ---------------------- | ----------------------------------------------------------------------- | ---------------------------------------------------------------- |
|
|
16
|
+
| **Prototype** | `packages/prototype/` | Shell, comments, variant explorer, gallery client, verify script |
|
|
17
|
+
| **Host prototypes** | `src/prototypes/<slug>/` | Feature UI, mock data, `component-ids.ts` |
|
|
18
|
+
| **Host manifest** | `prototype.config.ts` | Registers all prototypes |
|
|
19
|
+
| **Host design system** | `src/app/globals.css`, `@/components/ui` | Synced from source; host prototypes only |
|
|
20
|
+
| **Tool design system** | Host `globals.css`, `src/components/ui/`, `src/components/platform-ui/` | Uses host tokens; shadcn primitives + tool chrome composites |
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
Host prototypes import framework from `prototype` and UI from `@/components/ui`.
|
|
24
|
+
|
|
25
|
+
**Prototype package code must never import `@/components/ui` or `@/lib/utils` from the host.** Use `@prototype/components/ui`, `@prototype/components/platform-ui`, and `@prototype/lib/utils` only.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Relationship to source app (host apps)
|
|
30
|
+
|
|
31
|
+
Host apps replicate product UI from the **source application** (linked read-only via `SOURCE_PATH` and `pnpm link-source`) **exactly** — standalone code, no runtime imports from the source monorepo.
|
|
32
|
+
|
|
33
|
+
### What is synced vs replicated
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
| Layer | Source | Runtime import from source? |
|
|
37
|
+
| ----------------------- | -------------------------------------------------------- | --------------------------- |
|
|
38
|
+
| Design tokens + base UI | Synced → `@/components/ui`, `globals.css` | No |
|
|
39
|
+
| Feature/page UI | Replicated → `src/prototypes/<slug>/_components/` | No |
|
|
40
|
+
| Data / auth / routing | Mock constants + local state | No |
|
|
41
|
+
| Source reference | `source/` symlink (`SOURCE_PATH` + `pnpm link-source`) | Read-only |
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
**Synced** via `pnpm sync-from-source`: `globals.css` (host only), fonts, `src/components/ui/`, shared utils.
|
|
45
|
+
|
|
46
|
+
**Replicated per prototype**: page components, layout shells, form/section layout, mock data.
|
|
47
|
+
|
|
48
|
+
### Source sync config (`prototype.sync.config.sh`)
|
|
49
|
+
|
|
50
|
+
The sync/link scripts are host-agnostic — package code names nothing host-specific. The host declares everything in a `prototype.sync.config.sh` at its repo root (the scripts error until it exists). Create it from the template at `scripts/lib/host-config.example.sh`. It declares:
|
|
51
|
+
|
|
52
|
+
- `SYNC_FILES`, `SYNC_DIRS`, `SYNC_GLOBS` — paths to copy from source (mirrored 1:1).
|
|
53
|
+
- `SYNC_LOCAL_EXTENSIONS` — components this host customizes beyond source; printed as a re-apply reminder since the sync overwrites them.
|
|
54
|
+
- `SOURCE_DB_ENV_VARS`, `SOURCE_DB_CONSOLE_URL` — env vars `link-source-db` copies from the source app's `.env.local`, and the console URL to print.
|
|
55
|
+
|
|
56
|
+
### How to build a prototype from source
|
|
57
|
+
|
|
58
|
+
1. Link source: `SOURCE_PATH` in `.env.local`, run `pnpm link-source`. (First-time setup: create `prototype.sync.config.sh` from `scripts/lib/host-config.example.sh`.)
|
|
59
|
+
2. Find the real page in source and read it fully.
|
|
60
|
+
3. Trace imports; classify as base UI (`@/components/ui`), shared util, context-bound (mock), or layout chrome (`Mock`*).
|
|
61
|
+
4. Copy render logic, not infrastructure — preserve class names, layout, semantic tokens.
|
|
62
|
+
5. Mock data as typed constants matching screenshots/source fixtures.
|
|
63
|
+
6. Look up dimensions from source — do not guess.
|
|
64
|
+
7. Wire prototype infrastructure (checklist below).
|
|
65
|
+
8. Run `pnpm verify:prototype-ids`.
|
|
66
|
+
|
|
67
|
+
Default to **mock data only**.
|
|
68
|
+
|
|
69
|
+
Reference prototype: `example-feature` — `src/prototypes/example-feature/` (or any registered slug in your host app).
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Prototypes (`src/prototypes/`)
|
|
74
|
+
|
|
75
|
+
Shareable UI at `/prototypes/[slug]`. Registered in `prototype.config.ts`.
|
|
76
|
+
|
|
77
|
+
**Every UI component must be comment-anchorable** — enforced by `pnpm verify:prototype-ids`.
|
|
78
|
+
|
|
79
|
+
### Rules (mandatory)
|
|
80
|
+
|
|
81
|
+
1. **Register** the slug in `prototype.config.ts` and add a screenshot under `public/prototypes/screenshots/`.
|
|
82
|
+
2. **Create** `src/prototypes/<slug>/component-ids.ts` — every component target id (see `example-feature/component-ids.ts`).
|
|
83
|
+
3. **Wire comments** with `usePrototypeComments` on the page (see `example-feature/index.tsx`).
|
|
84
|
+
4. **Wrap the root JSX of every React component** in `PrototypeComponent` from `prototype`.
|
|
85
|
+
5. **On-page prototype controls** (state pickers, variant tabs, preview toggles) must use `PrototypeControl` or `PrototypeControlGroup`, not plain `PrototypeComponent`.
|
|
86
|
+
6. **Use ids from the registry only** — dev mode logs an error for unregistered ids.
|
|
87
|
+
7. **Id naming:**
|
|
88
|
+
- File's main export: kebab-case filename (`settings-section.tsx` → `settings-section`; `index.tsx` → `page`).
|
|
89
|
+
- Other functions in the same file: `{filename}.{function-kebab}`.
|
|
90
|
+
- Dynamic list items: add a prefix to `dynamicPrefixes` in `component-ids.ts`.
|
|
91
|
+
8. **Scroll container:** `PrototypeComponent` with `id="scroll-container"` on the main `overflow-y-auto` wrapper.
|
|
92
|
+
9. **Do not** use `data-testid` for comment anchoring.
|
|
93
|
+
|
|
94
|
+
### Examples
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
import { PrototypeComponent } from "prototype";
|
|
98
|
+
|
|
99
|
+
export function SettingsSection(props: SettingsSectionProps) {
|
|
100
|
+
return (
|
|
101
|
+
<PrototypeComponent id="settings-section" className="...">
|
|
102
|
+
...
|
|
103
|
+
</PrototypeComponent>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
```tsx
|
|
109
|
+
import { PrototypeControl } from "prototype";
|
|
110
|
+
|
|
111
|
+
export function PrototypePreviewStateSelect(...) {
|
|
112
|
+
return (
|
|
113
|
+
<PrototypeControl id="prototype-preview-state-select" className="flex items-center gap-2">
|
|
114
|
+
...
|
|
115
|
+
</PrototypeControl>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### New prototype checklist
|
|
121
|
+
|
|
122
|
+
1. Identify the source page/feature and confirm visual parity.
|
|
123
|
+
2. Create `src/prototypes/<slug>/` with a default export page component.
|
|
124
|
+
3. Add `component-ids.ts` — exhaustive static id list + `dynamicPrefixes`.
|
|
125
|
+
4. Register in `prototype.config.ts` with `componentRegistry`.
|
|
126
|
+
5. Wrap every UI component in `PrototypeComponent` / `PrototypeControl`.
|
|
127
|
+
6. Call `usePrototypeComments(liveState, onRestore)` on the page.
|
|
128
|
+
7. Run `pnpm verify:prototype-ids`.
|
|
129
|
+
8. Capture screenshot; share via `pnpm share-prototype <slug>`.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Preview states & state map
|
|
134
|
+
|
|
135
|
+
Prototypes with preview modes use `definePreviewStateRegistry` in `*-preview-states.ts`. One registry drives the state picker, map nodes, `edges`, and sections.
|
|
136
|
+
|
|
137
|
+
### State map layout
|
|
138
|
+
|
|
139
|
+
Edge paths draw directly between node anchors (straight or elbow segments). They **do not route around** other states.
|
|
140
|
+
|
|
141
|
+
When two states are connected by an `edges` entry, arrange `canvasLayout.rows` so **no unrelated state sits on the path between them**. Otherwise the connector passes through the intervening card — arrows only render at path endpoints, so the middle segment looks directionless and the link reads ambiguously.
|
|
142
|
+
|
|
143
|
+
Prefer adjacent columns on the same row, or use `{ id, column }` / `startColumn` to offset nodes so vertical edges do not cut through unrelated cards in the same column.
|
|
144
|
+
|
|
145
|
+
Reference: `src/prototypes/example-feature/_components/list-preview-states.ts`.
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Design exploration
|
|
150
|
+
|
|
151
|
+
Use when comparing **2+ UI directions** for the same user problem.
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
| Layer | Location | Owns |
|
|
155
|
+
| ------------- | ------------------------------------------------------ | -------------------------------------------------------------------------------------------- |
|
|
156
|
+
| **Tool** | `prototype` (`PrototypeVariantExplorer`, etc.) | Modal chrome, variant tabs, rationale popover, Mobbin gallery, localStorage for brief fields |
|
|
157
|
+
| **Prototype** | `src/prototypes/<slug>/_components/` | Variant renderers, copy, rationale, context JSON, Mobbin references, `component-ids.ts` |
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
Reference: `example-feature/_components/no-data-design-exploration-config.tsx` + `no-data-variant-toggle.tsx`.
|
|
161
|
+
|
|
162
|
+
### Config shape
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
{
|
|
166
|
+
componentIdPrefix: string;
|
|
167
|
+
variantTabsIdPrefix: string;
|
|
168
|
+
storageKeyPrefix: string;
|
|
169
|
+
variant, onVariantChange,
|
|
170
|
+
options: { value, label, hint? }[];
|
|
171
|
+
rationale: Record<TVariant, { good, bad }>;
|
|
172
|
+
renderers: Record<TVariant, ComponentType>;
|
|
173
|
+
brief: { titleDefault, descriptionDefault };
|
|
174
|
+
context?: { label, data: unknown, render?, defaultExpanded?, panelId? };
|
|
175
|
+
mobbin?: { references, title?, description?, imagePathForReference? };
|
|
176
|
+
variantsSection?: { title?, description? };
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Iterating on variants
|
|
181
|
+
|
|
182
|
+
When asked to **modify an existing option**, add a **new variant** (do not replace in place), register ids, and update `DEFAULT_*_VARIANT`.
|
|
183
|
+
|
|
184
|
+
**Variant list order:** prepend each new entry to the top of `*_VARIANT_OPTIONS` (first item in the array). That order drives the design-brief sidebar/modal scroll view and variant tabs — newest explorations appear at the top.
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
| Prompt intent | Action |
|
|
188
|
+
| --------------------- | ----------------------------------------------- |
|
|
189
|
+
| Targeted modification | One new derivative variant; keep prior variants |
|
|
190
|
+
| Broad regeneration | New full set of variants |
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## PR split specs (implementation plan)
|
|
196
|
+
|
|
197
|
+
Use when a prototype ships as a **sequence of small source PRs** rather than one monolith. The review sidebar **Spec** panel lists each PR, previews its slice, and generates agent prompts.
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
| Layer | Location | Owns |
|
|
201
|
+
| ------------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
202
|
+
| **Tool** | `prototype` | `PrototypeSpecPanelContent`, `buildPrSplitPrototypeUrl`, `buildPrAgentPrompt`, Vercel preview fetch (`/api/pr-vercel-preview`), highlight tokens |
|
|
203
|
+
| **Prototype** | `src/prototypes/<slug>/_components/` | `PR_SPLIT_ENTRIES` data, `PR_SPLIT_CONFIG`, wireframe renderers, live-state URL wiring |
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
Reference: `example-feature/_components/pr-split-config.ts` + `pr-split-wireframes.tsx`.
|
|
207
|
+
|
|
208
|
+
### Host setup
|
|
209
|
+
|
|
210
|
+
1. Re-export the preview API route:
|
|
211
|
+
|
|
212
|
+
```ts
|
|
213
|
+
// src/app/api/pr-vercel-preview/route.ts
|
|
214
|
+
export { getPrVercelPreview as GET } from "prototype/server";
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
1. Set `GITHUB_TOKEN` (or rely on local `gh` CLI) so PR cards can resolve Vercel preview URLs.
|
|
218
|
+
|
|
219
|
+
### Prototype data (`pr-split-config.ts`)
|
|
220
|
+
|
|
221
|
+
Keep **only** prototype-specific config and entries in the host prototype:
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
import type { PrSplitConfig, PrSplitEntry as PrSplitEntryBase } from "prototype";
|
|
225
|
+
|
|
226
|
+
export type MyWireframeId = "sidebar" | "invite-form" | "member-list" | /* … */;
|
|
227
|
+
|
|
228
|
+
export type MyPrSplitEntry = PrSplitEntryBase<MyWireframeId, MyLiveState>;
|
|
229
|
+
|
|
230
|
+
export const PR_SPLIT_CONFIG: PrSplitConfig<MyLiveState> = {
|
|
231
|
+
slug: "my-slug",
|
|
232
|
+
seriesLabel: "My feature FE",
|
|
233
|
+
sourceRepo: "your-org/your-repo",
|
|
234
|
+
sourceWorkPath: "apps/web",
|
|
235
|
+
configFilePath: "src/prototypes/my-slug/_components/pr-split-config.ts",
|
|
236
|
+
branchName: (entry) => `feature/my-feature-fe-${entry.order}-…`,
|
|
237
|
+
writeEntryToSearchParams: (searchParams, entry) => {
|
|
238
|
+
// Write liveState into URL params (plus tool adds `prSplit=<order>`)
|
|
239
|
+
},
|
|
240
|
+
defaultPreviewPath: "/settings/team",
|
|
241
|
+
vercelProjectName: "source-app",
|
|
242
|
+
scopeNote: "Do not bundle unrelated work.",
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
export const PR_SPLIT_ENTRIES: MyPrSplitEntry[] = [
|
|
246
|
+
{
|
|
247
|
+
order: 1,
|
|
248
|
+
title: "…",
|
|
249
|
+
description: "…",
|
|
250
|
+
size: "Small" | "Medium" | "Large",
|
|
251
|
+
targetId: "my-slug.settings-section", // registered in component-ids.ts
|
|
252
|
+
liveState: { /* restores prototype when card is clicked */ },
|
|
253
|
+
wireframeId: "invite-form",
|
|
254
|
+
prUrl: "https://github.com/your-org/your-repo/pull/…", // after PR opens
|
|
255
|
+
branch: "…",
|
|
256
|
+
analyticsNotes: ["Event name"],
|
|
257
|
+
approved: true,
|
|
258
|
+
},
|
|
259
|
+
];
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
**Entry fields:**
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
| Field | Required | Purpose |
|
|
266
|
+
| ------------------------------ | -------------- | ------------------------------------------------------------------------------ |
|
|
267
|
+
| `order` | yes | Merge sequence (1, 2, 3…) |
|
|
268
|
+
| `title`, `description`, `size` | yes | Card copy + agent prompt |
|
|
269
|
+
| `targetId` | yes | Component to highlight (`focusShareTarget`) — must exist in `component-ids.ts` |
|
|
270
|
+
| `liveState` | yes | Prototype state restored when the card is selected |
|
|
271
|
+
| `wireframeId` | yes | Key into prototype wireframe registry |
|
|
272
|
+
| `prUrl`, `branch` | after PR opens | Sidebar links + dependency chain in prompts |
|
|
273
|
+
| `linearUrl` | optional | Linear issue link shown in the PR split sidebar |
|
|
274
|
+
| `previewPath` | optional | Path on Vercel preview host (default from config) |
|
|
275
|
+
| `vercelPreviewHost` | optional | Fallback when GitHub comment lookup fails |
|
|
276
|
+
| `analyticsNotes` | optional | Product analytics events for the agent prompt |
|
|
277
|
+
| `approved` | optional | Shows approved vs in-review badge |
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
### Wireframes (`pr-split-wireframes.tsx`)
|
|
281
|
+
|
|
282
|
+
Prototype-specific schematic thumbnails for each `wireframeId`. Pattern:
|
|
283
|
+
|
|
284
|
+
1. Define a `PageShell` (or layout scaffold) matching the prototype page structure.
|
|
285
|
+
2. Use low-fidelity `Wire` blocks — neutral grays for chrome, **highlighted** regions for the PR target.
|
|
286
|
+
3. Import highlight tokens from the tool: `PR_TARGET_HIGHLIGHT_BORDER`, `PR_TARGET_HIGHLIGHT_FILL`.
|
|
287
|
+
4. Register one renderer per `wireframeId` in a `Record<WireframeId, () => ReactNode>`.
|
|
288
|
+
5. Export `PrSplitWireframe` wrapped in `PrototypeComponent` (register id in `component-ids.ts`).
|
|
289
|
+
|
|
290
|
+
Highlighted areas must match what `targetId` points to on the real prototype.
|
|
291
|
+
|
|
292
|
+
### Page wiring (`index.tsx`)
|
|
293
|
+
|
|
294
|
+
1. Parse `?prSplit=<order>` on load; restore matching entry's `liveState`.
|
|
295
|
+
2. Sync `prSplit` param when selection changes.
|
|
296
|
+
3. Mount spec panel via review context:
|
|
297
|
+
|
|
298
|
+
```tsx
|
|
299
|
+
import {
|
|
300
|
+
PrototypeSpecPanelContent,
|
|
301
|
+
buildPrAgentPrompt,
|
|
302
|
+
} from "prototype";
|
|
303
|
+
|
|
304
|
+
setSpecContent(
|
|
305
|
+
<PrototypeSpecPanelContent
|
|
306
|
+
entries={PR_SPLIT_ENTRIES}
|
|
307
|
+
renderWireframe={(id) => <PrSplitWireframe id={id} embedded />}
|
|
308
|
+
buildAgentPrompt={(entry, origin) =>
|
|
309
|
+
buildPrAgentPrompt(entry, PR_SPLIT_ENTRIES, PR_SPLIT_CONFIG, origin)
|
|
310
|
+
}
|
|
311
|
+
onPrNavigate={handlePrNavigate}
|
|
312
|
+
selectedPrOrder={selectedPrOrder}
|
|
313
|
+
/>,
|
|
314
|
+
);
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
1. `handlePrNavigate` applies `entry.liveState` and calls `review.focusShareTarget(entry.targetId)`.
|
|
318
|
+
2. Register `"spec-panel-content"` in `component-ids.ts`.
|
|
319
|
+
|
|
320
|
+
### Agent workflow
|
|
321
|
+
|
|
322
|
+
1. Copy prompt from an unopened PR card (copy icon).
|
|
323
|
+
2. Implement in source app per prompt instructions.
|
|
324
|
+
3. Open PR → set `prUrl` and `branch` on the matching `PR_SPLIT_ENTRIES` item.
|
|
325
|
+
4. Later PR prompts automatically list prior PRs as dependencies.
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Comment system
|
|
330
|
+
|
|
331
|
+
- Storage: Upstash Redis key `prototype-comments:<slug>`
|
|
332
|
+
- Resolution: `targetId` → `querySelector` inside `[data-prototype-screenshot]`
|
|
333
|
+
- Library: `packages/prototype/src/lib/prototype-comments/`
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## Fidelity checklist
|
|
338
|
+
|
|
339
|
+
Before finishing, confirm side-by-side with source or a screenshot:
|
|
340
|
+
|
|
341
|
+
- Layout, spacing, typography, badge variants, empty/loading/error states
|
|
342
|
+
- All semantic tokens from `globals.css` — no hardcoded hex
|
|
343
|
+
- Interactive states behave like source where in scope
|
|
344
|
+
|
|
345
|
+
### Anti-patterns
|
|
346
|
+
|
|
347
|
+
- Importing from `source/` at runtime
|
|
348
|
+
- Reimplementing synced `@/components/ui` primitives
|
|
349
|
+
- Approximating layout dimensions or colors
|
|
350
|
+
|
package/README.md
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# prototype
|
|
2
|
+
|
|
3
|
+
Shared framework for building shareable UI prototypes in Next.js — review shell, comment anchoring, variant exploration, and the prototype home gallery.
|
|
4
|
+
|
|
5
|
+
Host apps keep **project-specific** code: prototypes under `src/prototypes/`, design tokens in `globals.css`, synced `@/components/ui`, and styleguide pages. The `prototype` package owns everything reusable across projects.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
From npm (public):
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm add proto-plugin
|
|
13
|
+
# or
|
|
14
|
+
npm install proto-plugin
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Host setup
|
|
18
|
+
|
|
19
|
+
1. **Register prototypes** in `prototype.config.ts` at the repo root:
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { definePrototypeConfig } from "proto-plugin";
|
|
23
|
+
import MyPrototype from "./src/prototypes/my-slug";
|
|
24
|
+
import { myComponentRegistry } from "./src/prototypes/my-slug/component-ids";
|
|
25
|
+
|
|
26
|
+
export default definePrototypeConfig({
|
|
27
|
+
prototypes: [
|
|
28
|
+
{
|
|
29
|
+
slug: "my-slug",
|
|
30
|
+
title: "My prototype",
|
|
31
|
+
screenshot: "/prototypes/screenshots/my-slug.png",
|
|
32
|
+
component: MyPrototype,
|
|
33
|
+
componentRegistry: myComponentRegistry,
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
2. **Gallery home** — `src/app/(platform-gallery)/page.tsx`:
|
|
40
|
+
|
|
41
|
+
```tsx
|
|
42
|
+
import { createPrototypeGalleryPage } from "proto-plugin";
|
|
43
|
+
import prototypeConfig from "../../../prototype.config";
|
|
44
|
+
|
|
45
|
+
export default createPrototypeGalleryPage(prototypeConfig);
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
3. **Prototype route** — `src/app/(source-prototype)/prototypes/[slug]/page.tsx`:
|
|
49
|
+
|
|
50
|
+
```tsx
|
|
51
|
+
import { createPrototypePage } from "proto-plugin";
|
|
52
|
+
import prototypeConfig from "../../../../../prototype.config";
|
|
53
|
+
|
|
54
|
+
const page = createPrototypePage(prototypeConfig);
|
|
55
|
+
export default page.default;
|
|
56
|
+
export const generateStaticParams = page.generateStaticParams;
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
4. **Next.js config** — transpile the package (use a relative import so CSS is not loaded during config evaluation):
|
|
60
|
+
|
|
61
|
+
```ts
|
|
62
|
+
import { withPrototype } from "./packages/prototype/src/config/with-prototype";
|
|
63
|
+
|
|
64
|
+
export default withPrototype({ nextConfig: { /* … */ } });
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
5. **Tailwind** — scan prototype package components from the host `globals.css`:
|
|
68
|
+
|
|
69
|
+
```css
|
|
70
|
+
@import "tailwindcss";
|
|
71
|
+
@source "../../packages/prototype/src/**/*.{js,ts,jsx,tsx}";
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
6. **tsconfig paths** (optional, for tool internal `@prototype/*` alias when developing the package):
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"compilerOptions": {
|
|
79
|
+
"paths": {
|
|
80
|
+
"proto-plugin": ["./packages/prototype/src/index.ts"],
|
|
81
|
+
"proto-plugin/server": ["./packages/prototype/src/server.ts"]
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Public API
|
|
88
|
+
|
|
89
|
+
| Export | Use |
|
|
90
|
+
| --- | --- |
|
|
91
|
+
| `definePrototypeConfig` | Register prototypes (sets global config as a side effect) |
|
|
92
|
+
| `createPrototypePage` | Factory for `/prototypes/[slug]` page + `generateStaticParams` |
|
|
93
|
+
| `createPrototypeRegistry` | Server helpers: `getAllPrototypes`, `getPrototype`, … |
|
|
94
|
+
| `PrototypeComponent`, `PrototypeControl` | Comment-anchorable UI wrappers |
|
|
95
|
+
| `PrototypeShell` | Review chrome (comments sidebar, screenshot capture) |
|
|
96
|
+
| `PrototypeVariantExplorer` | Multi-variant design exploration |
|
|
97
|
+
| `usePrototypeComments` | Live state + comment restore |
|
|
98
|
+
| `PrototypeGalleryClient` | Card grid for prototype home |
|
|
99
|
+
| `PrototypeGalleryShell`, `PrototypeGalleryHeader`, `PrototypeGalleryPage` | Tool-styled gallery layout (wrap in host route at `/`) |
|
|
100
|
+
| `definePrototypeComponentRegistry` | Per-prototype component id registry |
|
|
101
|
+
|
|
102
|
+
**Server-only** (import from `proto-plugin/server`):
|
|
103
|
+
|
|
104
|
+
- `readScreenshotManifest`
|
|
105
|
+
- `touchScreenshotManifest`
|
|
106
|
+
|
|
107
|
+
## Styles
|
|
108
|
+
|
|
109
|
+
The `prototype` package uses the **host design system** — same tokens and Tailwind utilities as prototype pages.
|
|
110
|
+
|
|
111
|
+
| Layer | Path |
|
|
112
|
+
| --- | --- |
|
|
113
|
+
| Host tokens + Tailwind | Host `src/app/globals.css` |
|
|
114
|
+
| shadcn primitives | `src/components/ui/` |
|
|
115
|
+
| Tool composites (sidebar, panel, toolbar, menus) | `src/components/platform-ui/` |
|
|
116
|
+
|
|
117
|
+
Host `globals.css` must `@source` prototype package TSX for Tailwind utilities.
|
|
118
|
+
|
|
119
|
+
## Publish
|
|
120
|
+
|
|
121
|
+
From `packages/prototype/`:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
npm login
|
|
125
|
+
pnpm publish-package
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Uses the public npm registry (`registry.npmjs.org`).
|
|
129
|
+
|
|
130
|
+
## Verify component ids
|
|
131
|
+
|
|
132
|
+
From the host repo root (forwards to the `prototype` package):
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
pnpm verify:prototype-ids
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Or run directly in the package:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
pnpm --filter prototype verify:prototype-ids
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Runs `scripts/verify-prototype-component-ids.mjs` against the host's `src/prototypes/*/`.
|
|
145
|
+
|
|
146
|
+
## Source app sync
|
|
147
|
+
|
|
148
|
+
Scripts live in `scripts/` and resolve the host root via `prototype.config.ts`.
|
|
149
|
+
|
|
150
|
+
The scripts are host-agnostic: which files to sync, which components the host
|
|
151
|
+
has customized, and which source-app env vars to link are all declared by the
|
|
152
|
+
host in a `prototype.sync.config.sh` at its repo root (template:
|
|
153
|
+
`scripts/lib/host-config.example.sh`).
|
|
154
|
+
|
|
155
|
+
From the host repo root:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
pnpm link-source # symlink source/ in editor
|
|
159
|
+
pnpm sync-from-source # sync files declared in prototype.sync.config.sh
|
|
160
|
+
pnpm link-source-db # copy configured env vars from source .env.local
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Or run directly in the package:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
pnpm --filter prototype link-source
|
|
167
|
+
pnpm --filter prototype sync-from-source
|
|
168
|
+
pnpm --filter prototype link-source-db
|
|
169
|
+
pnpm --filter prototype share-prototype <slug>
|
|
170
|
+
pnpm --filter prototype download-mobbin-references
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Set `SOURCE_PATH` in the host `.env.local` (see host `.env.example`).
|
|
174
|
+
|
|
175
|
+
### Share a prototype preview
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
pnpm share-prototype example-feature
|
|
179
|
+
pnpm share-prototype --no-push example-feature
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Uses `VERCEL_PROJECT` when set, otherwise the host `package.json` name. Override with `--project <name>`.
|
|
183
|
+
|
|
184
|
+
### Mobbin reference images
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
pnpm download-mobbin-references
|
|
188
|
+
pnpm download-mobbin-references -- --ids=uuid1,uuid2
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Starter prompt (for AI agents)
|
|
192
|
+
|
|
193
|
+
Copy the block below into a new agent chat to scaffold a host app from scratch. The agent should ask you for a few values up front, then handle the rest (including inferring what to sync from source).
|
|
194
|
+
|
|
195
|
+
````markdown
|
|
196
|
+
Set up a new Next.js host app for `proto-plugin` — a framework for shareable UI prototypes.
|
|
197
|
+
|
|
198
|
+
## Before you start — ask me for these
|
|
199
|
+
|
|
200
|
+
Do not scaffold or run commands until I answer. Ask in one message:
|
|
201
|
+
|
|
202
|
+
1. **Host app name** — directory name for the new Next.js project.
|
|
203
|
+
2. **Where to create it** — parent directory (absolute path), or confirm the current workspace.
|
|
204
|
+
3. **Source app path** — absolute path to the real product repo whose UI we will prototype (used for `source/` symlink and sync).
|
|
205
|
+
4. **Optional env** — whether I want comment/screenshot persistence configured now (`KV_REST_API_URL`, `KV_REST_API_TOKEN`, `BLOB_READ_WRITE_TOKEN`) or to skip for later.
|
|
206
|
+
|
|
207
|
+
Wait for my answers, then do all setup yourself.
|
|
208
|
+
|
|
209
|
+
## 1. Scaffold the app
|
|
210
|
+
|
|
211
|
+
Create a new directory and initialize a vanilla Next.js app using the host app name and parent path I gave you:
|
|
212
|
+
|
|
213
|
+
- App Router, TypeScript, Tailwind CSS v4, ESLint, pnpm
|
|
214
|
+
- No src-dir alias tricks beyond what Next generates (`src/app/…`)
|
|
215
|
+
- React 19 + Next.js 15+
|
|
216
|
+
|
|
217
|
+
Run `pnpm create next-app@latest` with the host app name I provided (`--typescript --tailwind --eslint --app --src-dir --use-pnpm`), in the parent directory I specified, then `cd` into the new project.
|
|
218
|
+
|
|
219
|
+
Install the package:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
pnpm add proto-plugin
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## 2. Wire the host app
|
|
226
|
+
|
|
227
|
+
Follow the package README (`node_modules/proto-plugin/README.md`) and implement every host step:
|
|
228
|
+
|
|
229
|
+
1. **`prototype.config.ts`** at the repo root — start with an empty `prototypes: []` array using `definePrototypeConfig` from `proto-plugin`.
|
|
230
|
+
2. **Gallery home** — `src/app/page.tsx` via `createPrototypeGalleryPage(prototypeConfig)`.
|
|
231
|
+
3. **Prototype route** — `src/app/prototypes/[slug]/page.tsx` via `createPrototypePage(prototypeConfig)` (export `default` + `generateStaticParams`).
|
|
232
|
+
4. **Root layout** — wrap children with `createPrototypeSiteLayout()` from `proto-plugin` in `src/app/layout.tsx`.
|
|
233
|
+
5. **API catch-all** — `src/app/api/[...path]/route.ts` using `createPrototypeApiRoute(prototypeConfig)` from `proto-plugin/server`; export `GET`, `POST`, and `PUT` handlers that call `dispatch`.
|
|
234
|
+
6. **`next.config.ts`** — wrap with `withPrototype` from `proto-plugin/with-prototype` and ensure `proto-plugin` is transpiled.
|
|
235
|
+
7. **`src/app/globals.css`** — keep Tailwind v4 setup and add:
|
|
236
|
+
|
|
237
|
+
```css
|
|
238
|
+
@source "../../node_modules/proto-plugin/src/**/*.{js,ts,jsx,tsx}";
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
8. **`package.json` scripts** — forward CLI commands to the installed package:
|
|
242
|
+
|
|
243
|
+
```json
|
|
244
|
+
{
|
|
245
|
+
"link-source": "pnpm --dir node_modules/proto-plugin link-source",
|
|
246
|
+
"sync-from-source": "pnpm --dir node_modules/proto-plugin sync-from-source",
|
|
247
|
+
"link-source-db": "pnpm --dir node_modules/proto-plugin link-source-db",
|
|
248
|
+
"verify:prototype-ids": "pnpm --dir node_modules/proto-plugin verify:prototype-ids",
|
|
249
|
+
"share-prototype": "pnpm --dir node_modules/proto-plugin share-prototype"
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
9. **`.env.example` and `.env.local`** — document and set `SOURCE_PATH` to the source app path I provided. Add comment/screenshot storage vars only if I asked for them in step 5 — the app should run without them, but comments won't persist.
|
|
254
|
+
|
|
255
|
+
Run `pnpm dev` and confirm `/` shows the empty gallery and the app builds cleanly before continuing.
|
|
256
|
+
|
|
257
|
+
## 3. Link the source app
|
|
258
|
+
|
|
259
|
+
The host reads the real product codebase through a read-only `source/` symlink — never import from it at runtime.
|
|
260
|
+
|
|
261
|
+
1. Copy `node_modules/proto-plugin/scripts/lib/host-config.example.sh` to **`prototype.sync.config.sh`** at the host repo root.
|
|
262
|
+
2. Inspect the linked source app and fill in `SYNC_FILES`, `SYNC_DIRS`, and `SYNC_GLOBS` yourself — start with design tokens and base UI (`src/app/globals.css`, `src/components/ui/`, fonts, shared utils) and add anything else the source clearly depends on. Do not ask me to confirm the list.
|
|
263
|
+
3. Set `SOURCE_PATH` in `.env.local` to the source app path I provided.
|
|
264
|
+
4. Run `pnpm link-source` — creates `source/` → source app symlink.
|
|
265
|
+
5. Run `pnpm sync-from-source` — copies declared paths from source into the host.
|
|
266
|
+
6. If I asked for local DB/API env vars, configure `SOURCE_DB_ENV_VARS` in `prototype.sync.config.sh` and run `pnpm link-source-db`.
|
|
267
|
+
|
|
268
|
+
After sync, re-check `globals.css` still includes the `@source` line for `proto-plugin`.
|
|
269
|
+
|
|
270
|
+
## 4. Ready for prototypes
|
|
271
|
+
|
|
272
|
+
When setup is done, tell me the host is ready and summarize what was synced. For building individual prototypes, read and follow **`node_modules/proto-plugin/AGENTS.md`** — that is the ground truth for prototype structure, `PrototypeComponent` ids, source fidelity, and verification (`pnpm verify:prototype-ids`).
|
|
273
|
+
|
|
274
|
+
Do not modify files inside `node_modules/proto-plugin/`. All host-specific work stays in the host repo (`prototype.config.ts`, `prototype.sync.config.sh`, `src/prototypes/`, synced design system files).
|
|
275
|
+
````
|
|
276
|
+
|
|
277
|
+
## Agent instructions
|
|
278
|
+
|
|
279
|
+
See [`AGENTS.md`](./AGENTS.md) — ground truth for building prototypes with this tool.
|
package/components.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://ui.shadcn.com/schema.json",
|
|
3
|
+
"style": "new-york",
|
|
4
|
+
"rsc": false,
|
|
5
|
+
"tsx": true,
|
|
6
|
+
"tailwind": {
|
|
7
|
+
"config": "",
|
|
8
|
+
"css": "src/styles/globals.css",
|
|
9
|
+
"baseColor": "zinc",
|
|
10
|
+
"cssVariables": true,
|
|
11
|
+
"prefix": ""
|
|
12
|
+
},
|
|
13
|
+
"aliases": {
|
|
14
|
+
"components": "@prototype/components",
|
|
15
|
+
"ui": "@prototype/components/ui",
|
|
16
|
+
"utils": "@prototype/lib/utils"
|
|
17
|
+
}
|
|
18
|
+
}
|