handoff-app 2.0.0-1 → 2.0.0-3

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 (219) hide show
  1. package/README.md +170 -91
  2. package/config/docs/foundations/colors/guidelines.md +9 -0
  3. package/config/docs/foundations/effects/guidelines.md +9 -0
  4. package/config/docs/foundations/effects/resources.md +9 -0
  5. package/config/docs/foundations/grid.md +10 -0
  6. package/config/docs/foundations/icons/guidelines.md +9 -0
  7. package/config/docs/foundations/images/guidelines.md +9 -0
  8. package/config/docs/foundations/images/resources.md +9 -0
  9. package/config/docs/foundations/images.md +10 -0
  10. package/config/docs/foundations/logo/resources.md +9 -0
  11. package/config/docs/foundations/typography/guidelines.md +9 -0
  12. package/config/docs/foundations/typography/resources.md +9 -0
  13. package/config/docs/foundations.md +5 -3
  14. package/dist/app-builder/build.js +109 -49
  15. package/dist/app-builder/client-config.js +13 -12
  16. package/dist/app-builder/paths.js +7 -9
  17. package/dist/app-builder/static-export.js +6 -6
  18. package/dist/app-builder/vercel-output.js +2 -2
  19. package/dist/artifacts/url.d.ts +7 -7
  20. package/dist/artifacts/url.js +7 -7
  21. package/dist/cli/auth/browser.d.ts +2 -0
  22. package/dist/cli/auth/browser.js +33 -0
  23. package/dist/cli/auth/device.d.ts +11 -0
  24. package/dist/cli/auth/device.js +155 -0
  25. package/dist/cli/auth/store.d.ts +29 -0
  26. package/dist/cli/auth/store.js +146 -0
  27. package/dist/cli/create.js +48 -3
  28. package/dist/cli/scaffold.js +20 -154
  29. package/dist/commands/checkout/index.d.ts +6 -6
  30. package/dist/commands/checkout/index.js +8 -12
  31. package/dist/commands/index.js +4 -0
  32. package/dist/commands/login/index.d.ts +8 -0
  33. package/dist/commands/login/index.js +53 -0
  34. package/dist/commands/logout/index.d.ts +7 -0
  35. package/dist/commands/logout/index.js +54 -0
  36. package/dist/commands/publish/index.d.ts +6 -5
  37. package/dist/commands/publish/index.js +8 -11
  38. package/dist/commands/utils.d.ts +6 -0
  39. package/dist/commands/utils.js +9 -1
  40. package/dist/config/entries.d.ts +47 -0
  41. package/dist/config/entries.js +162 -0
  42. package/dist/config/index.d.ts +2 -0
  43. package/dist/config/index.js +5 -1
  44. package/dist/config/runtime.d.ts +9 -9
  45. package/dist/config/runtime.js +15 -15
  46. package/dist/index.d.ts +12 -8
  47. package/dist/index.js +26 -10
  48. package/dist/registry/asset-storage/resolve.d.ts +1 -1
  49. package/dist/registry/asset-storage/resolve.js +1 -1
  50. package/dist/registry/auth/access-tokens.d.ts +46 -0
  51. package/dist/registry/auth/access-tokens.js +165 -0
  52. package/dist/registry/auth/action-tokens.d.ts +66 -0
  53. package/dist/registry/auth/action-tokens.js +178 -0
  54. package/dist/registry/auth/crypto.d.ts +4 -0
  55. package/dist/registry/auth/crypto.js +16 -0
  56. package/dist/registry/auth/database.d.ts +7 -0
  57. package/dist/registry/auth/database.js +22 -0
  58. package/dist/registry/auth/device-authorizations.d.ts +51 -0
  59. package/dist/registry/auth/device-authorizations.js +170 -0
  60. package/dist/registry/auth/gravatar.d.ts +1 -0
  61. package/dist/registry/auth/gravatar.js +8 -0
  62. package/dist/registry/auth/index.d.ts +11 -0
  63. package/dist/registry/auth/index.js +72 -0
  64. package/dist/registry/auth/installation.d.ts +42 -0
  65. package/dist/registry/auth/installation.js +105 -0
  66. package/dist/registry/auth/password.d.ts +12 -0
  67. package/dist/registry/auth/password.js +58 -0
  68. package/dist/registry/auth/rate-limits.d.ts +22 -0
  69. package/dist/registry/auth/rate-limits.js +75 -0
  70. package/dist/registry/auth/types.d.ts +26 -0
  71. package/dist/registry/auth/types.js +9 -0
  72. package/dist/registry/auth/user-record.d.ts +13 -0
  73. package/dist/registry/auth/user-record.js +16 -0
  74. package/dist/registry/auth/users.d.ts +31 -0
  75. package/dist/registry/auth/users.js +135 -0
  76. package/dist/registry/auth/validation.d.ts +3 -0
  77. package/dist/registry/auth/validation.js +28 -0
  78. package/dist/registry/checkout/assets.js +4 -2
  79. package/dist/registry/checkout/index.d.ts +11 -6
  80. package/dist/registry/checkout/index.js +159 -30
  81. package/dist/registry/checkout/tokens.js +4 -2
  82. package/dist/registry/client.d.ts +2 -1
  83. package/dist/registry/client.js +8 -0
  84. package/dist/registry/connection.d.ts +9 -0
  85. package/dist/registry/connection.js +29 -1
  86. package/dist/registry/db/client.d.ts +9 -9
  87. package/dist/registry/db/client.js +7 -7
  88. package/dist/registry/db/driver.d.ts +46 -0
  89. package/dist/registry/db/{adapter.js → driver.js} +22 -19
  90. package/dist/registry/db/index.d.ts +2 -2
  91. package/dist/registry/db/index.js +15 -9
  92. package/dist/registry/db/migrate.d.ts +1 -1
  93. package/dist/registry/db/migrate.js +5 -5
  94. package/dist/registry/db/schema.d.ts +2521 -750
  95. package/dist/registry/db/schema.js +126 -1
  96. package/dist/registry/publish/assets.js +1 -1
  97. package/dist/registry/publish/errors.js +3 -3
  98. package/dist/registry/publish/index.d.ts +9 -2
  99. package/dist/registry/publish/index.js +96 -10
  100. package/dist/registry/publish/tokens.js +1 -1
  101. package/dist/registry/transfer.d.ts +13 -0
  102. package/dist/types/config.d.ts +11 -4
  103. package/docs/cli.md +4 -0
  104. package/drizzle/0005_add_registry_auth.sql +95 -0
  105. package/drizzle/meta/0005_snapshot.json +1926 -0
  106. package/drizzle/meta/_journal.json +8 -1
  107. package/drizzle.config.ts +1 -1
  108. package/package.json +5 -4
  109. package/src/app/components/Auth/AccountLayout.tsx +87 -0
  110. package/src/app/components/Auth/AuthControls.tsx +99 -0
  111. package/src/app/components/Auth/AuthShell.tsx +73 -0
  112. package/src/app/components/Auth/RegistryInstallGate.tsx +23 -0
  113. package/src/app/components/Auth/RegistrySessionProvider.tsx +15 -0
  114. package/src/app/components/Auth/api.ts +20 -0
  115. package/src/app/components/Foundations/DisplayLogo.tsx +3 -3
  116. package/src/app/components/Layout/Header.tsx +2 -0
  117. package/src/app/components/Navigation/MobileNav.tsx +2 -0
  118. package/src/app/lib/auth/api.ts +113 -0
  119. package/src/app/lib/auth/config.ts +175 -0
  120. package/src/app/lib/auth/email.ts +34 -0
  121. package/src/app/lib/docs-api/runtime-config.ts +10 -24
  122. package/src/app/lib/registry-api/auth.ts +29 -46
  123. package/src/app/lib/registry-api/errors.ts +2 -2
  124. package/src/app/lib/registry-api/handler.ts +19 -14
  125. package/src/app/lib/registry-api/token-transfer.ts +1 -1
  126. package/src/app/lib/registry-api/transfer.ts +31 -2
  127. package/src/app/lib/registry-connection.ts +2 -2
  128. package/src/app/next.config.mjs +13 -4
  129. package/src/app/pages/_app.tsx +10 -4
  130. package/src/app/pages/account/index.tsx +153 -0
  131. package/src/app/pages/account/tokens.tsx +230 -0
  132. package/src/app/pages/account/users.tsx +310 -0
  133. package/src/app/pages/api/account/index.ts +26 -0
  134. package/src/app/pages/api/account/tokens/[id].ts +17 -0
  135. package/src/app/pages/api/account/tokens/index.ts +44 -0
  136. package/src/app/pages/api/admin/users/[id]/[action].ts +89 -0
  137. package/src/app/pages/api/admin/users/index.ts +53 -0
  138. package/src/app/pages/api/auth/[...nextauth].ts +4 -0
  139. package/src/app/pages/api/auth/request-reset.ts +53 -0
  140. package/src/app/pages/api/auth/reset-password.ts +29 -0
  141. package/src/app/pages/api/install.ts +102 -0
  142. package/src/app/pages/api/oauth/device/approve.ts +23 -0
  143. package/src/app/pages/api/oauth/device/index.ts +41 -0
  144. package/src/app/pages/api/oauth/revoke.ts +24 -0
  145. package/src/app/pages/api/oauth/token.ts +31 -0
  146. package/src/app/pages/api/registry/health.ts +4 -3
  147. package/src/app/pages/api/registry/transfer/[kind]/[id].ts +3 -3
  148. package/src/app/pages/api/registry/transfer/[kind]/index.ts +21 -0
  149. package/src/app/pages/api/registry/transfer/assets/[collection].ts +2 -1
  150. package/src/app/pages/api/registry/transfer/assets/blobs/[hash].ts +2 -1
  151. package/src/app/pages/api/registry/transfer/tokens/[...setId].ts +2 -2
  152. package/src/app/pages/cli/device.tsx +143 -0
  153. package/src/app/pages/foundations/icons/index.tsx +2 -2
  154. package/src/app/pages/foundations/icons/{[name] → library/[name]}/index.tsx +6 -6
  155. package/src/app/pages/install.tsx +336 -0
  156. package/src/app/pages/login.tsx +117 -0
  157. package/src/app/pages/reset-password.tsx +159 -0
  158. package/src/app/types/next-auth.d.ts +27 -0
  159. package/src/app-builder/build.ts +96 -59
  160. package/src/app-builder/client-config.ts +12 -11
  161. package/src/app-builder/paths.ts +7 -9
  162. package/src/app-builder/static-export.ts +6 -6
  163. package/src/app-builder/vercel-output.ts +2 -2
  164. package/src/artifacts/url.ts +7 -7
  165. package/src/cli/auth/browser.ts +29 -0
  166. package/src/cli/auth/device.ts +181 -0
  167. package/src/cli/auth/store.ts +137 -0
  168. package/src/cli/create.ts +58 -3
  169. package/src/cli/scaffold.ts +20 -197
  170. package/src/commands/checkout/index.ts +10 -15
  171. package/src/commands/index.ts +4 -0
  172. package/src/commands/login/index.ts +48 -0
  173. package/src/commands/logout/index.ts +51 -0
  174. package/src/commands/publish/index.ts +10 -14
  175. package/src/commands/utils.ts +12 -0
  176. package/src/config/entries.ts +175 -0
  177. package/src/config/index.ts +4 -0
  178. package/src/config/runtime.ts +15 -14
  179. package/src/index.ts +26 -12
  180. package/src/registry/asset-storage/resolve.ts +1 -1
  181. package/src/registry/auth/access-tokens.ts +198 -0
  182. package/src/registry/auth/action-tokens.ts +225 -0
  183. package/src/registry/auth/crypto.ts +13 -0
  184. package/src/registry/auth/database.ts +15 -0
  185. package/src/registry/auth/device-authorizations.ts +223 -0
  186. package/src/registry/auth/gravatar.ts +6 -0
  187. package/src/registry/auth/index.ts +89 -0
  188. package/src/registry/auth/installation.ts +117 -0
  189. package/src/registry/auth/password.ts +46 -0
  190. package/src/registry/auth/rate-limits.ts +84 -0
  191. package/src/registry/auth/types.ts +34 -0
  192. package/src/registry/auth/user-record.ts +25 -0
  193. package/src/registry/auth/users.ts +145 -0
  194. package/src/registry/auth/validation.ts +24 -0
  195. package/src/registry/checkout/assets.ts +4 -2
  196. package/src/registry/checkout/index.ts +182 -30
  197. package/src/registry/checkout/tokens.ts +4 -2
  198. package/src/registry/client.ts +7 -1
  199. package/src/registry/connection.ts +23 -0
  200. package/src/registry/db/client.ts +12 -12
  201. package/src/registry/db/{adapter.ts → driver.ts} +24 -21
  202. package/src/registry/db/index.ts +16 -4
  203. package/src/registry/db/migrate.ts +5 -5
  204. package/src/registry/db/schema.ts +174 -1
  205. package/src/registry/publish/assets.ts +1 -1
  206. package/src/registry/publish/errors.ts +3 -3
  207. package/src/registry/publish/index.ts +108 -10
  208. package/src/registry/publish/tokens.ts +1 -1
  209. package/src/registry/transfer.ts +14 -0
  210. package/src/types/config.ts +11 -4
  211. package/templates/default/README.md.tpl +58 -1
  212. package/templates/default/gitignore.tpl +19 -3
  213. package/templates/default/handoff.config.js.tpl +13 -0
  214. package/templates/default/handoff.config.ts.tpl +13 -0
  215. package/templates/default/handoff.config.with-examples.js.tpl +13 -0
  216. package/templates/default/handoff.config.with-examples.ts.tpl +13 -0
  217. package/templates/default/package.json.tpl +2 -1
  218. package/templates/default/vercel.json.tpl +4 -0
  219. package/dist/registry/db/adapter.d.ts +0 -43
package/README.md CHANGED
@@ -19,19 +19,20 @@ authoring locally or running a shared, deployed catalog.
19
19
  * [Requirements](#requirements)
20
20
  * [Quick start](#quick-start)
21
21
  * [Project layout](#project-layout)
22
- * [Authoring components and patterns](#authoring-components-and-patterns)
22
+ * [Authoring components, patterns, and pages](#authoring-components-patterns-and-pages)
23
23
  * [Fetching design tokens](#fetching-design-tokens)
24
24
  * [Running locally](#running-locally)
25
25
  * [Building artifacts](#building-artifacts)
26
26
  * [Static site (default)](#static-site-default)
27
27
  * [Registry app](#registry-app)
28
+ * [Deploying](#deploying)
28
29
  * [Publishing and checkout](#publishing-and-checkout)
29
30
  * [Configuration](#configuration)
30
31
  * [The runtime block](#the-runtime-block)
31
32
  * [Environment variables](#environment-variables)
33
+ * [Registry installation and access](#registry-installation-and-access)
32
34
  * [Hooks](#hooks)
33
35
  * [CLI reference](#cli-reference)
34
- * [Further reading](#further-reading)
35
36
  * [Maintainers](#maintainers)
36
37
  * [Contributing](#contributing)
37
38
  * [License](#license)
@@ -47,16 +48,16 @@ It brings a few pieces together:
47
48
  * **Token extraction.** Pull standardized foundations from your design source and
48
49
  store them as JSON. Figma is supported out of the box through the Figma REST
49
50
  API.
50
- * **Transformation pipeline.** Produce SCSS, CSS, Style Dictionary, and preview
51
- snippets from that data.
51
+ * **Transformation pipeline.** Produce SCSS and CSS by default, with optional
52
+ Style Dictionary or custom transformer output.
52
53
  * **Documentation runtime.** Render live, working previews of your components,
53
54
  tokens, and styles, served through a stable docs read API.
54
55
  * **Delivery tooling.** Build and ship the deliverables, either as a static site
55
56
  or as a deployed, database-backed catalog.
56
57
 
57
- Out of the box Handoff ships SCSS and CSS maps for [Bootstrap 5](https://getbootstrap.com/).
58
- If you use another framework or custom CSS, you can write your own map files to
59
- connect the generated tokens to your project.
58
+ Use the global `entries.scss` and `entries.js` files to load a framework or your
59
+ own frontend code into previews. For example, a Bootstrap project can import
60
+ [Bootstrap 5](https://getbootstrap.com/) from its Sass and JavaScript entries.
60
61
 
61
62
  You install `handoff-app` as a project-local dependency and run its commands in
62
63
  your project's context, so every project pins its own toolchain version.
@@ -74,13 +75,12 @@ badge so the active mode is always clear.
74
75
  server, and build a static documentation snapshot. Local authoring stays fast
75
76
  and self-contained, with no database or registry required.
76
77
  * **Registry mode.** A deployed, dynamic Next.js app backed by PostgreSQL serves
77
- a shared catalog. It only ever serves what a workspace published to it. The
78
+ a shared catalog from published records and packaged default pages. The
78
79
  registry never compiles or materializes workspace source.
79
80
 
80
81
  A **connected workspace** is workspace mode plus a registry connection. It still
81
- renders only your local files and still reads as `Workspace`, but it gains two
82
- commands: `publish` to push a locally built component or pattern up to a
83
- registry, and `checkout` to pull one back down into your workspace.
82
+ renders only local files and still reads as `Workspace`, but it can publish and
83
+ check out components, patterns, pages, token sets, and asset collections.
84
84
 
85
85
  Under the hood, documentation in every mode is consumed through one stable docs
86
86
  read API and one canonical artifact URL scheme (`/api/docs/artifacts/{path}`),
@@ -89,7 +89,7 @@ which store is behind it.
89
89
 
90
90
  ## Requirements
91
91
 
92
- * Node 18.17+
92
+ * Node 18.18 or newer. Node 20 LTS or newer is recommended.
93
93
  * npm 8+
94
94
  * A paid Figma account, if you fetch tokens from a Figma library
95
95
  * PostgreSQL (or a Postgres-compatible service such as Neon) for registry mode
@@ -103,13 +103,13 @@ npx handoff-app init
103
103
  ```
104
104
 
105
105
  The wizard asks for a project name, whether to include sample components, your
106
- preferred language (TypeScript or JavaScript), and optionally your Figma project
107
- ID and access token. It then creates the project directory, writes the config
108
- and starter files, and installs dependencies.
106
+ preferred language, optional Vercel deployment settings, and optional Figma
107
+ credentials. It then creates the project, writes the starter files, and installs
108
+ the project-local dependencies.
109
109
 
110
110
  ```bash
111
111
  cd my-handoff-project
112
- npm run fetch # pull design tokens from Figma (optional if no Figma creds yet)
112
+ npm run fetch # pull design tokens after adding Figma credentials (optional)
113
113
  npm run start # author locally with live preview at http://localhost:3000
114
114
  ```
115
115
 
@@ -120,8 +120,9 @@ The generated `package.json` wires up the common scripts:
120
120
  "scripts": {
121
121
  "start": "handoff-app start",
122
122
  "dev": "handoff-app dev",
123
+ "fetch": "handoff-app fetch",
123
124
  "build": "handoff-app build",
124
- "fetch": "handoff-app fetch"
125
+ "db:migrate": "handoff-app db:migrate"
125
126
  }
126
127
  }
127
128
  ```
@@ -142,18 +143,28 @@ my-handoff-project/
142
143
  │ ├─ Button.tsx # component implementation
143
144
  │ └─ button.handoff.ts # component declaration
144
145
  ├─ patterns/ # multi-component compositions
146
+ │ └─ hero/
147
+ │ └─ hero.handoff.ts
148
+ ├─ pages/ # custom Markdown documentation and navigation
149
+ │ └─ guides/
150
+ │ └─ getting-started.md
145
151
  ├─ sass/ # optional global SCSS entry
146
152
  ├─ js/ # optional global JS entry
147
- ├─ exported/ # generated tokens and artifacts (gitignored)
153
+ ├─ public/ # optional static assets
154
+ ├─ exported/ # fetched tokens and assets; commit this directory
148
155
  └─ out/ # build output (gitignored)
149
156
  ```
150
157
 
151
- ## Authoring components and patterns
158
+ A working Handoff project can mix global Sass and JavaScript entry points,
159
+ React, Handlebars, and CSF components, composed patterns, nested Markdown pages,
160
+ and fetched files under `exported/<projectId>`.
161
+
162
+ ## Authoring components, patterns, and pages
152
163
 
153
164
  A component is a directory with an implementation file and a declaration. The
154
- declaration is discovered as `*.handoff.{ts,js,cjs,json}` (the legacy
155
- `{dirname}.{js,cjs,json}` form keeps working too). List the directories you want
156
- built under `entries.components` in your config.
165
+ declaration is discovered as `*.handoff.{ts,js,cjs,json}`. The older
166
+ `{dirname}.{js,cjs,json}` form also works. List individual directories or a
167
+ parent collection such as `components` under `entries.components`.
157
168
 
158
169
  Declarations are written with the typed helpers exported from `handoff-app`:
159
170
 
@@ -191,6 +202,12 @@ directory name). The display `name`/`title` is independent of the `id`, so you
191
202
  can rename freely without breaking references. Identity is matched by `id`
192
203
  during publish and checkout.
193
204
 
205
+ Patterns use `definePattern` and compose component IDs. Each reference can select
206
+ a named preview or supply its own arguments. Custom documentation lives as
207
+ Markdown under `pages/`. A page's relative file path becomes both its route and
208
+ registry ID, so `pages/guides/getting-started.md` is served and transferred as
209
+ `guides/getting-started`.
210
+
194
211
  ## Fetching design tokens
195
212
 
196
213
  Handoff fetches tokens from Figma out of the box. Set your Figma credentials in
@@ -207,10 +224,16 @@ Then pull the latest foundations and component data:
207
224
  npm run fetch
208
225
  ```
209
226
 
210
- To get a personal access token in Figma, open the Figma menu, go to
211
- `Help and Account` then `Account Settings`, scroll to `Personal Access Token`,
212
- name a token, and copy it. Republish your Figma library after design changes and
213
- run `fetch` again to pick them up.
227
+ The fetch output is stored under `exported/<projectId>`. It includes
228
+ `tokens.json`, generated CSS and Sass, and available icon or logo archives. Keep
229
+ this directory in version control so local and CI builds use the same source
230
+ data.
231
+
232
+ To create a personal access token in Figma, open the account menu from the file
233
+ browser, select `Settings`, open `Security`, and generate a token under
234
+ `Personal access tokens`. Grant `file_content:read` and `library_content:read`,
235
+ then copy the token when Figma displays it. Republish your Figma library after
236
+ design changes and run `fetch` again to pick them up.
214
237
 
215
238
  ## Running locally
216
239
 
@@ -226,8 +249,9 @@ preview updates. The site boots at http://localhost:3000 by default.
226
249
 
227
250
  ## Building artifacts
228
251
 
229
- `handoff-app build` accepts a `--target` flag. The target, not `NODE_ENV`,
230
- decides what gets produced.
252
+ `handoff-app build` accepts two independent flags. `--target` decides *what* is
253
+ produced. The target, not `NODE_ENV`, drives this. The optional `--package`
254
+ decides *how* that target is packaged for deployment.
231
255
 
232
256
  ### Static site (default)
233
257
 
@@ -236,12 +260,11 @@ handoff-app build # static target (default)
236
260
  handoff-app build --target static # explicit, identical output
237
261
  ```
238
262
 
239
- The static target builds your workspace components, patterns, and tokens,
240
- materializes the docs read model into route-shaped static files, and runs a
241
- static export to `out/<projectId>` (respecting `sitesOutputDirectory`). The
242
- output is plain static files: it renders list, detail, preview, and inspect
243
- pages and loads previews through canonical artifact URLs with no live server. It
244
- works on a managed host like Vercel and on a plain static file server with no
263
+ The static target builds workspace components and patterns, includes local
264
+ pages, tokens, and assets, materializes the docs read model into route-shaped
265
+ static files, and exports to `out/<projectId>` (respecting
266
+ `sitesOutputDirectory`). The output renders list, detail, preview, and inspect
267
+ pages with no live server, so any static file server or CDN can serve it without
245
268
  host-specific rewrites.
246
269
 
247
270
  The build fails clearly if a required artifact referenced by generated HTML
@@ -260,31 +283,66 @@ standalone bundle. It never builds or bundles workspace source and has no
260
283
  workspace-source runtime dependency. It serves the docs read API and the
261
284
  registry API from the database and published artifacts.
262
285
 
263
- The bundle is self-hostable on a Node server, VPS, or container. Start it with
264
- `node server.js` from the output directory and supply the database connection at
265
- deploy time:
286
+ The bundle is self-hostable on a Node server, VPS, or container. Supply the
287
+ database connection, a session secret of at least 32 characters, and the public
288
+ registry URL at deploy time:
266
289
 
267
290
  ```bash
268
- DATABASE_URL="postgres://…" node out/registry/server.js
291
+ DATABASE_URL="postgres://..." \
292
+ AUTH_SECRET="replace-with-a-long-random-value" \
293
+ AUTH_URL="https://registry.example.com" \
294
+ node out/registry/server.js
269
295
  ```
270
296
 
271
297
  A generated `README.md` next to the bundle documents the required env vars and
272
- Docker/Vercel specifics. Apply database migrations from the CLI as a controlled
273
- release step (e.g. in CI/CD) before deploying:
298
+ how to run it. Apply database migrations from the CLI as a controlled release
299
+ step (e.g. in CI/CD) before deploying:
274
300
 
275
301
  ```bash
276
302
  handoff-app db:migrate
277
303
  ```
278
304
 
279
- `db:migrate` reads your project config and DB env vars, applies the
280
- package-owned migration set, and runs independently of `build`. The database
281
- adapter (`pg` or `neon`) is chosen with `runtime.registry.database.adapter`, and
282
- both adapters ship with the package.
305
+ `db:migrate` reads your project config and database environment variables, applies the
306
+ package-owned migration set, and runs independently of `build`. PostgreSQL is
307
+ the supported database; `runtime.registry.database.driver` selects the
308
+ connection driver (`pg` or `neon`), not the database engine. Both drivers ship
309
+ with the package.
310
+
311
+ Registry assets are stored in PostgreSQL by default, with a 4 MB limit per
312
+ blob. Larger deployments can use the built-in Vercel Blob adapter or a custom
313
+ storage adapter through `runtime.registry.assetStorage`.
314
+
315
+ ### Deploying
316
+
317
+ * **Static** produces plain files under `out/<projectId>`. Serve them with any
318
+ static file server or CDN. Commit `exported/` so a clean checkout has token
319
+ data to build from.
320
+ * **Registry** produces a self-contained Node bundle under `out/registry`. Run it
321
+ on any Node host with `node out/registry/server.js` and configure
322
+ `DATABASE_URL`, `AUTH_SECRET`, and `AUTH_URL` in the environment.
323
+
324
+ The optional `--package` flag repackages a target without changing what it
325
+ builds:
326
+
327
+ | `--package` | Output |
328
+ | --- | --- |
329
+ | omitted (default) | `out/<projectId>` (static) or the `out/registry` Node bundle (registry) |
330
+ | `vercel` | `.vercel/output`, a Vercel Build Output API bundle |
331
+
332
+ `handoff-app init` can scaffold a `vercel.json` that runs a packaged build; edit
333
+ its `buildCommand` to change the target.
283
334
 
284
335
  ## Publishing and checkout
285
336
 
286
- Connect a workspace to a registry by adding a `registryConnection` block to your
287
- config and setting the access token env var:
337
+ For interactive use, authorize the workspace with the browser device flow:
338
+
339
+ ```bash
340
+ handoff-app login --url https://registry.example.com
341
+ ```
342
+
343
+ The saved login supplies the registry URL and credential to `publish` and
344
+ `checkout`. For CI or another headless environment, add a `registryConnection`
345
+ block and provide a user-issued access token through an environment variable:
288
346
 
289
347
  ```ts
290
348
  runtime: {
@@ -301,44 +359,37 @@ runtime: {
301
359
  HANDOFF_REGISTRY_ACCESS_TOKEN=your-registry-token
302
360
  ```
303
361
 
304
- Then push and pull entities by `id`:
362
+ Then push and pull one entity by ID, or omit the ID to process every entity of
363
+ that kind:
305
364
 
306
365
  ```bash
307
- handoff-app publish component button # build locally, upload that entity's package
308
- handoff-app checkout pattern hero # pull a registry entity into this workspace
366
+ handoff-app publish components button # build locally, upload that entity's package
367
+ handoff-app checkout patterns hero # pull a registry entity into this workspace
368
+ handoff-app publish pages # publish every custom Markdown page
369
+ handoff-app checkout tokens foundation/colors
309
370
  ```
310
371
 
311
- `publish` runs a fresh targeted build of the selected entity and uploads only
312
- that entity's package: normalized metadata, source files referenced by its
313
- `entries`, rendered docs artifacts (including required shared artifacts like
314
- `component/main.css` and `component/main.js`), and build metadata. It fails
315
- before upload if required artifacts are missing, stale, or incompatible, and it
316
- never touches unrelated entities' artifacts. Declaration files are never
317
- uploaded.
318
-
319
- `checkout` reads the registry record and source files, writes them in standard
320
- authoring form, and synthesizes a local declaration in your configured
321
- `runtime.workspace.declarationFormat` (defaulting to `js`). Declarations are a
322
- workspace-only concern, so they are always synthesized locally and never read
323
- from the registry. Overwriting existing local files requires `--force` or an
324
- interactive confirmation.
372
+ `publish` builds the selected content before upload. Components and patterns
373
+ include normalized metadata, referenced source files, rendered docs artifacts,
374
+ shared preview assets, and build metadata. Pages upload their Markdown source.
375
+ Tokens and assets upload their generated sets or collections. Declaration files
376
+ remain local to the workspace.
377
+
378
+ `checkout` restores the standard workspace layout. It synthesizes component and
379
+ pattern declarations in `runtime.workspace.declarationFormat`, which defaults to
380
+ `js`, and restores pages, tokens, and assets to their normal locations.
381
+ Overwriting local files requires `--force` or interactive confirmation.
325
382
 
326
383
  ## Configuration
327
384
 
328
- Project configuration lives in `handoff.config.{ts,js,cjs,json}` (resolved in
329
- that precedence order). TypeScript and ESM configs use `defineConfig` for typed
330
- authoring; plain CommonJS configs that never call `defineConfig` keep working
331
- unchanged.
385
+ Project configuration lives in `handoff.config.{ts,js,cjs,json}` and is resolved
386
+ in that order. Use `defineConfig` for typed authoring and camelCase aliases.
387
+ Plain object exports remain supported.
332
388
 
333
389
  ```ts
334
390
  import { defineConfig } from 'handoff-app';
335
391
 
336
392
  export default defineConfig({
337
- app: {
338
- title: 'Acme Design System',
339
- client: 'Acme Corp',
340
- basePath: '',
341
- },
342
393
  entries: {
343
394
  scss: './sass/main.scss',
344
395
  js: './js/main.js',
@@ -372,13 +423,16 @@ runtime: {
372
423
  // Registry deployment settings (build --target registry, db:migrate).
373
424
  registry: {
374
425
  databaseUrlEnv: 'DATABASE_URL',
375
- apiTokenEnv: 'HANDOFF_REGISTRY_API_TOKEN',
376
- database: { adapter: 'pg' }, // 'pg' | 'neon'
426
+ database: { driver: 'pg' }, // connection driver: 'pg' | 'neon' (PostgreSQL only)
427
+ assetStorage: {
428
+ adapter: 'database', // 'database' | 'vercel-blob' | 'custom'
429
+ maxInlineBytes: 4194304,
430
+ },
377
431
  },
378
432
  },
379
433
  ```
380
434
 
381
- Secrets are always referenced by environment-variable name, never written as
435
+ Registry secrets are referenced by environment-variable name, never written as
382
436
  values, and are redacted from API responses.
383
437
 
384
438
  ### Environment variables
@@ -388,9 +442,39 @@ values, and are redacted from API responses.
388
442
  | `HANDOFF_FIGMA_PROJECT_ID` | Figma file ID used by `fetch` |
389
443
  | `HANDOFF_DEV_ACCESS_TOKEN` | Figma personal access token used by `fetch` |
390
444
  | `HANDOFF_REGISTRY_URL` | Default env var for a connected workspace's registry URL |
391
- | `HANDOFF_REGISTRY_ACCESS_TOKEN` | Connected-workspace access token for publish/checkout |
445
+ | `HANDOFF_REGISTRY_ACCESS_TOKEN` | User-issued CI token for publish/checkout |
392
446
  | `DATABASE_URL` | Registry database connection string (name is configurable) |
393
- | `HANDOFF_REGISTRY_API_TOKEN` | Bearer token guarding registry management mutations |
447
+ | `AUTH_SECRET` | Long random secret used to sign registry browser sessions |
448
+ | `AUTH_URL` | Canonical public registry URL, including its base path |
449
+ | `RESEND_API_KEY` | Optional Resend API key for invitations and password resets |
450
+ | `AUTH_FROM_EMAIL` | Optional verified sender used with Resend |
451
+ | `BLOB_READ_WRITE_TOKEN` | Default credential for the Vercel Blob asset adapter |
452
+ | `HANDOFF_OUTPUT_DIR` | Override the fetched output directory (`exported`) |
453
+ | `HANDOFF_SITES_DIR` | Override the build output directory (`out`) |
454
+ | `HANDOFF_APP_PORT` | Local documentation server port (`3000`) |
455
+ | `HANDOFF_WEBSOCKET_PORT` | Local reload server port (`3001`) |
456
+ | `HANDOFF_LOG_LEVEL` | Logging level: `debug`, `info`, `warn`, `error`, or `silent` |
457
+
458
+ ### Registry installation and access
459
+
460
+ Database migrations remain an explicit deployment step. Configure the
461
+ environment, run `handoff-app db:migrate`, deploy, and immediately open
462
+ `/install` to create the first administrator. The installer validates the
463
+ deployment but never changes the schema.
464
+
465
+ The first visitor can claim an uninstalled registry. Do not leave a new
466
+ deployment unattended before installation is complete.
467
+
468
+ Administrators can invite users, manage roles, and deactivate accounts. Members
469
+ receive read access for browsing and checkout, while administrators can also
470
+ publish. If Resend is not configured, the registry shows invitation links once
471
+ for manual delivery.
472
+
473
+ `handoff-app login` stores a revocable credential in
474
+ `.handoff/cli-auth.json` and only uses it for the exact registry URL that issued
475
+ it. For CI, create a scoped token in Account settings and expose it through
476
+ `runtime.registryConnection.accessTokenEnv`. The former
477
+ `HANDOFF_REGISTRY_API_TOKEN` server secret is no longer accepted.
394
478
 
395
479
  ### Hooks
396
480
 
@@ -408,12 +492,16 @@ See [docs/api.md](docs/api.md#hooks) for hook arguments and examples.
408
492
  | --- | --- |
409
493
  | `init` | Scaffold a new workspace project with the interactive wizard |
410
494
  | `fetch` | Fetch design tokens from Figma |
495
+ | `scaffold` | Scaffold component stubs from fetched Figma components |
411
496
  | `dev` | Start the local dev server with the live docs read API |
412
497
  | `start` | Start the dev server with file watchers for live authoring |
413
- | `build [--target static\|registry]` | Build the static site (default) or package the registry app |
498
+ | `build [--target static\|registry] [--package standalone\|vercel]` | Build the static site (default) or registry app; `--package vercel` emits a Vercel Build Output bundle |
499
+ | `build:app` | Alias for `build --target static` |
414
500
  | `build:components [component]` | Build components without building the full app |
415
- | `publish <component\|pattern> <id>` | Build and publish an entity to the connected registry |
416
- | `checkout <component\|pattern> <id>` | Pull an entity from the connected registry |
501
+ | `publish <components\|patterns\|pages\|tokens\|assets> [id]` | Build and publish entities to the connected registry (all of the kind, or one by id) |
502
+ | `checkout <components\|patterns\|pages\|tokens\|assets> [id]` | Pull entities from the connected registry into this workspace |
503
+ | `login --url <registry-url>` | Authorize this workspace through the registry device flow |
504
+ | `logout [--url <registry-url>]` | Revoke and remove the saved workspace credential |
417
505
  | `db:migrate` | Run registry database migrations (Drizzle / PostgreSQL) |
418
506
  | `make:component <name>` | Scaffold a new component |
419
507
  | `make:page <name> [parent]` | Scaffold a documentation page |
@@ -424,17 +512,8 @@ See [docs/api.md](docs/api.md#hooks) for hook arguments and examples.
424
512
  | `validate:components` | Run component validation |
425
513
 
426
514
  Global flags: `-c, --config <file>`, `-d, --debug`, `-f, --force`,
427
- `-h, --help`, `-v, --version`. See [docs/cli.md](docs/cli.md) for the full
428
- reference.
429
-
430
- ## Further reading
431
-
432
- * [Configure your project](https://www.handoff.com/docs/customization)
433
- * [Customize the content](https://www.handoff.com/docs/customization/content)
434
- * [Integrate tokens with your project](https://www.handoff.com/docs/tokens/integration)
435
- * [Build to static assets](https://www.handoff.com/docs/tokens/publishing)
436
- * [GitHub Actions CI/CD](https://www.handoff.com/docs/infrastructure/github/)
437
- * [Bitbucket Pipelines CI/CD](https://www.handoff.com/docs/infrastructure/bitbucket/)
515
+ `-h, --help`, `-v, --version`. Run `handoff-app <command> --help` for the exact
516
+ options in your installed version.
438
517
 
439
518
  ## Maintainers
440
519
 
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: Color Guidelines
3
+ description: How to apply the color palette consistently and accessibly across products.
4
+ metaTitle: 'Color Guidelines | Handoff Design System'
5
+ metaDescription: 'How to apply the color palette consistently and accessibly across products.'
6
+ ---
7
+
8
+ This is placeholder content for the **Color Guidelines** page. Replace it with your rules for
9
+ contrast, pairing, and semantic usage. Markdown and <b>HTML</b> are both supported.
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: Effects Guidelines
3
+ description: When and how to apply shadows, blurs, and elevation across the interface.
4
+ metaTitle: 'Effects Guidelines | Handoff Design System'
5
+ metaDescription: 'When and how to apply shadows, blurs, and elevation across the interface.'
6
+ ---
7
+
8
+ This is placeholder content for the **Effects Guidelines** page. Replace it with your rules for
9
+ elevation, depth, and motion. Markdown and <b>HTML</b> are both supported.
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: Effects Resources
3
+ description: Reference values and assets for reproducing the brand's effects in any tool.
4
+ metaTitle: 'Effects Resources | Handoff Design System'
5
+ metaDescription: 'Reference values and assets for reproducing effects in any tool.'
6
+ ---
7
+
8
+ This is placeholder content for the **Effects Resources** page. Replace it with your shadow tokens,
9
+ blur values, and export notes. Markdown and <b>HTML</b> are both supported.
@@ -0,0 +1,10 @@
1
+ ---
2
+ title: Grid
3
+ description: Layout grid and spacing system that keeps compositions aligned and balanced.
4
+ image: hero-design
5
+ metaTitle: 'Grid | Handoff Design System'
6
+ metaDescription: 'Layout grid and spacing system that keeps compositions aligned and balanced.'
7
+ ---
8
+
9
+ This is placeholder content for the **Grid** page. Replace it with your columns, gutters, and
10
+ breakpoint rules. Markdown and <b>HTML</b> are both supported.
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: Icon Guidelines
3
+ description: Sizing, spacing, and usage rules that keep the icon set consistent.
4
+ metaTitle: 'Icon Guidelines | Handoff Design System'
5
+ metaDescription: 'Sizing, spacing, and usage rules that keep the icon set consistent.'
6
+ ---
7
+
8
+ This is placeholder content for the **Icon Guidelines** page. Replace it with your rules for grid
9
+ sizing, stroke, and when to use each icon. Markdown and <b>HTML</b> are both supported.
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: Image Guidelines
3
+ description: How to select, crop, and treat imagery so it stays on brand.
4
+ metaTitle: 'Image Guidelines | Handoff Design System'
5
+ metaDescription: 'How to select, crop, and treat imagery so it stays on brand.'
6
+ ---
7
+
8
+ This is placeholder content for the **Image Guidelines** page. Replace it with your rules for
9
+ composition, cropping, and treatments. Markdown and <b>HTML</b> are both supported.
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: Image Resources
3
+ description: Source files and downloads for approved photography and illustration.
4
+ metaTitle: 'Image Resources | Handoff Design System'
5
+ metaDescription: 'Source files and downloads for approved photography and illustration.'
6
+ ---
7
+
8
+ This is placeholder content for the **Image Resources** page. Replace it with your image library,
9
+ downloads, and licensing notes. Markdown and <b>HTML</b> are both supported.
@@ -0,0 +1,10 @@
1
+ ---
2
+ title: Images
3
+ description: Photography and illustration style that shapes how the brand looks and feels.
4
+ image: hero-design
5
+ metaTitle: 'Images | Handoff Design System'
6
+ metaDescription: 'Photography and illustration style that shapes how the brand looks and feels.'
7
+ ---
8
+
9
+ This is placeholder content for the **Images** page. Replace it with your art direction,
10
+ photography style, and illustration principles. Markdown and <b>HTML</b> are both supported.
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: Logo Resources
3
+ description: Downloadable logo files and everything teams need to represent the brand correctly.
4
+ metaTitle: 'Logo Resources | Handoff Design System'
5
+ metaDescription: 'Downloadable logo files and everything teams need to represent the brand correctly.'
6
+ ---
7
+
8
+ This is placeholder content for the **Logo Resources** page. Replace it with your logo downloads,
9
+ file formats, and usage notes. Markdown and <b>HTML</b> are both supported.
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: Typography Guidelines
3
+ description: Best practices for type scale, hierarchy, and readability across the system.
4
+ metaTitle: 'Typography Guidelines | Handoff Design System'
5
+ metaDescription: 'Best practices for type scale, hierarchy, and readability across the system.'
6
+ ---
7
+
8
+ This is placeholder content for the **Typography Guidelines** page. Replace it with your rules for
9
+ hierarchy, spacing, and responsive type. Markdown and <b>HTML</b> are both supported.
@@ -0,0 +1,9 @@
1
+ ---
2
+ title: Typography Resources
3
+ description: Font files, licenses, and assets needed to work with the brand typography.
4
+ metaTitle: 'Typography Resources | Handoff Design System'
5
+ metaDescription: 'Font files, licenses, and assets needed to work with the brand typography.'
6
+ ---
7
+
8
+ This is placeholder content for the **Typography Resources** page. Replace it with your font
9
+ downloads, licensing details, and platform notes. Markdown and <b>HTML</b> are both supported.
@@ -67,8 +67,10 @@ menu:
67
67
  title: Images
68
68
  icon: image
69
69
  menu:
70
- - path: foundations/icons
71
- title: Library
72
- - path: foundations/icons/guidelines
70
+ - path: foundations/images
71
+ title: Overview
72
+ - path: foundations/images/guidelines
73
73
  title: Guidelines
74
+ - path: foundations/images/resources
75
+ title: Resources
74
76
  ---