handoff-app 2.0.0-9 → 2.0.1
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 +90 -1
- package/{Changelog.md → CHANGELOG.md} +105 -1
- package/CLAUDE.md +92 -1
- package/{License.md → LICENSE.md} +1 -1
- package/README.md +818 -406
- package/RECIPES.md +975 -0
- package/UPGRADE.md +57 -9
- package/components.json +20 -20
- package/config/docs/foundations/colors/guidelines.md +0 -1
- package/config/docs/foundations/colors.md +0 -1
- package/config/docs/foundations/effects/guidelines.md +0 -1
- package/config/docs/foundations/effects/resources.md +0 -1
- package/config/docs/foundations/effects.md +0 -1
- package/config/docs/foundations/fonts.md +0 -1
- package/config/docs/foundations/grid.md +0 -1
- package/config/docs/foundations/icon.md +0 -1
- package/config/docs/foundations/icons/guidelines.md +0 -1
- package/config/docs/foundations/icons.md +0 -1
- package/config/docs/foundations/images/guidelines.md +0 -1
- package/config/docs/foundations/images/resources.md +0 -1
- package/config/docs/foundations/images.md +0 -1
- package/config/docs/foundations/logo/resources.md +0 -1
- package/config/docs/foundations/logo.md +0 -1
- package/config/docs/foundations/typography/guidelines.md +0 -1
- package/config/docs/foundations/typography/resources.md +0 -1
- package/config/docs/foundations/typography.md +0 -1
- package/config/docs/foundations.md +0 -1
- package/config/docs/guidelines.md +0 -1
- package/config/docs/index.md +0 -1
- package/config/docs/system/tokens/foundations/colors.md +0 -4
- package/config/docs/system/tokens/foundations/effects.md +0 -4
- package/config/docs/system/tokens/foundations/typography.md +0 -2
- package/config/docs/system.md +0 -2
- package/config/templates/page.md +2 -1
- package/config/templates/page.mdx +2 -1
- package/dist/ai/connections.d.ts +66 -0
- package/dist/ai/connections.js +149 -0
- package/dist/ai/define.d.ts +10 -0
- package/dist/ai/define.js +13 -0
- package/dist/ai/types.d.ts +26 -0
- package/dist/ai/types.js +10 -0
- package/dist/app-builder/build.d.ts +14 -7
- package/dist/app-builder/build.js +195 -66
- package/dist/app-builder/client-config.js +3 -2
- package/dist/app-builder/paths.d.ts +0 -12
- package/dist/app-builder/paths.js +3 -20
- package/dist/app-builder/static-export.js +1 -1
- package/dist/app-builder/vercel-output.d.ts +1 -1
- package/dist/app-builder/vercel-output.js +5 -4
- package/dist/cache/build-cache.d.ts +27 -4
- package/dist/cache/build-cache.js +114 -47
- package/dist/cache/build-inputs.d.ts +13 -0
- package/dist/cache/build-inputs.js +19 -0
- package/dist/cache/index.d.ts +2 -1
- package/dist/cache/index.js +5 -1
- package/dist/cli/create.js +1 -2
- package/dist/cli.js +1 -1
- package/dist/commands/build/index.d.ts +1 -1
- package/dist/commands/build/index.js +1 -1
- package/dist/commands/utils.d.ts +3 -3
- package/dist/config/defaults.js +7 -4
- package/dist/config/from-env.d.ts +4 -0
- package/dist/config/from-env.js +38 -1
- package/dist/config/helpers.js +2 -2
- package/dist/config/index.d.ts +0 -1
- package/dist/config/index.js +1 -4
- package/dist/config/loader.js +26 -2
- package/dist/config/resolve-env.d.ts +2 -1
- package/dist/config/resolve-env.js +28 -12
- package/dist/config/runtime.js +1 -1
- package/dist/index.d.ts +12 -7
- package/dist/index.js +18 -22
- package/dist/nav/index.d.ts +2 -2
- package/dist/nav/registry.d.ts +3 -3
- package/dist/nav/registry.js +1 -1
- package/dist/nav/workspace.d.ts +3 -3
- package/dist/nav/workspace.js +1 -1
- package/dist/pipeline/figma.d.ts +13 -2
- package/dist/pipeline/figma.js +86 -46
- package/dist/pipeline/styles.js +1 -1
- package/dist/pipeline/validation.d.ts +1 -1
- package/dist/pipeline/validation.js +3 -3
- package/dist/providers.d.ts +10 -0
- package/dist/providers.js +13 -0
- package/dist/registry/asset-storage/define.d.ts +5 -5
- package/dist/registry/asset-storage/define.js +4 -4
- package/dist/registry/asset-storage/resolve.d.ts +9 -19
- package/dist/registry/asset-storage/resolve.js +33 -21
- package/dist/registry/asset-storage/types.d.ts +37 -17
- package/dist/registry/asset-storage/types.js +5 -5
- package/dist/registry/auth/ai-keys.d.ts +32 -0
- package/dist/registry/auth/ai-keys.js +69 -0
- package/dist/registry/auth/crypto.d.ts +17 -0
- package/dist/registry/auth/crypto.js +61 -1
- package/dist/registry/auth/index.d.ts +2 -1
- package/dist/registry/auth/index.js +11 -2
- package/dist/registry/checkout/index.d.ts +2 -1
- package/dist/registry/checkout/index.js +57 -127
- package/dist/registry/client.js +53 -17
- package/dist/registry/db/driver.js +3 -3
- package/dist/registry/db/schema.d.ts +261 -3
- package/dist/registry/db/schema.js +29 -4
- package/dist/registry/email/define.d.ts +10 -0
- package/dist/registry/email/define.js +13 -0
- package/dist/registry/email/providers/smtp.d.ts +10 -0
- package/dist/registry/email/providers/smtp.js +73 -0
- package/dist/registry/email/resolve.d.ts +28 -0
- package/dist/registry/email/resolve.js +74 -0
- package/dist/registry/email/types.d.ts +24 -0
- package/dist/registry/email/types.js +6 -0
- package/dist/registry/path.d.ts +2 -0
- package/dist/registry/path.js +11 -1
- package/dist/registry/publish/errors.js +4 -0
- package/dist/registry/publish/index.js +2 -0
- package/dist/registry/publish/package.d.ts +6 -0
- package/dist/registry/publish/package.js +29 -1
- package/dist/registry/transfer.d.ts +4 -0
- package/dist/store/registry.d.ts +3 -3
- package/dist/store/registry.js +4 -4
- package/dist/transformers/preview/component/builder.d.ts +1 -9
- package/dist/transformers/preview/component/builder.js +17 -17
- package/dist/transformers/preview/component/css.d.ts +2 -1
- package/dist/transformers/preview/component/css.js +8 -5
- package/dist/transformers/preview/component/html.d.ts +3 -1
- package/dist/transformers/preview/component/html.js +6 -2
- package/dist/transformers/preview/component/javascript.d.ts +2 -1
- package/dist/transformers/preview/component/javascript.js +10 -4
- package/dist/transformers/utils/build.d.ts +9 -0
- package/dist/transformers/utils/build.js +27 -5
- package/dist/types/config.d.ts +129 -18
- package/dist/utils/path.d.ts +1 -5
- package/dist/utils/path.js +6 -23
- package/docs/api.md +6 -4
- package/docs/cli.md +275 -54
- package/drizzle/0007_add_ai_keys.sql +11 -0
- package/drizzle/0008_add_source_dir.sql +2 -0
- package/drizzle/meta/0007_snapshot.json +2013 -0
- package/drizzle/meta/0008_snapshot.json +2025 -0
- package/drizzle/meta/_journal.json +14 -0
- package/package.json +19 -8
- package/src/ai/README.md +42 -0
- package/src/ai/connections.ts +189 -0
- package/src/ai/define.ts +15 -0
- package/src/ai/types.ts +30 -0
- package/src/app/components/AiAssistant/AiAssistantPanel.tsx +144 -0
- package/src/app/components/AiAssistant/AiAssistantProvider.tsx +215 -0
- package/src/app/components/AiAssistant/AiConversation.tsx +737 -0
- package/src/app/components/AiAssistant/AiToolResult.tsx +99 -0
- package/src/app/components/AiAssistant/dockState.ts +86 -0
- package/src/app/components/AiAssistant/toolLabel.ts +24 -0
- package/src/app/components/AiAssistant/useAiChat.ts +147 -0
- package/src/app/components/AiAssistant/useAiConnections.ts +86 -0
- package/src/app/components/AiAssistant/usePageContext.ts +63 -0
- package/src/app/components/Auth/AccountLayout.tsx +58 -19
- package/src/app/components/Auth/AuthShell.tsx +27 -33
- package/src/app/components/Auth/RegistryInstallGate.tsx +4 -8
- package/src/app/components/Auth/installStatus.ts +29 -0
- package/src/app/components/Component/Preview.tsx +5 -2
- package/src/app/components/Foundations/ColorGrid.tsx +13 -14
- package/src/app/components/Layout/Header.tsx +21 -15
- package/src/app/components/Layout/Main.tsx +2 -2
- package/src/app/components/Markdown/MarkdownComponents.tsx +30 -32
- package/src/app/components/McpIntegration/McpConfigDialog.tsx +12 -51
- package/src/app/components/Navigation/MobileNav.tsx +2 -2
- package/src/app/components/Navigation/SideNav.tsx +1 -15
- package/src/app/components/context/NavProvider.tsx +7 -3
- package/src/app/components/ui/attachment.tsx +50 -0
- package/src/app/components/ui/bubble.tsx +57 -0
- package/src/app/components/ui/button.tsx +3 -1
- package/src/app/components/ui/confirm-dialog.tsx +87 -0
- package/src/app/components/ui/dialog.tsx +7 -2
- package/src/app/components/ui/marker.tsx +56 -0
- package/src/app/components/ui/sidebar.tsx +3 -1
- package/src/app/components/util/index.ts +3 -12
- package/src/app/css/index.css +64 -0
- package/src/app/lib/ai/auth.ts +33 -0
- package/src/app/lib/ai/context.ts +99 -0
- package/src/app/lib/ai/model.ts +79 -0
- package/src/app/lib/ai/prompt.ts +36 -0
- package/src/app/lib/ai/resolve.ts +97 -0
- package/src/app/lib/ai/tools.ts +120 -0
- package/src/app/lib/api/methods.ts +13 -0
- package/src/app/lib/asset-storage.ts +35 -36
- package/src/app/lib/auth/api.ts +4 -12
- package/src/app/lib/auth/email.ts +96 -23
- package/src/app/lib/docs-api/page-rendering.ts +1 -1
- package/src/app/lib/docs-api/registry.ts +2 -3
- package/src/app/lib/docs-api/runtime-config.ts +47 -21
- package/src/app/lib/mcp/components.ts +523 -0
- package/src/app/lib/mcp/page-url.ts +24 -0
- package/src/app/lib/mcp/pages.ts +84 -0
- package/src/app/lib/mcp/result.ts +33 -0
- package/src/app/lib/mcp/server.ts +39 -318
- package/src/app/lib/mcp/tokens.ts +334 -0
- package/src/app/lib/mcp/tool.ts +19 -0
- package/src/app/lib/registry-api/asset-transfer.ts +119 -11
- package/src/app/lib/registry-api/errors.ts +2 -0
- package/src/app/lib/registry-api/handler.ts +7 -1
- package/src/app/lib/registry-api/transfer.ts +28 -6
- package/src/app/lib/server-module.ts +34 -0
- package/src/app/lib/utils.ts +20 -0
- package/src/app/next.config.mjs +26 -24
- package/src/app/pages/[...slug]/index.tsx +2 -1
- package/src/app/pages/_app.tsx +6 -2
- package/src/app/pages/_document.tsx +6 -0
- package/src/app/pages/account/ai.tsx +183 -0
- package/src/app/pages/account/index.tsx +68 -68
- package/src/app/pages/account/tokens.tsx +37 -7
- package/src/app/pages/account/users.tsx +75 -15
- package/src/app/pages/api/account/ai/keys/[connectionId].ts +60 -0
- package/src/app/pages/api/account/ai/keys/index.ts +20 -0
- package/src/app/pages/api/admin/users/[id]/[action].ts +80 -11
- package/src/app/pages/api/admin/users/index.ts +2 -2
- package/src/app/pages/api/ai/chat.ts +115 -0
- package/src/app/pages/api/ai/connections.ts +23 -0
- package/src/app/pages/api/auth/request-reset.ts +14 -16
- package/src/app/pages/api/docs/nav.json.ts +1 -1
- package/src/app/pages/api/install.ts +3 -3
- package/src/app/pages/api/mcp.ts +6 -0
- package/src/app/pages/api/registry/transfer/assets/blobs/[hash]/complete.ts +11 -0
- package/src/app/pages/api/registry/transfer/assets/blobs/[hash]/upload.ts +12 -0
- package/src/app/pages/api/registry/transfer/assets/blobs/[hash].ts +1 -1
- package/src/app/pages/cli/device.tsx +10 -5
- package/src/app/pages/foundations/colors.tsx +9 -8
- package/src/app/pages/foundations/index.tsx +3 -3
- package/src/app/pages/index.tsx +2 -2
- package/src/app/pages/install.tsx +7 -2
- package/src/app/pages/login.tsx +32 -27
- package/src/app/pages/reset-password.tsx +21 -20
- package/src/app/pages/system/component/[component]/index.tsx +2 -5
- package/src/app/pages/system/index.tsx +11 -11
- package/src/app/pages/system/pattern/[pattern]/index.tsx +2 -2
- package/src/app/pages/system/tokens/components/[component]/index.tsx +0 -4
- package/src/app-builder/README.md +2 -1
- package/src/app-builder/build.ts +218 -73
- package/src/app-builder/client-config.ts +3 -2
- package/src/app-builder/paths.ts +3 -22
- package/src/app-builder/static-export.ts +1 -1
- package/src/app-builder/vercel-output.ts +5 -4
- package/src/cache/README.md +4 -1
- package/src/cache/build-cache.ts +128 -43
- package/src/cache/build-inputs.ts +28 -0
- package/src/cache/index.ts +4 -0
- package/src/cli/create.ts +1 -2
- package/src/cli.ts +1 -1
- package/src/commands/build/index.ts +1 -1
- package/src/config/README.md +10 -9
- package/src/config/defaults.ts +7 -4
- package/src/config/from-env.ts +33 -0
- package/src/config/helpers.ts +1 -3
- package/src/config/index.ts +0 -3
- package/src/config/loader.ts +25 -3
- package/src/config/resolve-env.ts +28 -15
- package/src/config/runtime.ts +1 -1
- package/src/index.ts +33 -29
- package/src/nav/index.ts +2 -2
- package/src/nav/registry.ts +3 -3
- package/src/nav/workspace.ts +3 -3
- package/src/pipeline/README.md +1 -1
- package/src/pipeline/figma.ts +98 -49
- package/src/pipeline/styles.ts +1 -1
- package/src/pipeline/validation.ts +3 -3
- package/src/providers.ts +18 -0
- package/src/registry/asset-storage/define.ts +6 -6
- package/src/registry/asset-storage/resolve.ts +38 -37
- package/src/registry/asset-storage/types.ts +39 -17
- package/src/registry/auth/ai-keys.ts +62 -0
- package/src/registry/auth/crypto.ts +63 -1
- package/src/registry/auth/index.ts +11 -1
- package/src/registry/checkout/index.ts +60 -138
- package/src/registry/client.ts +60 -20
- package/src/registry/db/driver.ts +2 -2
- package/src/registry/db/schema.ts +49 -22
- package/src/registry/email/define.ts +15 -0
- package/src/registry/email/providers/smtp.ts +39 -0
- package/src/registry/email/resolve.ts +94 -0
- package/src/registry/email/types.ts +28 -0
- package/src/registry/path.ts +11 -0
- package/src/registry/publish/errors.ts +4 -0
- package/src/registry/publish/index.ts +3 -1
- package/src/registry/publish/package.ts +33 -0
- package/src/registry/transfer.ts +4 -0
- package/src/store/registry.ts +7 -7
- package/src/transformers/preview/component/builder.ts +19 -25
- package/src/transformers/preview/component/css.ts +9 -4
- package/src/transformers/preview/component/html.ts +6 -2
- package/src/transformers/preview/component/javascript.ts +14 -4
- package/src/transformers/utils/build.ts +22 -4
- package/src/types/config.ts +142 -20
- package/src/utils/README.md +1 -1
- package/src/utils/path.ts +6 -29
- package/templates/default/handoff.config.js.tpl +10 -2
- package/templates/default/handoff.config.ts.tpl +10 -2
- package/templates/default/handoff.config.with-examples.js.tpl +10 -2
- package/templates/default/handoff.config.with-examples.ts.tpl +10 -2
- package/templates/default/package.json.tpl +2 -2
- package/.editorconfig +0 -19
- package/.eslintrc.json +0 -4
- package/.prettierignore +0 -0
- package/.prettierrc.json +0 -8
- package/.vscode/settings.json +0 -17
- package/dist/config/validator.d.ts +0 -9
- package/dist/config/validator.js +0 -24
- package/dist/registry/asset-storage/adapters/vercel-blob.d.ts +0 -17
- package/dist/registry/asset-storage/adapters/vercel-blob.js +0 -87
- package/src/app/components/old/Header.tsx +0 -89
- package/src/app/lib/mcp/shape.ts +0 -596
- package/src/app/pages/assets/fonts.tsx +0 -129
- package/src/app/pages/assets/index.tsx +0 -91
- package/src/app/pages/assets/logos.tsx +0 -75
- package/src/config/validator.ts +0 -22
- package/src/registry/asset-storage/adapters/vercel-blob.ts +0 -51
package/AGENTS.md
CHANGED
|
@@ -1,7 +1,96 @@
|
|
|
1
|
-
#
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
## Local instructions
|
|
2
4
|
|
|
3
5
|
Before starting work, check whether `AGENTS.local.md` exists in the repository root.
|
|
4
6
|
|
|
5
7
|
If it exists, read and follow its instructions in addition to this file. Treat `AGENTS.local.md` as developer-specific local guidance.
|
|
6
8
|
|
|
7
9
|
If it does not exist, proceed normally.
|
|
10
|
+
|
|
11
|
+
## Project
|
|
12
|
+
|
|
13
|
+
`handoff-app` is an npm package (CLI + library) that turns design tokens (fetched from Figma), components, patterns, and Markdown pages into a Next.js documentation app and distributable artifacts. User-facing docs: [README.md](README.md), [RECIPES.md](RECIPES.md), [docs/cli.md](docs/cli.md), [docs/api.md](docs/api.md), [UPGRADE.md](UPGRADE.md).
|
|
14
|
+
|
|
15
|
+
Requires Node.js >= 22 and npm >= 10.
|
|
16
|
+
|
|
17
|
+
## Commands
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
npm run build # tsc: compiles src/ (except src/app) to dist/
|
|
21
|
+
npm run lint # next lint over src/app
|
|
22
|
+
npm test # alias for lint; there is no unit test suite
|
|
23
|
+
npx tsc -p src/app/tsconfig.json --noEmit # typecheck the Next.js app (root tsc excludes src/app);
|
|
24
|
+
# errors under a stale src/app/.next/types are not real
|
|
25
|
+
npx drizzle-kit generate # generate a registry migration after editing src/registry/db/schema.ts
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The CLI (`dist/cli.js`, bin `handoff-app`) always runs against a **working directory**: the directory that holds `handoff.config.ts` (or `HANDOFF_WORKING_PATH`). This repo is not a Handoff project, so to exercise a change, build here and run the CLI from a consumer project that uses this build (`start`, `dev`, `build`, `fetch`, `publish`, `checkout`, ...). Verify behavior there; `npm run lint` and the two `tsc` runs are the only checks in this repo.
|
|
29
|
+
|
|
30
|
+
Formatting: Prettier (config in `package.json`: 140 cols, single quotes, `es5` trailing commas, Tailwind class sorting) and `.editorconfig` (2 spaces, LF).
|
|
31
|
+
|
|
32
|
+
## Architecture
|
|
33
|
+
|
|
34
|
+
### Runtime modes
|
|
35
|
+
|
|
36
|
+
- **Workspace** (default): local files are the source of truth; no database. It is the **only** place that builds content.
|
|
37
|
+
- **Registry**: a deployed catalog backed by PostgreSQL (Drizzle). It serves only what a workspace publishes. It never builds and never reads workspace source.
|
|
38
|
+
- A **connected workspace** publishes to / checks out from a registry; it is not a third mode.
|
|
39
|
+
|
|
40
|
+
`runtime.mode` selects the mode; `build --target registry` sets registry mode in the generated app. Keep registry-only dependencies (Drizzle/Postgres) out of the workspace and static paths — e.g. `src/store/index.ts` deliberately does not re-export the registry store; registry consumers import `@handoff/store/registry` lazily.
|
|
41
|
+
|
|
42
|
+
### Two TypeScript programs
|
|
43
|
+
|
|
44
|
+
- **`src/` (minus `src/app`)** — the Node CLI/library, CommonJS, compiled by root `tsconfig.json` to `dist/`. `src/index.ts` holds the `Handoff` class (`fetch`, `build`, `publish`, `checkout`, `start`, `dev`); `src/cli.ts` registers the yargs commands in `src/commands/`.
|
|
45
|
+
- **`src/app/`** — the Next.js (pages router) documentation app. It is not compiled by `tsc`; at build/start time `src/app-builder` stages it into `.handoff/<projectId>/` under the package and runs `next build` / `next dev`. It imports the core via the `@handoff/*` alias (→ `src/*`). It also hosts the APIs: docs API, registry API, MCP endpoint (`/api/mcp`), auth, and the AI assistant (`src/app/lib/*`, `src/app/pages/api/*`).
|
|
46
|
+
|
|
47
|
+
### Main flows
|
|
48
|
+
|
|
49
|
+
- **fetch**: `src/pipeline` — Figma auth → extract → fonts → token transformers; output goes to the working directory's `exported/`.
|
|
50
|
+
- **build/start**: `src/config` loads `handoff.config.*` + profile sidecar + env, then `initRuntimeConfig()` normalizes catalog declarations (`src/catalog`) into component/pattern records; `src/transformers` builds previews with Vite/esbuild per renderer (React, Handlebars, CSF); `src/cache` skips unchanged components (`.handoff/.cache/build-cache.json`, bypass with `--force`); `src/app-builder` builds the app (static → `out/static`, registry → `out/registry`, `--package vercel` → `.vercel/output`). Watch mode uses chokidar + a WebSocket reload server with diff-aware rebuilds.
|
|
51
|
+
- **publish/checkout**: `src/registry` (`publish/`, `checkout/`, `transfer.ts`, `tokens/`, `assets/`, `auth/`) against the registry API in `src/app/lib/registry-api`. Storage is abstracted by `src/store` (filesystem vs. registry implementations of the same interfaces). Asset blobs go through a pluggable storage provider; email and AI providers are also pluggable custom server modules (`handoff-app/providers`).
|
|
52
|
+
- **Migrations**: SQL in `drizzle/` ships with the package and is applied by `handoff-app db:migrate`.
|
|
53
|
+
|
|
54
|
+
### Config and server-module rules
|
|
55
|
+
|
|
56
|
+
- **Baked vs. request-time values.** For a `fromEnv('NAME')` value, the build keeps only the variable name, and a deployed registry reads the value at request time. Secrets must use `fromEnv()`. These settings change the shape of the build and are baked, so a change needs a rebuild: `runtime.mode`, `runtime.mcp`, `runtime.ai.enabled`, the database driver, the asset storage and email providers, and every custom server module. A new or changed setting must fit one of these two categories.
|
|
57
|
+
- **Custom server modules** (asset storage, email, AI providers) are `.js`/`.mjs` files, relative to the working directory, that import their define helper from `handoff-app/providers`. The registry build stops when a module imports `handoff-app`. The build copies each module and the packages it imports into the registry bundle.
|
|
58
|
+
|
|
59
|
+
Package entry points (`handoff-app`, `/react`, `/handlebars`, `/pattern`, `/providers`) map to `src/index.ts`, `src/react.ts`, `src/handlebars.ts`, `src/pattern.ts`, `src/providers.ts`. Adding a renderer touches several `Record<RendererKind, …>` maps — see [src/catalog/README.md](src/catalog/README.md).
|
|
60
|
+
|
|
61
|
+
Most `src/<module>/` directories have a `README.md` describing their files and flow. Read it before changing a module, and update it when the module's contract changes.
|
|
62
|
+
|
|
63
|
+
## Conventions
|
|
64
|
+
|
|
65
|
+
- **Breaking changes** get migration steps in [UPGRADE.md](UPGRADE.md), per major version.
|
|
66
|
+
- **Changelog**: [CHANGELOG.md](CHANGELOG.md) follows Keep a Changelog + SemVer. Entries are written during release prep on the release branch. Do not add or edit entries in feature or fix work unless asked.
|
|
67
|
+
- **Docs style**: README/RECIPES/CHANGELOG use short, plain, imperative sentences (Simplified Technical English style).
|
|
68
|
+
|
|
69
|
+
### Branches and releases
|
|
70
|
+
|
|
71
|
+
- **Branch names**: `<category>/<kebab-case-topic>`, e.g. `feature/config-profiles`, `bugfix/code-toc-md`, `docs/readme-rewrite`, `chore/remove-mdx`. Categories in use: `feature/`, `bugfix/`, `docs/`, `chore/`, `release/`.
|
|
72
|
+
- **Release branches**: each release has a `release/X.Y.Z` branch. Feature and fix branches start from it and merge back into it through a PR, not into `main`. A major release can first collect work in a long-running `integration/X.Y.Z` branch, from which `release/X.Y.Z` is cut (as for 2.0.0).
|
|
73
|
+
- **Prereleases and final version**: `np` (`npm run release`) runs on the release branch. It publishes prereleases (`X.Y.Z-N`) and then the final `X.Y.Z`; each creates a commit whose message is the bare version and a `vX.Y.Z[-N]` tag. Do not write these commits by hand. Release prep (changelog entries and date, last fixes) is committed directly on the release branch.
|
|
74
|
+
- **`main`** receives only release merges: a PR from `release/X.Y.Z` into `main` ships the release.
|
|
75
|
+
|
|
76
|
+
### Commit messages
|
|
77
|
+
|
|
78
|
+
Use a Conventional Commit subject with no scope and, normally, no body:
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
<type>: <description>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
- Types: `feat`, `fix`, `chore`, `refactor`, `docs`, `test`, `build`, `ci`, `perf`, `style`.
|
|
85
|
+
- Description: lowercase, imperative, no trailing period. State what the change achieves for the user, not how the code does it; omit file names and implementation details unless needed for clarity.
|
|
86
|
+
- Several distinct changes in one commit: one imperative clause each, separated by `; `. Supporting changes belong to the change they support and are not listed separately.
|
|
87
|
+
- No fixed length limit; the purpose sets the length.
|
|
88
|
+
|
|
89
|
+
Examples from history:
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
fix: use plain JSON Schema for MCP tool inputs
|
|
93
|
+
feat: move Figma settings to integrations.figma
|
|
94
|
+
refactor: rename define entry point and storage adapter to providers
|
|
95
|
+
feat: accept fromEnv() references in asset storage options and resolve them at request time; remove providerId and record blobs as database or custom
|
|
96
|
+
```
|
|
@@ -6,7 +6,111 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
|
6
6
|
and this project adheres to
|
|
7
7
|
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
8
8
|
|
|
9
|
-
## \[
|
|
9
|
+
## \[2.0.1] - 2026-11-01
|
|
10
|
+
|
|
11
|
+
This release makes catalog items smaller to publish and reports packages that
|
|
12
|
+
are too large for the registry.
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
* Client bundles of interactive React previews use the minified production
|
|
17
|
+
build of React. This reduces each bundle by about 1 MB, so components and
|
|
18
|
+
patterns publish within the registry request limit more often. In the local
|
|
19
|
+
workspace, previews no longer show React development warnings. To get them
|
|
20
|
+
back, set `minify: false` and a development `process.env.NODE_ENV` in
|
|
21
|
+
`hooks.clientBuildConfig`, then rebuild with `--force`.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
* `publish` stops before the upload when a package is larger than the 4.5 MB
|
|
26
|
+
registry limit and names the largest files.
|
|
27
|
+
* A `413` response from the registry now shows a clear "too large" message.
|
|
28
|
+
|
|
29
|
+
## \[2.0.0] - 2026-10-16
|
|
30
|
+
|
|
31
|
+
Handoff 2.0 adds a shared registry to the local workspace. You write content in
|
|
32
|
+
a workspace, publish it to a registry, and check it out in other projects.
|
|
33
|
+
Coding agents and an AI assistant can read the design system through MCP.
|
|
34
|
+
|
|
35
|
+
### Registry and connected workspaces
|
|
36
|
+
|
|
37
|
+
* Added the registry: a deployed catalog with a PostgreSQL database. It stores
|
|
38
|
+
the catalog items, pages, tokens, and assets that a workspace publishes.
|
|
39
|
+
* Added `publish` and `checkout`. Each command transfers all content, one
|
|
40
|
+
kind, or specific ids. `--dry-run` lists the changes and writes nothing.
|
|
41
|
+
* Added registry accounts, invitations, password reset, and access tokens with
|
|
42
|
+
read or read-and-write access.
|
|
43
|
+
* Added `login` and `logout`. `login` authorizes the CLI with a device code in
|
|
44
|
+
the browser.
|
|
45
|
+
* Added `build --target registry` for a standalone registry server, and
|
|
46
|
+
`--package vercel` for a Vercel bundle of either build target.
|
|
47
|
+
* Added `db:migrate` to apply the registry database migrations.
|
|
48
|
+
* Added asset storage. The registry stores assets in PostgreSQL by default. A
|
|
49
|
+
custom provider module can store them in a different service and can accept
|
|
50
|
+
direct uploads.
|
|
51
|
+
* Added registry email through SMTP or a custom provider module.
|
|
52
|
+
|
|
53
|
+
### MCP and AI assistant
|
|
54
|
+
|
|
55
|
+
* Added an MCP endpoint at `/api/mcp/`. Coding agents use it to search and read
|
|
56
|
+
components, previews, component source, tokens, and pages.
|
|
57
|
+
* Added a connect dialog with client settings for Claude Code, Cursor, and
|
|
58
|
+
VS Code.
|
|
59
|
+
* Added an AI assistant to the documentation app. It uses the same MCP tools,
|
|
60
|
+
knows the current page, and links to the content that it read.
|
|
61
|
+
* Added AI connections for OpenAI-compatible APIs, for example gateways and
|
|
62
|
+
local Ollama, and for custom provider modules. In registry mode, readers can
|
|
63
|
+
add their own keys.
|
|
64
|
+
|
|
65
|
+
MCP and the AI assistant need a server: a workspace or a registry. A static
|
|
66
|
+
site has neither.
|
|
67
|
+
|
|
68
|
+
### Catalog authoring
|
|
69
|
+
|
|
70
|
+
* Added `defineCatalogItem`, one API for components and patterns.
|
|
71
|
+
`catalog.include` registers the catalog directories.
|
|
72
|
+
* Previews are named exports. `Preview<typeof item>` gives a React preview the
|
|
73
|
+
argument type of its component. A preview can declare a `render` function.
|
|
74
|
+
* Handoff builds the CSS of a React item from the stylesheets that its imports
|
|
75
|
+
load.
|
|
76
|
+
* Previews keep their export order in builds, publish, and checkout.
|
|
77
|
+
|
|
78
|
+
### Other changes
|
|
79
|
+
|
|
80
|
+
* Added config profiles (`--profile`, `HANDOFF_PROFILE`), `fromEnv()`
|
|
81
|
+
references, and one registry login for each profile.
|
|
82
|
+
* Added `-c, --config` to every command.
|
|
83
|
+
* The build cache records every file that the last build of a component read,
|
|
84
|
+
Sass partials included. Every full build and every publish uses the cache.
|
|
85
|
+
* Page titles use `app.title`. The default pages no longer show a hard-coded
|
|
86
|
+
Handoff title.
|
|
87
|
+
* Reorganized the README, and added RECIPES.md and a migration guide in
|
|
88
|
+
UPGRADE.md.
|
|
89
|
+
|
|
90
|
+
### Breaking changes
|
|
91
|
+
|
|
92
|
+
* Handoff requires Node.js 22 or newer and npm 10 or newer.
|
|
93
|
+
* `defineCatalogItem` replaces `defineReactComponent`,
|
|
94
|
+
`defineHandlebarsComponent`, `defineCsfComponent`, `defineComponent`, and
|
|
95
|
+
`definePattern`.
|
|
96
|
+
* `catalog.include` replaces `entries.components` and `entries.patterns`.
|
|
97
|
+
* Previews are named exports, not a `previews` map. Some fields have new
|
|
98
|
+
names, for example `title` is `name` and `values` is `args`.
|
|
99
|
+
* Declarations use `.handoff.ts`, `.handoff.js`, or `.handoff.cjs`. Handoff
|
|
100
|
+
does not read JSON declarations or legacy `<name>.json` and `<name>.js` files.
|
|
101
|
+
* Figma settings moved to `integrations.figma`. The access token must be an
|
|
102
|
+
environment reference.
|
|
103
|
+
* The static build goes to `out/static`, and fetched tokens and assets go to
|
|
104
|
+
`exported/`. Neither path contains the project id. Removed the
|
|
105
|
+
`public-<projectId>` directories.
|
|
106
|
+
* Removed the `make:template` command.
|
|
107
|
+
* Removed the legacy `/assets` pages. The foundation pages show logos and
|
|
108
|
+
icons.
|
|
109
|
+
|
|
110
|
+
See the [migration guide](UPGRADE.md#version-1xx-to-version-2xx) for the
|
|
111
|
+
upgrade steps.
|
|
112
|
+
|
|
113
|
+
## \[1.2.2] - 2026-08-03
|
|
10
114
|
|
|
11
115
|
This patch release improves watch-mode reliability for patterns, broadens slot
|
|
12
116
|
default typing, clears downstream lint/build compatibility issues, and fixes a
|
package/CLAUDE.md
CHANGED
|
@@ -1,7 +1,98 @@
|
|
|
1
|
-
#
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Local instructions
|
|
2
6
|
|
|
3
7
|
Before starting work, check whether `AGENTS.local.md` exists in the repository root.
|
|
4
8
|
|
|
5
9
|
If it exists, read and follow its instructions in addition to this file. Treat `AGENTS.local.md` as developer-specific local guidance.
|
|
6
10
|
|
|
7
11
|
If it does not exist, proceed normally.
|
|
12
|
+
|
|
13
|
+
## Project
|
|
14
|
+
|
|
15
|
+
`handoff-app` is an npm package (CLI + library) that turns design tokens (fetched from Figma), components, patterns, and Markdown pages into a Next.js documentation app and distributable artifacts. User-facing docs: [README.md](README.md), [RECIPES.md](RECIPES.md), [docs/cli.md](docs/cli.md), [docs/api.md](docs/api.md), [UPGRADE.md](UPGRADE.md).
|
|
16
|
+
|
|
17
|
+
Requires Node.js >= 22 and npm >= 10.
|
|
18
|
+
|
|
19
|
+
## Commands
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm run build # tsc: compiles src/ (except src/app) to dist/
|
|
23
|
+
npm run lint # next lint over src/app
|
|
24
|
+
npm test # alias for lint; there is no unit test suite
|
|
25
|
+
npx tsc -p src/app/tsconfig.json --noEmit # typecheck the Next.js app (root tsc excludes src/app);
|
|
26
|
+
# errors under a stale src/app/.next/types are not real
|
|
27
|
+
npx drizzle-kit generate # generate a registry migration after editing src/registry/db/schema.ts
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The CLI (`dist/cli.js`, bin `handoff-app`) always runs against a **working directory**: the directory that holds `handoff.config.ts` (or `HANDOFF_WORKING_PATH`). This repo is not a Handoff project, so to exercise a change, build here and run the CLI from a consumer project that uses this build (`start`, `dev`, `build`, `fetch`, `publish`, `checkout`, ...). Verify behavior there; `npm run lint` and the two `tsc` runs are the only checks in this repo.
|
|
31
|
+
|
|
32
|
+
Formatting: Prettier (config in `package.json`: 140 cols, single quotes, `es5` trailing commas, Tailwind class sorting) and `.editorconfig` (2 spaces, LF).
|
|
33
|
+
|
|
34
|
+
## Architecture
|
|
35
|
+
|
|
36
|
+
### Runtime modes
|
|
37
|
+
|
|
38
|
+
- **Workspace** (default): local files are the source of truth; no database. It is the **only** place that builds content.
|
|
39
|
+
- **Registry**: a deployed catalog backed by PostgreSQL (Drizzle). It serves only what a workspace publishes. It never builds and never reads workspace source.
|
|
40
|
+
- A **connected workspace** publishes to / checks out from a registry; it is not a third mode.
|
|
41
|
+
|
|
42
|
+
`runtime.mode` selects the mode; `build --target registry` sets registry mode in the generated app. Keep registry-only dependencies (Drizzle/Postgres) out of the workspace and static paths — e.g. `src/store/index.ts` deliberately does not re-export the registry store; registry consumers import `@handoff/store/registry` lazily.
|
|
43
|
+
|
|
44
|
+
### Two TypeScript programs
|
|
45
|
+
|
|
46
|
+
- **`src/` (minus `src/app`)** — the Node CLI/library, CommonJS, compiled by root `tsconfig.json` to `dist/`. `src/index.ts` holds the `Handoff` class (`fetch`, `build`, `publish`, `checkout`, `start`, `dev`); `src/cli.ts` registers the yargs commands in `src/commands/`.
|
|
47
|
+
- **`src/app/`** — the Next.js (pages router) documentation app. It is not compiled by `tsc`; at build/start time `src/app-builder` stages it into `.handoff/<projectId>/` under the package and runs `next build` / `next dev`. It imports the core via the `@handoff/*` alias (→ `src/*`). It also hosts the APIs: docs API, registry API, MCP endpoint (`/api/mcp`), auth, and the AI assistant (`src/app/lib/*`, `src/app/pages/api/*`).
|
|
48
|
+
|
|
49
|
+
### Main flows
|
|
50
|
+
|
|
51
|
+
- **fetch**: `src/pipeline` — Figma auth → extract → fonts → token transformers; output goes to the working directory's `exported/`.
|
|
52
|
+
- **build/start**: `src/config` loads `handoff.config.*` + profile sidecar + env, then `initRuntimeConfig()` normalizes catalog declarations (`src/catalog`) into component/pattern records; `src/transformers` builds previews with Vite/esbuild per renderer (React, Handlebars, CSF); `src/cache` skips unchanged components (`.handoff/.cache/build-cache.json`, bypass with `--force`); `src/app-builder` builds the app (static → `out/static`, registry → `out/registry`, `--package vercel` → `.vercel/output`). Watch mode uses chokidar + a WebSocket reload server with diff-aware rebuilds.
|
|
53
|
+
- **publish/checkout**: `src/registry` (`publish/`, `checkout/`, `transfer.ts`, `tokens/`, `assets/`, `auth/`) against the registry API in `src/app/lib/registry-api`. Storage is abstracted by `src/store` (filesystem vs. registry implementations of the same interfaces). Asset blobs go through a pluggable storage provider; email and AI providers are also pluggable custom server modules (`handoff-app/providers`).
|
|
54
|
+
- **Migrations**: SQL in `drizzle/` ships with the package and is applied by `handoff-app db:migrate`.
|
|
55
|
+
|
|
56
|
+
### Config and server-module rules
|
|
57
|
+
|
|
58
|
+
- **Baked vs. request-time values.** For a `fromEnv('NAME')` value, the build keeps only the variable name, and a deployed registry reads the value at request time. Secrets must use `fromEnv()`. These settings change the shape of the build and are baked, so a change needs a rebuild: `runtime.mode`, `runtime.mcp`, `runtime.ai.enabled`, the database driver, the asset storage and email providers, and every custom server module. A new or changed setting must fit one of these two categories.
|
|
59
|
+
- **Custom server modules** (asset storage, email, AI providers) are `.js`/`.mjs` files, relative to the working directory, that import their define helper from `handoff-app/providers`. The registry build stops when a module imports `handoff-app`. The build copies each module and the packages it imports into the registry bundle.
|
|
60
|
+
|
|
61
|
+
Package entry points (`handoff-app`, `/react`, `/handlebars`, `/pattern`, `/providers`) map to `src/index.ts`, `src/react.ts`, `src/handlebars.ts`, `src/pattern.ts`, `src/providers.ts`. Adding a renderer touches several `Record<RendererKind, …>` maps — see [src/catalog/README.md](src/catalog/README.md).
|
|
62
|
+
|
|
63
|
+
Most `src/<module>/` directories have a `README.md` describing their files and flow. Read it before changing a module, and update it when the module's contract changes.
|
|
64
|
+
|
|
65
|
+
## Conventions
|
|
66
|
+
|
|
67
|
+
- **Breaking changes** get migration steps in [UPGRADE.md](UPGRADE.md), per major version.
|
|
68
|
+
- **Changelog**: [CHANGELOG.md](CHANGELOG.md) follows Keep a Changelog + SemVer. Entries are written during release prep on the release branch. Do not add or edit entries in feature or fix work unless asked.
|
|
69
|
+
- **Docs style**: README/RECIPES/CHANGELOG use short, plain, imperative sentences (Simplified Technical English style).
|
|
70
|
+
|
|
71
|
+
### Branches and releases
|
|
72
|
+
|
|
73
|
+
- **Branch names**: `<category>/<kebab-case-topic>`, e.g. `feature/config-profiles`, `bugfix/code-toc-md`, `docs/readme-rewrite`, `chore/remove-mdx`. Categories in use: `feature/`, `bugfix/`, `docs/`, `chore/`, `release/`.
|
|
74
|
+
- **Release branches**: each release has a `release/X.Y.Z` branch. Feature and fix branches start from it and merge back into it through a PR, not into `main`. A major release can first collect work in a long-running `integration/X.Y.Z` branch, from which `release/X.Y.Z` is cut (as for 2.0.0).
|
|
75
|
+
- **Prereleases and final version**: `np` (`npm run release`) runs on the release branch. It publishes prereleases (`X.Y.Z-N`) and then the final `X.Y.Z`; each creates a commit whose message is the bare version and a `vX.Y.Z[-N]` tag. Do not write these commits by hand. Release prep (changelog entries and date, last fixes) is committed directly on the release branch.
|
|
76
|
+
- **`main`** receives only release merges: a PR from `release/X.Y.Z` into `main` ships the release.
|
|
77
|
+
|
|
78
|
+
### Commit messages
|
|
79
|
+
|
|
80
|
+
Use a Conventional Commit subject with no scope and, normally, no body:
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
<type>: <description>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
- Types: `feat`, `fix`, `chore`, `refactor`, `docs`, `test`, `build`, `ci`, `perf`, `style`.
|
|
87
|
+
- Description: lowercase, imperative, no trailing period. State what the change achieves for the user, not how the code does it; omit file names and implementation details unless needed for clarity.
|
|
88
|
+
- Several distinct changes in one commit: one imperative clause each, separated by `; `. Supporting changes belong to the change they support and are not listed separately.
|
|
89
|
+
- No fixed length limit; the purpose sets the length.
|
|
90
|
+
|
|
91
|
+
Examples from history:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
fix: use plain JSON Schema for MCP tool inputs
|
|
95
|
+
feat: move Figma settings to integrations.figma
|
|
96
|
+
refactor: rename define entry point and storage adapter to providers
|
|
97
|
+
feat: accept fromEnv() references in asset storage options and resolve them at request time; remove providerId and record blobs as database or custom
|
|
98
|
+
```
|