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.
Files changed (209) hide show
  1. package/AGENTS.md +350 -0
  2. package/README.md +279 -0
  3. package/components.json +18 -0
  4. package/package.json +73 -0
  5. package/scripts/download-mobbin-reference-images.mjs +112 -0
  6. package/scripts/lib/host-config.example.sh +48 -0
  7. package/scripts/lib/host-config.sh +25 -0
  8. package/scripts/lib/resolve-host-root.mjs +18 -0
  9. package/scripts/lib/source-path.sh +49 -0
  10. package/scripts/link-source-db.sh +128 -0
  11. package/scripts/link-source.sh +40 -0
  12. package/scripts/publish-package.sh +147 -0
  13. package/scripts/share-prototype.sh +279 -0
  14. package/scripts/sync-from-source.sh +74 -0
  15. package/scripts/verify-prototype-component-ids.mjs +151 -0
  16. package/scripts/verify-prototype-preview-states.mjs +135 -0
  17. package/src/app.ts +4 -0
  18. package/src/components/platform-ui/code-block.tsx +21 -0
  19. package/src/components/platform-ui/controls-panel-options.tsx +71 -0
  20. package/src/components/platform-ui/controls-panel-select.tsx +438 -0
  21. package/src/components/platform-ui/empty-state.tsx +15 -0
  22. package/src/components/platform-ui/icon-button.tsx +18 -0
  23. package/src/components/platform-ui/panel-select.tsx +123 -0
  24. package/src/components/platform-ui/panel.tsx +97 -0
  25. package/src/components/platform-ui/review-dropdown-menu.tsx +35 -0
  26. package/src/components/platform-ui/sidebar.tsx +293 -0
  27. package/src/components/platform-ui/toolbar-icon-button.tsx +34 -0
  28. package/src/components/platform-ui/toolbar.tsx +37 -0
  29. package/src/components/prototype-gallery-client.tsx +57 -0
  30. package/src/components/prototype-provider.tsx +20 -0
  31. package/src/components/prototypes/mini-pill-label.tsx +37 -0
  32. package/src/components/prototypes/prototype-change-log-panel.tsx +207 -0
  33. package/src/components/prototypes/prototype-comment-provider.tsx +61 -0
  34. package/src/components/prototypes/prototype-comment-toolbar.tsx +65 -0
  35. package/src/components/prototypes/prototype-control.tsx +31 -0
  36. package/src/components/prototypes/prototype-controls.tsx +553 -0
  37. package/src/components/prototypes/prototype-create-exploration-modal.tsx +117 -0
  38. package/src/components/prototypes/prototype-create-state-modal.tsx +117 -0
  39. package/src/components/prototypes/prototype-default-state-map-page.tsx +66 -0
  40. package/src/components/prototypes/prototype-design-brief-modal.tsx +128 -0
  41. package/src/components/prototypes/prototype-design-brief-panel.tsx +525 -0
  42. package/src/components/prototypes/prototype-design-context-panel.tsx +65 -0
  43. package/src/components/prototypes/prototype-floating-pill.module.scss +1341 -0
  44. package/src/components/prototypes/prototype-mobbin-gallery.tsx +330 -0
  45. package/src/components/prototypes/prototype-reference-docs.tsx +222 -0
  46. package/src/components/prototypes/prototype-review-chrome.module.scss +630 -0
  47. package/src/components/prototypes/prototype-review-chrome.tsx +1241 -0
  48. package/src/components/prototypes/prototype-review-dropdown-menu-item.tsx +1 -0
  49. package/src/components/prototypes/prototype-review-dropdown-menu-separator.tsx +1 -0
  50. package/src/components/prototypes/prototype-review-panel-menu-item.tsx +1 -0
  51. package/src/components/prototypes/prototype-review-panel-menu-separator.tsx +1 -0
  52. package/src/components/prototypes/prototype-review-panel-select.tsx +4 -0
  53. package/src/components/prototypes/prototype-review-sidebar.tsx +167 -0
  54. package/src/components/prototypes/prototype-share-link-restore.tsx +75 -0
  55. package/src/components/prototypes/prototype-share-mode.tsx +206 -0
  56. package/src/components/prototypes/prototype-spec-panel-content.tsx +538 -0
  57. package/src/components/prototypes/prototype-state-canvas-overlay.module.scss +336 -0
  58. package/src/components/prototypes/prototype-state-canvas-overlay.tsx +1023 -0
  59. package/src/components/prototypes/prototype-state-canvas.tsx +38 -0
  60. package/src/components/prototypes/prototype-state-screenshot-preview.tsx +47 -0
  61. package/src/components/prototypes/prototype-target.tsx +120 -0
  62. package/src/components/prototypes/prototype-tweak-highlight.tsx +132 -0
  63. package/src/components/prototypes/prototype-tweaks.tsx +48 -0
  64. package/src/components/prototypes/prototype-variant-explorer.tsx +347 -0
  65. package/src/components/prototypes/prototype-variant-rationale-panel.tsx +49 -0
  66. package/src/components/prototypes/prototype-variant-tabs.tsx +207 -0
  67. package/src/components/prototypes/prototype-vercel-preview-modal.tsx +120 -0
  68. package/src/components/prototypes/state-map-annotation-tooltip.module.scss +89 -0
  69. package/src/components/prototypes/state-map-annotation-tooltip.tsx +137 -0
  70. package/src/components/prototypes/state-map-wireframe-highlight.module.scss +25 -0
  71. package/src/components/prototypes/state-map-wireframe-highlight.tsx +82 -0
  72. package/src/components/shell/prototype-gallery-shell.tsx +79 -0
  73. package/src/components/shell/prototype-screenshot-capture.tsx +45 -0
  74. package/src/components/shell/prototype-shell.module.scss +194 -0
  75. package/src/components/shell/prototype-shell.tsx +160 -0
  76. package/src/components/shell/prototype-state-screenshot-capture.tsx +68 -0
  77. package/src/components/ui/button.tsx +58 -0
  78. package/src/components/ui/dialog.module.scss +81 -0
  79. package/src/components/ui/dialog.tsx +127 -0
  80. package/src/components/ui/dropdown-menu.tsx +200 -0
  81. package/src/components/ui/input.tsx +22 -0
  82. package/src/components/ui/label.tsx +26 -0
  83. package/src/components/ui/option-select.tsx +81 -0
  84. package/src/components/ui/scroll-area.tsx +48 -0
  85. package/src/components/ui/separator.tsx +31 -0
  86. package/src/components/ui/slider.tsx +28 -0
  87. package/src/components/ui/switch.tsx +29 -0
  88. package/src/components/ui/tabs.tsx +55 -0
  89. package/src/components/ui/toggle-group.tsx +80 -0
  90. package/src/components/ui/tooltip.tsx +32 -0
  91. package/src/config/create-prototype-gallery-page.tsx +65 -0
  92. package/src/config/create-prototype-host-app.tsx +121 -0
  93. package/src/config/create-prototype-page.tsx +41 -0
  94. package/src/config/create-prototype-site-layout.tsx +28 -0
  95. package/src/config/define-prototype-config.ts +7 -0
  96. package/src/config/prototype-icon.tsx +25 -0
  97. package/src/config/prototype-site-layout-client.tsx +35 -0
  98. package/src/config/with-prototype.ts +20 -0
  99. package/src/index.ts +303 -0
  100. package/src/lib/pr-split/build-pr-agent-prompt.ts +68 -0
  101. package/src/lib/pr-split/build-pr-split-prototype-url.ts +12 -0
  102. package/src/lib/pr-split/pr-split-highlight.ts +6 -0
  103. package/src/lib/pr-split/pr-split-types.ts +58 -0
  104. package/src/lib/pr-split/resolve-source-preview-url.ts +45 -0
  105. package/src/lib/pr-split/use-pr-vercel-previews.ts +69 -0
  106. package/src/lib/prototype-comments/core/annotation-channel.ts +41 -0
  107. package/src/lib/prototype-comments/core/annotation-status.ts +60 -0
  108. package/src/lib/prototype-comments/core/annotation-target.ts +567 -0
  109. package/src/lib/prototype-comments/core/capture-theme.ts +41 -0
  110. package/src/lib/prototype-comments/core/capture.ts +11 -0
  111. package/src/lib/prototype-comments/core/comment-capture-blocked.ts +47 -0
  112. package/src/lib/prototype-comments/core/comment-threads.ts +52 -0
  113. package/src/lib/prototype-comments/core/element-identification.ts +615 -0
  114. package/src/lib/prototype-comments/core/export.ts +35 -0
  115. package/src/lib/prototype-comments/core/freeze-animations.ts +266 -0
  116. package/src/lib/prototype-comments/core/identify-element.ts +76 -0
  117. package/src/lib/prototype-comments/core/normalize-viewport.ts +35 -0
  118. package/src/lib/prototype-comments/core/react-detection.ts +704 -0
  119. package/src/lib/prototype-comments/core/restore.ts +7 -0
  120. package/src/lib/prototype-comments/core/screenshot.ts +428 -0
  121. package/src/lib/prototype-comments/core/source-location.ts +906 -0
  122. package/src/lib/prototype-comments/core/storage.ts +80 -0
  123. package/src/lib/prototype-comments/core/types.ts +79 -0
  124. package/src/lib/prototype-comments/core/validation.ts +17 -0
  125. package/src/lib/prototype-comments/hooks/useLayoutShift.ts +61 -0
  126. package/src/lib/prototype-comments/index.ts +58 -0
  127. package/src/lib/prototype-comments/react/CommentCaptureToolbar.tsx +1398 -0
  128. package/src/lib/prototype-comments/react/CommentProvider.tsx +298 -0
  129. package/src/lib/prototype-comments/scss.d.ts +10 -0
  130. package/src/lib/prototype-comments/ui/CommentAnnotationOverlay.tsx +253 -0
  131. package/src/lib/prototype-comments/ui/CommentDetailPage.tsx +56 -0
  132. package/src/lib/prototype-comments/ui/CommentHeaderCount.tsx +28 -0
  133. package/src/lib/prototype-comments/ui/CommentThread.tsx +331 -0
  134. package/src/lib/prototype-comments/ui/CommentsGrid.tsx +780 -0
  135. package/src/lib/prototype-comments/ui/CommentsListPage.tsx +25 -0
  136. package/src/lib/prototype-comments/ui/CommentsSidebar.tsx +77 -0
  137. package/src/lib/prototype-comments/ui/annotation-marker/index.tsx +200 -0
  138. package/src/lib/prototype-comments/ui/annotation-marker/styles.module.scss +194 -0
  139. package/src/lib/prototype-comments/ui/annotation-popup/index.tsx +335 -0
  140. package/src/lib/prototype-comments/ui/annotation-popup/styles.module.scss +469 -0
  141. package/src/lib/prototype-comments/ui/capture-styles.module.scss +2225 -0
  142. package/src/lib/prototype-comments/ui/comment-highlight.ts +48 -0
  143. package/src/lib/prototype-comments/ui/comment-thread.module.scss +203 -0
  144. package/src/lib/prototype-comments/ui/comments-grid-card.module.scss +253 -0
  145. package/src/lib/prototype-comments/ui/comments-sidebar.module.scss +123 -0
  146. package/src/lib/prototype-comments/ui/icon-transitions.module.scss +51 -0
  147. package/src/lib/prototype-comments/ui/icons.tsx +1086 -0
  148. package/src/lib/prototype-comments/ui/is-comment-detail-path.ts +7 -0
  149. package/src/lib/prototypes/capture-prototype-viewport.ts +32 -0
  150. package/src/lib/prototypes/changelog-meta-context.tsx +162 -0
  151. package/src/lib/prototypes/changelog-meta-storage.ts +62 -0
  152. package/src/lib/prototypes/changelog-meta.ts +95 -0
  153. package/src/lib/prototypes/create-prototype-registry.ts +74 -0
  154. package/src/lib/prototypes/create-state-screenshot-thumbnail.ts +46 -0
  155. package/src/lib/prototypes/design-exploration-default-storage.ts +68 -0
  156. package/src/lib/prototypes/design-exploration-default.ts +51 -0
  157. package/src/lib/prototypes/design-exploration-types.ts +203 -0
  158. package/src/lib/prototypes/prototype-comment-registry.tsx +145 -0
  159. package/src/lib/prototypes/prototype-comment-review-bridge.tsx +40 -0
  160. package/src/lib/prototypes/prototype-comment-review-state.ts +57 -0
  161. package/src/lib/prototypes/prototype-component-registry.ts +40 -0
  162. package/src/lib/prototypes/prototype-config-types.ts +34 -0
  163. package/src/lib/prototypes/prototype-preview-state-registry.ts +443 -0
  164. package/src/lib/prototypes/prototype-preview-state-types.ts +89 -0
  165. package/src/lib/prototypes/prototype-review-context.tsx +905 -0
  166. package/src/lib/prototypes/prototype-review-url.ts +134 -0
  167. package/src/lib/prototypes/prototype-share-link.ts +175 -0
  168. package/src/lib/prototypes/prototype-state-canvas-constants.ts +118 -0
  169. package/src/lib/prototypes/prototype-state-canvas-types.ts +159 -0
  170. package/src/lib/prototypes/prototype-state-screenshot.ts +39 -0
  171. package/src/lib/prototypes/prototype-tweak-registry.ts +96 -0
  172. package/src/lib/prototypes/prototype-tweak-types.ts +31 -0
  173. package/src/lib/prototypes/reference-docs.ts +137 -0
  174. package/src/lib/prototypes/screenshot-manifest.ts +33 -0
  175. package/src/lib/prototypes/screenshot-src.ts +7 -0
  176. package/src/lib/prototypes/share-command.ts +8 -0
  177. package/src/lib/prototypes/state-map-annotation.ts +70 -0
  178. package/src/lib/prototypes/use-design-exploration-default.ts +114 -0
  179. package/src/lib/prototypes/use-persisted-local-state.ts +140 -0
  180. package/src/lib/prototypes/use-prototype-comments.ts +63 -0
  181. package/src/lib/prototypes/use-prototype-mobile-viewport-frame.ts +46 -0
  182. package/src/lib/prototypes/use-prototype-state-screenshot-src.ts +71 -0
  183. package/src/lib/prototypes/use-prototype-tool-theme.tsx +115 -0
  184. package/src/lib/prototypes/use-prototype-viewport-frame.ts +34 -0
  185. package/src/lib/prototypes/use-register-prototype-reference-docs.ts +16 -0
  186. package/src/lib/prototypes/use-snap-corner-position.ts +417 -0
  187. package/src/lib/prototypes/use-toolbar-hover-panel.ts +98 -0
  188. package/src/lib/prototypes/variant-set-lucide-icon.tsx +55 -0
  189. package/src/lib/tool-portal.ts +33 -0
  190. package/src/lib/use-copy-to-clipboard.ts +81 -0
  191. package/src/lib/utils.ts +6 -0
  192. package/src/lib/vercel-preview/parse-vercel-github-comment.ts +81 -0
  193. package/src/server/create-host-api-route.ts +100 -0
  194. package/src/server/create-prototype-api-routes.ts +428 -0
  195. package/src/server/gallery/create-gallery-api.ts +56 -0
  196. package/src/server/gallery/folders-route.ts +156 -0
  197. package/src/server/gallery/gallery-env.ts +39 -0
  198. package/src/server/gallery/gallery-route.ts +150 -0
  199. package/src/server/gallery/gallery-types.ts +15 -0
  200. package/src/server/gallery/image-route.ts +59 -0
  201. package/src/server/gallery/item-route.ts +92 -0
  202. package/src/server/pr-vercel-preview-route.ts +162 -0
  203. package/src/server/redis/client.ts +55 -0
  204. package/src/server/redis/prototype-changelog-meta.ts +31 -0
  205. package/src/server/redis/prototype-comments.ts +92 -0
  206. package/src/server/redis/prototype-design-exploration-default.ts +32 -0
  207. package/src/server.ts +51 -0
  208. package/src/styles/globals.css +624 -0
  209. 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.
@@ -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
+ }