handoff-app 2.0.0-6 → 2.0.0-8
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/README.md +240 -52
- package/UPGRADE.md +218 -0
- package/config/config.template.js +1 -4
- package/config/config.template.ts +1 -2
- package/dist/app-builder/build.js +12 -6
- package/dist/app-builder/client-config.js +3 -1
- package/dist/app-builder/config-diff/strategies/pattern.js +3 -3
- package/dist/app-builder/watchers/component.js +5 -5
- package/dist/app-builder/watchers/utils.d.ts +2 -3
- package/dist/app-builder/watchers.d.ts +8 -15
- package/dist/app-builder/watchers.js +70 -61
- package/dist/cache/build-cache.js +23 -23
- package/dist/catalog/define.d.ts +6 -0
- package/dist/catalog/define.js +72 -0
- package/dist/catalog/implementation.d.ts +27 -0
- package/dist/catalog/implementation.js +133 -0
- package/dist/catalog/index.d.ts +6 -0
- package/dist/catalog/index.js +22 -0
- package/dist/catalog/normalize.d.ts +16 -0
- package/dist/catalog/normalize.js +115 -0
- package/dist/catalog/previews.d.ts +18 -0
- package/dist/catalog/previews.js +106 -0
- package/dist/catalog/renderers.d.ts +43 -0
- package/dist/catalog/renderers.js +62 -0
- package/dist/catalog/types.d.ts +63 -0
- package/dist/cli/auth/device.d.ts +6 -1
- package/dist/cli/auth/device.js +5 -2
- package/dist/cli/auth/store.d.ts +15 -6
- package/dist/cli/auth/store.js +72 -19
- package/dist/cli/make.d.ts +0 -5
- package/dist/cli/make.js +22 -67
- package/dist/cli/scaffold.js +25 -33
- package/dist/commands/checkout/index.d.ts +7 -4
- package/dist/commands/checkout/index.js +9 -6
- package/dist/commands/compat/push-args.d.ts +2 -2
- package/dist/commands/index.js +0 -2
- package/dist/commands/login/index.d.ts +5 -0
- package/dist/commands/login/index.js +18 -6
- package/dist/commands/logout/index.d.ts +5 -0
- package/dist/commands/logout/index.js +54 -15
- package/dist/commands/publish/index.d.ts +9 -6
- package/dist/commands/publish/index.js +11 -8
- package/dist/commands/pull/index.js +1 -1
- package/dist/commands/push/index.js +1 -1
- package/dist/commands/types.d.ts +2 -0
- package/dist/commands/utils.d.ts +36 -11
- package/dist/commands/utils.js +30 -16
- package/dist/config/catalog-include.d.ts +43 -0
- package/dist/config/catalog-include.js +203 -0
- package/dist/config/defaults.d.ts +3 -3
- package/dist/config/defaults.js +54 -48
- package/dist/config/env.d.ts +9 -0
- package/dist/config/env.js +43 -0
- package/dist/config/errors.d.ts +4 -0
- package/dist/config/errors.js +11 -0
- package/dist/config/from-env.d.ts +24 -0
- package/dist/config/from-env.js +7 -0
- package/dist/config/helpers.d.ts +2 -0
- package/dist/config/helpers.js +3 -1
- package/dist/config/index.d.ts +4 -3
- package/dist/config/index.js +10 -5
- package/dist/config/loader.d.ts +29 -11
- package/dist/config/loader.js +126 -45
- package/dist/config/resolve-env.d.ts +5 -0
- package/dist/config/resolve-env.js +102 -0
- package/dist/config/runtime.d.ts +7 -8
- package/dist/config/runtime.js +154 -154
- package/dist/config/validator.d.ts +2 -2
- package/dist/config/validator.js +2 -4
- package/dist/handlebars.d.ts +9 -0
- package/dist/handlebars.js +16 -0
- package/dist/index.d.ts +48 -8
- package/dist/index.js +88 -30
- package/dist/pattern.d.ts +7 -0
- package/dist/pattern.js +13 -0
- package/dist/pipeline/index.d.ts +1 -1
- package/dist/pipeline/index.js +1 -1
- package/dist/react.d.ts +43 -0
- package/dist/react.js +11 -0
- package/dist/registry/asset-storage/adapters/vercel-blob.js +1 -1
- package/dist/registry/asset-storage/define.d.ts +1 -1
- package/dist/registry/asset-storage/define.js +1 -1
- package/dist/registry/asset-storage/resolve.d.ts +2 -2
- package/dist/registry/asset-storage/resolve.js +4 -1
- package/dist/registry/checkout/index.d.ts +9 -0
- package/dist/registry/checkout/index.js +339 -153
- package/dist/registry/connection.d.ts +28 -24
- package/dist/registry/connection.js +53 -67
- package/dist/registry/db/driver.d.ts +4 -11
- package/dist/registry/db/driver.js +4 -16
- package/dist/registry/db/index.d.ts +1 -1
- package/dist/registry/db/index.js +1 -2
- package/dist/registry/db/schema.d.ts +34 -0
- package/dist/registry/db/schema.js +2 -0
- package/dist/registry/publish/index.d.ts +13 -2
- package/dist/registry/publish/index.js +113 -29
- package/dist/registry/publish/package.js +14 -1
- package/dist/registry/selection.d.ts +20 -0
- package/dist/registry/selection.js +37 -1
- package/dist/store/filesystem.d.ts +3 -3
- package/dist/store/filesystem.js +7 -7
- package/dist/store/registry.js +24 -3
- package/dist/transformers/plugins/csf-render.js +4 -2
- package/dist/transformers/plugins/ssr-render.js +14 -5
- package/dist/transformers/preview/component/api.d.ts +8 -0
- package/dist/transformers/preview/component/api.js +11 -15
- package/dist/transformers/preview/component/artifacts.d.ts +1 -1
- package/dist/transformers/preview/component/artifacts.js +11 -7
- package/dist/transformers/preview/component/builder.js +15 -18
- package/dist/transformers/preview/component/css.d.ts +2 -0
- package/dist/transformers/preview/component/css.js +8 -11
- package/dist/transformers/preview/component/html.js +18 -16
- package/dist/transformers/preview/component/javascript.js +2 -4
- package/dist/transformers/preview/pattern/builder.js +31 -18
- package/dist/transformers/preview/types.d.ts +15 -1
- package/dist/types/config.d.ts +77 -40
- package/docs/api.md +34 -0
- package/docs/cli.md +3 -3
- package/drizzle/0006_add_component_source_format.sql +3 -0
- package/drizzle/meta/0006_snapshot.json +1941 -0
- package/drizzle/meta/_journal.json +8 -1
- package/package.json +34 -1
- package/src/app/components/Component/Preview.tsx +36 -50
- package/src/app/components/Markdown/CodeHighlight.tsx +73 -70
- package/src/app/components/context/PreviewContext.tsx +5 -5
- package/src/app/components/util/index.ts +7 -15
- package/src/app/lib/mcp/shape.ts +6 -5
- package/src/app/lib/registry-api/transfer.ts +7 -5
- package/src/app/pages/account/tokens.tsx +3 -1
- package/src/app-builder/build.ts +13 -8
- package/src/app-builder/client-config.ts +5 -3
- package/src/app-builder/config-diff/strategies/pattern.ts +1 -1
- package/src/app-builder/watchers/component.ts +3 -3
- package/src/app-builder/watchers/utils.ts +2 -3
- package/src/app-builder/watchers.ts +63 -57
- package/src/cache/build-cache.ts +16 -15
- package/src/catalog/README.md +92 -0
- package/src/catalog/define.ts +79 -0
- package/src/catalog/implementation.ts +145 -0
- package/src/catalog/index.ts +31 -0
- package/src/catalog/normalize.ts +143 -0
- package/src/catalog/previews.ts +111 -0
- package/src/catalog/renderers.ts +94 -0
- package/src/catalog/types.ts +74 -0
- package/src/cli/README.md +1 -1
- package/src/cli/auth/device.ts +8 -3
- package/src/cli/auth/store.ts +75 -18
- package/src/cli/make.ts +20 -72
- package/src/cli/scaffold.ts +25 -31
- package/src/commands/README.md +1 -1
- package/src/commands/checkout/index.ts +17 -7
- package/src/commands/compat/push-args.ts +2 -2
- package/src/commands/index.ts +0 -2
- package/src/commands/login/index.ts +20 -6
- package/src/commands/logout/index.ts +74 -20
- package/src/commands/publish/index.ts +19 -9
- package/src/commands/pull/index.ts +2 -2
- package/src/commands/push/index.ts +2 -2
- package/src/commands/types.ts +2 -0
- package/src/commands/utils.ts +36 -12
- package/src/config/README.md +63 -2
- package/src/config/catalog-include.ts +227 -0
- package/src/config/defaults.ts +24 -14
- package/src/config/env.ts +41 -0
- package/src/config/errors.ts +7 -0
- package/src/config/from-env.ts +26 -0
- package/src/config/helpers.ts +4 -2
- package/src/config/index.ts +7 -4
- package/src/config/loader.ts +168 -50
- package/src/config/resolve-env.ts +94 -0
- package/src/config/runtime.ts +188 -193
- package/src/config/validator.ts +4 -6
- package/src/handlebars.ts +18 -0
- package/src/index.d.ts +2 -2
- package/src/index.ts +124 -34
- package/src/pattern.ts +14 -0
- package/src/pipeline/index.ts +1 -1
- package/src/react.ts +52 -0
- package/src/registry/asset-storage/adapters/vercel-blob.ts +1 -1
- package/src/registry/asset-storage/define.ts +1 -1
- package/src/registry/asset-storage/resolve.ts +6 -3
- package/src/registry/checkout/index.ts +421 -157
- package/src/registry/connection.ts +72 -71
- package/src/registry/db/driver.ts +6 -17
- package/src/registry/db/index.ts +0 -1
- package/src/registry/db/schema.ts +2 -0
- package/src/registry/publish/index.ts +128 -31
- package/src/registry/publish/package.ts +14 -1
- package/src/registry/selection.ts +44 -0
- package/src/store/filesystem.ts +6 -6
- package/src/store/registry.ts +13 -2
- package/src/transformers/plugins/csf-render.ts +4 -2
- package/src/transformers/plugins/ssr-render.ts +15 -5
- package/src/transformers/preview/component/api.ts +13 -1
- package/src/transformers/preview/component/artifacts.ts +8 -4
- package/src/transformers/preview/component/builder.ts +17 -4
- package/src/transformers/preview/component/css.ts +6 -10
- package/src/transformers/preview/component/html.ts +30 -19
- package/src/transformers/preview/component/javascript.ts +1 -3
- package/src/transformers/preview/pattern/builder.ts +33 -20
- package/src/transformers/preview/types.ts +15 -1
- package/src/types/config.ts +76 -40
- package/templates/default/components/button/button.react.handoff.js.tpl +19 -23
- package/templates/default/components/button/button.react.handoff.ts.tpl +22 -22
- package/templates/default/env.tpl +10 -0
- package/templates/default/gitignore.tpl +7 -0
- package/templates/default/handoff.config.js.tpl +21 -182
- package/templates/default/handoff.config.ts.tpl +21 -166
- package/templates/default/handoff.config.with-examples.js.tpl +22 -180
- package/templates/default/handoff.config.with-examples.ts.tpl +22 -164
- package/config/templates/component/template.json +0 -49
- package/config/templates/template.html +0 -7
- package/dist/commands/make/template.d.ts +0 -8
- package/dist/commands/make/template.js +0 -43
- package/dist/config/entries.d.ts +0 -47
- package/dist/config/entries.js +0 -162
- package/dist/config/normalizers/declaration.d.ts +0 -11
- package/dist/config/normalizers/declaration.js +0 -122
- package/dist/config/normalizers/pattern.d.ts +0 -8
- package/dist/config/normalizers/pattern.js +0 -41
- package/dist/declarations/helpers.d.ts +0 -6
- package/dist/declarations/helpers.js +0 -19
- package/dist/declarations/index.d.ts +0 -2
- package/dist/declarations/index.js +0 -9
- package/dist/declarations/types.d.ts +0 -60
- package/src/commands/make/template.ts +0 -46
- package/src/config/entries.ts +0 -175
- package/src/config/normalizers/declaration.ts +0 -179
- package/src/config/normalizers/pattern.ts +0 -59
- package/src/declarations/helpers.ts +0 -36
- package/src/declarations/index.ts +0 -19
- package/src/declarations/types.ts +0 -70
- /package/dist/{declarations → catalog}/types.js +0 -0
package/README.md
CHANGED
|
@@ -66,11 +66,16 @@ my-handoff-project/
|
|
|
66
66
|
└─ out/ # build output; gitignored
|
|
67
67
|
```
|
|
68
68
|
|
|
69
|
-
##
|
|
69
|
+
## Catalog items
|
|
70
70
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
71
|
+
Every documented UI entry is a catalog item. Each item declares either an implementation or a composition of other items.
|
|
72
|
+
An implementation names its renderer. `defineCatalogItem` comes from the module for that renderer.
|
|
73
|
+
The declaration supplies stable identity, documentation metadata, source entries, and previews.
|
|
74
|
+
|
|
75
|
+
### React
|
|
76
|
+
|
|
77
|
+
Handoff finds the implementation file from its import, so you do not need to repeat the path.
|
|
78
|
+
Previews are named exports. `Preview<typeof item>` gives them the implementation's argument type.
|
|
74
79
|
|
|
75
80
|
```tsx
|
|
76
81
|
// components/example/Component.tsx
|
|
@@ -83,61 +88,136 @@ export default function Component({ label }: ComponentProps) {
|
|
|
83
88
|
}
|
|
84
89
|
```
|
|
85
90
|
|
|
86
|
-
```
|
|
87
|
-
// components/example/
|
|
88
|
-
import {
|
|
91
|
+
```tsx
|
|
92
|
+
// components/example/example.handoff.ts
|
|
93
|
+
import { defineCatalogItem, type Preview } from 'handoff-app/react';
|
|
89
94
|
import Component from './Component';
|
|
90
95
|
|
|
91
|
-
|
|
96
|
+
const item = defineCatalogItem({
|
|
92
97
|
id: 'component-id',
|
|
93
98
|
name: 'Component name',
|
|
94
99
|
description: 'Usage guidance for the component.',
|
|
95
100
|
group: 'Group name',
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
},
|
|
101
|
+
implementation: Component,
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
export default item;
|
|
105
|
+
|
|
106
|
+
type ComponentPreview = Preview<typeof item>;
|
|
107
|
+
|
|
108
|
+
export const Default = {
|
|
109
|
+
args: { label: 'Example' },
|
|
110
|
+
} satisfies ComponentPreview;
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The export name is the preview name. Use `name` to set a different display title.
|
|
114
|
+
|
|
115
|
+
### Handlebars
|
|
116
|
+
|
|
117
|
+
The implementation is the path to the template. Arguments are `Record<string, unknown>` by default;
|
|
118
|
+
an explicit argument type is supplied through `defineCatalogItem<BadgeArgs>`.
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
// components/badge/badge.handoff.ts
|
|
122
|
+
import { defineCatalogItem, type Preview } from 'handoff-app/handlebars';
|
|
123
|
+
|
|
124
|
+
const item = defineCatalogItem({
|
|
125
|
+
id: 'badge',
|
|
126
|
+
name: 'Badge',
|
|
127
|
+
implementation: './Badge.hbs',
|
|
105
128
|
});
|
|
129
|
+
|
|
130
|
+
export default item;
|
|
131
|
+
|
|
132
|
+
type BadgePreview = Preview<typeof item>;
|
|
133
|
+
|
|
134
|
+
export const Primary = {
|
|
135
|
+
args: { variant: 'primary', children: 'New' },
|
|
136
|
+
} satisfies BadgePreview;
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### CSF
|
|
140
|
+
|
|
141
|
+
CSF is a source format. A story file uses the renderer from the module that declares it. A React item references an existing CSF file with `fromCSF`.
|
|
142
|
+
The CSF file stays unchanged and defines its previews through named exports. Each story's `args` merge with and override `meta.args`.
|
|
143
|
+
Handoff preserves story names, `argTypes`, and `render` functions.
|
|
144
|
+
It finds the React component through `meta.component`, then documents and publishes it with the story file.
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
// components/card/card.handoff.ts
|
|
148
|
+
import { defineCatalogItem, fromCSF } from 'handoff-app/react';
|
|
149
|
+
|
|
150
|
+
export default defineCatalogItem({
|
|
151
|
+
id: 'card',
|
|
152
|
+
name: 'Card',
|
|
153
|
+
implementation: fromCSF('./Card.stories.tsx'),
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
`Meta` and `StoryObj` are exported from `handoff-app/react`, so a story file type-checks without a
|
|
158
|
+
Storybook dependency. A project that already has Storybook keeps using its own types.
|
|
159
|
+
|
|
160
|
+
```tsx
|
|
161
|
+
// components/card/Card.stories.tsx
|
|
162
|
+
import { type Meta, type StoryObj } from 'handoff-app/react';
|
|
163
|
+
import Card from './Card';
|
|
164
|
+
|
|
165
|
+
const meta = { component: Card } satisfies Meta<typeof Card>;
|
|
166
|
+
export default meta;
|
|
167
|
+
|
|
168
|
+
export const Primary: StoryObj<typeof meta> = {
|
|
169
|
+
args: { title: 'Example' },
|
|
170
|
+
};
|
|
106
171
|
```
|
|
107
172
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
173
|
+
A CSF preview is rendered on the server and is not hydrated. A direct React implementation is
|
|
174
|
+
hydrated in the browser.
|
|
175
|
+
|
|
176
|
+
### Compositions
|
|
177
|
+
|
|
178
|
+
A composition references other items by stable id. A named preview can be selected and its arguments
|
|
179
|
+
can be overridden by each reference. A composition needs no renderer, so it is declared with
|
|
180
|
+
`defineCatalogItem` from `handoff-app/pattern`.
|
|
111
181
|
|
|
112
182
|
```ts
|
|
113
|
-
// patterns/example/
|
|
114
|
-
import {
|
|
183
|
+
// patterns/example/example.handoff.ts
|
|
184
|
+
import { defineCatalogItem } from 'handoff-app/pattern';
|
|
115
185
|
|
|
116
|
-
export default
|
|
186
|
+
export default defineCatalogItem({
|
|
117
187
|
id: 'pattern-id',
|
|
118
188
|
name: 'Pattern name',
|
|
119
189
|
description: 'Purpose and usage of the composition.',
|
|
120
190
|
group: 'Group name',
|
|
121
|
-
|
|
122
|
-
{
|
|
123
|
-
|
|
124
|
-
preview: 'default',
|
|
125
|
-
args: { label: 'Pattern example' },
|
|
126
|
-
},
|
|
191
|
+
composition: [
|
|
192
|
+
{ ref: 'component-id', preview: 'Default' },
|
|
193
|
+
{ ref: 'badge', args: { children: 'Send' } },
|
|
127
194
|
],
|
|
128
195
|
});
|
|
129
196
|
```
|
|
130
197
|
|
|
131
|
-
|
|
198
|
+
An item declares `implementation` or `composition`, never both. Terms such as atom, element, and
|
|
199
|
+
block stay optional classification metadata on `type` and `categories`.
|
|
200
|
+
|
|
201
|
+
The `id` addresses the item everywhere: its artifacts, its documentation URL, and its publish and
|
|
202
|
+
checkout commands. Components and patterns share one namespace, so each id must be unique across
|
|
203
|
+
both.
|
|
204
|
+
|
|
205
|
+
If two declarations claim one id, Handoff keeps the first and skips the second. The warning names
|
|
206
|
+
both files. `publish` refuses to run until each id is unique.
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
### Registration
|
|
210
|
+
|
|
211
|
+
Catalog directories are registered in one place. A path is either an item directory or a collection
|
|
212
|
+
directory whose subdirectories are each treated as an item.
|
|
132
213
|
|
|
133
214
|
```ts
|
|
134
215
|
// handoff.config.ts
|
|
135
216
|
import { defineConfig } from 'handoff-app';
|
|
136
217
|
|
|
137
218
|
export default defineConfig({
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
patterns: ['patterns'],
|
|
219
|
+
catalog: {
|
|
220
|
+
include: ['components', 'patterns'],
|
|
141
221
|
},
|
|
142
222
|
runtime: {
|
|
143
223
|
workspace: {
|
|
@@ -147,6 +227,11 @@ export default defineConfig({
|
|
|
147
227
|
});
|
|
148
228
|
```
|
|
149
229
|
|
|
230
|
+
### Upgrade from version 1.x.x to version 2.x.x
|
|
231
|
+
|
|
232
|
+
See the [version 1.x.x to version 2.x.x migration guide](UPGRADE.md#version-1xx-to-version-2xx)
|
|
233
|
+
for breaking changes, migration steps, and upgrade verification.
|
|
234
|
+
|
|
150
235
|
Custom documentation pages are Markdown files under `pages/`. Their relative
|
|
151
236
|
paths become their routes and registry IDs.
|
|
152
237
|
|
|
@@ -274,12 +359,12 @@ runtime variables listed above are supplied through the deployment environment.
|
|
|
274
359
|
|
|
275
360
|
#### Neon PostgreSQL
|
|
276
361
|
|
|
277
|
-
|
|
362
|
+
Import `fromEnv` from `handoff-app`. Select the Neon connection driver in `handoff.config.ts`:
|
|
278
363
|
|
|
279
364
|
```ts
|
|
280
365
|
runtime: {
|
|
281
366
|
registry: {
|
|
282
|
-
|
|
367
|
+
databaseUrl: fromEnv('DATABASE_URL'),
|
|
283
368
|
database: {
|
|
284
369
|
driver: 'neon',
|
|
285
370
|
},
|
|
@@ -319,6 +404,12 @@ should not be left unattended before installation is complete.
|
|
|
319
404
|
|
|
320
405
|
### 4. Workspace authorization
|
|
321
406
|
|
|
407
|
+
A workspace reaches a registry with a registry URL and an access token. There
|
|
408
|
+
are two ways to supply them. Both use the same kind of token, and both are
|
|
409
|
+
listed and revoked under Account → Access tokens in the registry.
|
|
410
|
+
|
|
411
|
+
#### Device login
|
|
412
|
+
|
|
322
413
|
CLI authorization is started from the source workspace with:
|
|
323
414
|
|
|
324
415
|
```bash
|
|
@@ -326,9 +417,48 @@ npm run login -- --url http://localhost:4000
|
|
|
326
417
|
```
|
|
327
418
|
|
|
328
419
|
Registry sign-in, entry of the displayed device code, and CLI approval are
|
|
329
|
-
completed in the browser. The
|
|
420
|
+
completed in the browser. The issued credential is saved in
|
|
330
421
|
`.handoff/cli-auth.json` for that exact registry URL.
|
|
331
422
|
|
|
423
|
+
One credential is saved per profile, so a workspace can stay signed in to
|
|
424
|
+
several registries at the same time:
|
|
425
|
+
|
|
426
|
+
```bash
|
|
427
|
+
npm run login -- --profile staging --url https://staging.example.com
|
|
428
|
+
npm run publish -- all --profile staging
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
A login profile name is free. It needs no `handoff.config.<name>.*` file, and
|
|
432
|
+
`login` is the only command that accepts a new name. A profile without its own
|
|
433
|
+
login falls back to the default login, so one `npm run login` is still enough
|
|
434
|
+
for a workspace with one registry.
|
|
435
|
+
|
|
436
|
+
`npm run logout` revokes and removes the login of the selected profile. The
|
|
437
|
+
`--all` option removes every saved login.
|
|
438
|
+
|
|
439
|
+
#### Environment variables
|
|
440
|
+
|
|
441
|
+
A token is created in the registry under Account → Access tokens. Read and
|
|
442
|
+
write access is required to publish; read access is enough to check out. The
|
|
443
|
+
token and the registry URL are then set in `.env`:
|
|
444
|
+
|
|
445
|
+
```dotenv
|
|
446
|
+
HANDOFF_REGISTRY_URL=http://localhost:4000
|
|
447
|
+
HANDOFF_REGISTRY_ACCESS_TOKEN=hnd_...
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
No configuration file entry is needed, because these two variables are the
|
|
451
|
+
defaults for `runtime.registryConnection`. A selected profile reads
|
|
452
|
+
`.env.<profile>` on top of `.env`, so one workspace can address a different
|
|
453
|
+
registry per profile. In CI, the job environment supplies the same two
|
|
454
|
+
variables instead of a file.
|
|
455
|
+
|
|
456
|
+
Environment values win over a saved device login, so a CI job stays
|
|
457
|
+
deterministic on a machine where a developer is signed in. A token is only used
|
|
458
|
+
for the registry URL it was issued for. If the environment names a different
|
|
459
|
+
registry than the login of the selected profile, publish and checkout report
|
|
460
|
+
which login was skipped and why.
|
|
461
|
+
|
|
332
462
|
### 5. Content publishing
|
|
333
463
|
|
|
334
464
|
Every kind in the workspace is published in dependency order with:
|
|
@@ -340,20 +470,23 @@ npm run publish -- all
|
|
|
340
470
|
A single kind is published on its own:
|
|
341
471
|
|
|
342
472
|
```bash
|
|
343
|
-
npm run publish --
|
|
344
|
-
npm run publish -- patterns
|
|
473
|
+
npm run publish -- catalog
|
|
345
474
|
npm run publish -- pages
|
|
346
475
|
npm run publish -- tokens
|
|
347
476
|
npm run publish -- assets
|
|
348
477
|
```
|
|
349
478
|
|
|
479
|
+
`catalog` covers every catalog item. An item is stored as a component or as a
|
|
480
|
+
pattern, and its declaration decides which. The command names items and never a
|
|
481
|
+
kind.
|
|
482
|
+
|
|
350
483
|
Publishing tokens or assets runs the Figma data pipeline before upload, so the
|
|
351
484
|
documented Figma credentials must be available.
|
|
352
485
|
|
|
353
486
|
One or more IDs can be appended to narrow a publish to those entities:
|
|
354
487
|
|
|
355
488
|
```bash
|
|
356
|
-
npm run publish --
|
|
489
|
+
npm run publish -- catalog item-id another-id
|
|
357
490
|
```
|
|
358
491
|
|
|
359
492
|
`--dry-run` reports what would be uploaded and contacts no registry at all, so
|
|
@@ -363,24 +496,29 @@ the existing output, and the two combine to leave the workspace untouched:
|
|
|
363
496
|
|
|
364
497
|
```bash
|
|
365
498
|
npm run publish -- all --dry-run
|
|
366
|
-
npm run publish --
|
|
499
|
+
npm run publish -- catalog --no-build
|
|
367
500
|
```
|
|
368
501
|
|
|
369
502
|
`checkout` takes the same `all`, multi-ID, and `--dry-run` forms. A dry-run
|
|
370
503
|
checkout reads from the registry, lists the files it would create or overwrite,
|
|
371
504
|
and writes nothing.
|
|
372
505
|
|
|
373
|
-
After the registry is reloaded, the published
|
|
374
|
-
|
|
375
|
-
|
|
506
|
+
After the registry is reloaded, the published catalog items and foundations are
|
|
507
|
+
visible. Published database records are read by registry pages; the local
|
|
508
|
+
workspace is never read directly.
|
|
376
509
|
|
|
377
|
-
For CI,
|
|
510
|
+
For CI, supply `HANDOFF_REGISTRY_URL` and `HANDOFF_REGISTRY_ACCESS_TOKEN`
|
|
511
|
+
through the job environment, as described under
|
|
512
|
+
[Workspace authorization](#4-workspace-authorization). A connection block in
|
|
513
|
+
`handoff.config.ts` is needed only to pin the URL in the repository, or to read
|
|
514
|
+
the values from differently named variables (`fromEnv` is imported from
|
|
515
|
+
`handoff-app`):
|
|
378
516
|
|
|
379
517
|
```ts
|
|
380
518
|
runtime: {
|
|
381
519
|
registryConnection: {
|
|
382
520
|
url: 'https://registry.example.com',
|
|
383
|
-
|
|
521
|
+
accessToken: fromEnv('HANDOFF_REGISTRY_ACCESS_TOKEN'),
|
|
384
522
|
},
|
|
385
523
|
},
|
|
386
524
|
```
|
|
@@ -433,17 +571,19 @@ for Claude Code, Cursor and VS Code behind the plug icon in the header. By hand:
|
|
|
433
571
|
## Configuration
|
|
434
572
|
|
|
435
573
|
Configuration is read from `handoff.config.ts`, `.js`, `.cjs`, or `.json`, in
|
|
436
|
-
that order. `defineConfig` provides typed authoring.
|
|
437
|
-
|
|
574
|
+
that order. `defineConfig` provides typed authoring. Values merge onto the
|
|
575
|
+
defaults: plain objects merge recursively, and arrays, scalars, `null`, and
|
|
576
|
+
functions replace.
|
|
438
577
|
|
|
439
578
|
Useful environment variables:
|
|
440
579
|
|
|
441
580
|
| Variable | Purpose |
|
|
442
581
|
| --- | --- |
|
|
582
|
+
| `HANDOFF_PROFILE` | Config profile merged onto the base config |
|
|
443
583
|
| `HANDOFF_FIGMA_PROJECT_ID` | Figma file ID used by `fetch` |
|
|
444
584
|
| `HANDOFF_DEV_ACCESS_TOKEN` | Figma personal access token used by `fetch` |
|
|
445
585
|
| `HANDOFF_REGISTRY_URL` | Connected workspace registry URL |
|
|
446
|
-
| `HANDOFF_REGISTRY_ACCESS_TOKEN` |
|
|
586
|
+
| `HANDOFF_REGISTRY_ACCESS_TOKEN` | Registry access token used by a connected workspace |
|
|
447
587
|
| `HANDOFF_SYNC_SECRET` | Optional deployment-wide registry credential |
|
|
448
588
|
| `DATABASE_URL` | Registry PostgreSQL connection string |
|
|
449
589
|
| `AUTH_SECRET` | Registry session-signing secret, at least 32 characters |
|
|
@@ -462,6 +602,52 @@ Vercel Blob or a custom adapter can be selected through
|
|
|
462
602
|
selected through `runtime.registry.database.driver`; PostgreSQL is used by
|
|
463
603
|
both.
|
|
464
604
|
|
|
605
|
+
## Profiles
|
|
606
|
+
|
|
607
|
+
A profile is a sidecar config file that merges onto the base config. It holds
|
|
608
|
+
only what changes between environments, so a project keeps one shared config
|
|
609
|
+
instead of a second complete copy of it.
|
|
610
|
+
|
|
611
|
+
- The base config is `handoff.config.ts`, `.js`, `.cjs`, or `.json`. It is the
|
|
612
|
+
only config file loaded when no profile is selected.
|
|
613
|
+
- A profile file is `handoff.config.<profile>.*`, with the same four
|
|
614
|
+
extensions.
|
|
615
|
+
- Select a profile with `--profile <name>` or with `HANDOFF_PROFILE`.
|
|
616
|
+
`--profile` takes precedence over `HANDOFF_PROFILE`.
|
|
617
|
+
- Profile names are not predefined. A name can contain lowercase letters,
|
|
618
|
+
numbers, and hyphens.
|
|
619
|
+
- A selected profile must exist. If no `handoff.config.<name>.*` file is found,
|
|
620
|
+
the command stops with an error.
|
|
621
|
+
- `login`, `logout`, `publish`, and `checkout` also accept a profile that has
|
|
622
|
+
only a saved registry login, because there the profile selects the registry.
|
|
623
|
+
Every other command still needs the config file.
|
|
624
|
+
- Layers resolve as defaults, base config, profile, then programmatic config,
|
|
625
|
+
with the merge rules described under [Configuration](#configuration).
|
|
626
|
+
- A selected profile also reads `.env.<profile>` on top of `.env`, when that
|
|
627
|
+
file exists. Both are read from the directory the command runs in, and a
|
|
628
|
+
variable already set in the environment beats both files.
|
|
629
|
+
|
|
630
|
+
```bash
|
|
631
|
+
npx handoff-app build --target registry --profile registry
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
`build --target registry` always packages a registry-mode application, so a
|
|
635
|
+
profile does not need to set `runtime.mode`. This makes a profile a good place
|
|
636
|
+
for the registry build settings: the database driver, the database
|
|
637
|
+
environment-variable name, the asset storage, and whether MCP is enabled. A
|
|
638
|
+
hosting provider or a CI job selects the profile through `HANDOFF_PROFILE`.
|
|
639
|
+
|
|
640
|
+
`defineConfig` types a profile as well as a base config. The generated
|
|
641
|
+
`.gitignore` lists `handoff.config.local.*`, which makes `local` the usual name
|
|
642
|
+
for a profile that stays on one machine.
|
|
643
|
+
|
|
644
|
+
Arrays replace, so a profile that declares `catalog.include` also decides what
|
|
645
|
+
`make` and `checkout` register.
|
|
646
|
+
|
|
647
|
+
`.env.<profile>` is read once at startup rather than watched.
|
|
648
|
+
`HANDOFF_WORKING_PATH` cannot be set from it, because the working path is
|
|
649
|
+
resolved before any profile is known.
|
|
650
|
+
|
|
465
651
|
## CLI reference
|
|
466
652
|
|
|
467
653
|
| Command | Description |
|
|
@@ -473,12 +659,14 @@ both.
|
|
|
473
659
|
| `npm run build -- [--target static\|registry]` | The static site or standalone registry bundle is built |
|
|
474
660
|
| `npm run db:migrate` | Registry database migrations are applied |
|
|
475
661
|
| `npm run validate` | Configured components are validated |
|
|
476
|
-
| `npm run publish -- <kind\|all> [id...]` |
|
|
662
|
+
| `npm run publish -- <kind\|all> [id...]` | Catalog items, pages, tokens, or assets are published |
|
|
477
663
|
| `npm run checkout -- <kind\|all> [id...]` | Published content is pulled into a workspace |
|
|
478
|
-
| `npm run login -- --url <url>` | The CLI is authorized through the registry device flow |
|
|
479
|
-
| `npm run logout -- [--
|
|
664
|
+
| `npm run login -- [--profile <name>] --url <url>` | The CLI is authorized through the registry device flow |
|
|
665
|
+
| `npm run logout -- [--profile <name>] [--all]` | Saved CLI credentials are revoked and removed |
|
|
480
666
|
|
|
481
|
-
|
|
667
|
+
Every command except `init` accepts `-c, --config`, `--profile`, `-d, --debug`,
|
|
668
|
+
and `-f, --force`. `publish` and `checkout` additionally accept `--dry-run`, and
|
|
669
|
+
`publish` accepts `--no-build`.
|
|
482
670
|
|
|
483
671
|
Arguments after `--` are forwarded to the local CLI. Exact options can be shown
|
|
484
672
|
by adding `--help` after the separator. Advanced configuration and hooks are
|
package/UPGRADE.md
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Upgrade Handoff
|
|
2
|
+
|
|
3
|
+
This document contains migration steps for each major version upgrade.
|
|
4
|
+
|
|
5
|
+
## Version 1.x.x to version 2.x.x
|
|
6
|
+
|
|
7
|
+
This guide describes how to upgrade a Handoff project from version 1.x.x to version 2.x.x.
|
|
8
|
+
Each feature section identifies the affected projects and the required changes.
|
|
9
|
+
|
|
10
|
+
### Before you start
|
|
11
|
+
|
|
12
|
+
1. Verify that the project builds with its current Handoff version.
|
|
13
|
+
2. Save the project files, package version, and lockfile in version control.
|
|
14
|
+
3. Install the version 2.x.x package that you plan to use.
|
|
15
|
+
4. Apply the migration sections that affect your project.
|
|
16
|
+
|
|
17
|
+
### Breaking changes
|
|
18
|
+
|
|
19
|
+
| Change | Affected projects |
|
|
20
|
+
| --- | --- |
|
|
21
|
+
| [Figma token environment references](#figma-token-environment-references) | Projects that put a Figma token directly in config |
|
|
22
|
+
| [Catalog items](#catalog-items) | Projects with component or pattern declarations |
|
|
23
|
+
|
|
24
|
+
<!-- Add future breaking changes as feature sections before "Verify the upgrade". Add each section to this table. -->
|
|
25
|
+
|
|
26
|
+
### Figma token environment references
|
|
27
|
+
|
|
28
|
+
`devAccessToken` and its legacy spelling `dev_access_token` now accept only an environment reference.
|
|
29
|
+
A literal token throws `HandoffConfigError`, including in JavaScript and JSON configs.
|
|
30
|
+
Move the token to the environment and replace the literal:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { defineConfig, fromEnv } from 'handoff-app';
|
|
34
|
+
|
|
35
|
+
export default defineConfig({
|
|
36
|
+
devAccessToken: fromEnv('HANDOFF_DEV_ACCESS_TOKEN'),
|
|
37
|
+
});
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
For JSON, use `"devAccessToken": { "$env": "HANDOFF_DEV_ACCESS_TOKEN" }`.
|
|
41
|
+
If you already use `HANDOFF_DEV_ACCESS_TOKEN` and omit the config property, no change is required.
|
|
42
|
+
Environment references resolve after profile merging. Higher-layer literals still override default
|
|
43
|
+
environment seeds for properties that allow literals, such as output directories.
|
|
44
|
+
|
|
45
|
+
### Catalog items
|
|
46
|
+
|
|
47
|
+
#### Affected projects
|
|
48
|
+
|
|
49
|
+
This change affects projects that use the old component or pattern registration API.
|
|
50
|
+
It also affects projects that use the deprecated API from an earlier version 2.x.x prerelease.
|
|
51
|
+
Version 2.x.x requires `defineCatalogItem` for implementations and compositions.
|
|
52
|
+
|
|
53
|
+
#### Register catalog directories
|
|
54
|
+
|
|
55
|
+
Move component and pattern directories from `entries` to `catalog.include`.
|
|
56
|
+
|
|
57
|
+
Version 1.x.x:
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
entries: { components: ['components'], patterns: ['patterns'], scss: 'styles/main.scss' }
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Version 2.x.x:
|
|
64
|
+
|
|
65
|
+
```js
|
|
66
|
+
catalog: { include: ['components', 'patterns'] },
|
|
67
|
+
entries: { scss: 'styles/main.scss' }
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Each path can name one item directory or a collection of item directories. Global `entries.js` and `entries.scss` still work.
|
|
71
|
+
|
|
72
|
+
#### Convert declaration files
|
|
73
|
+
|
|
74
|
+
Use `<name>.handoff.ts`, `<name>.handoff.js`, or `<name>.handoff.cjs`.
|
|
75
|
+
Replace legacy filenames such as `button.json` or `button.js`.
|
|
76
|
+
|
|
77
|
+
Version 2.x.x does not support JSON item declarations, including `.handoff.json`.
|
|
78
|
+
JSON project config (`handoff.config.json`) remains supported.
|
|
79
|
+
|
|
80
|
+
If `runtime.workspace.declarationFormat` is `json`, change it to `ts`, `js`, or `cjs`. The default remains `ts`.
|
|
81
|
+
|
|
82
|
+
#### Replace declaration helpers
|
|
83
|
+
|
|
84
|
+
| Removed API | Replacement |
|
|
85
|
+
| --- | --- |
|
|
86
|
+
| `defineReactComponent(Component, config)` | `defineCatalogItem({ ...config, implementation: Component })` from `handoff-app/react` |
|
|
87
|
+
| `defineHandlebarsComponent(config)` | `defineCatalogItem({ ...config, implementation: './Button.hbs' })` from `handoff-app/handlebars` |
|
|
88
|
+
| `defineCsfComponent(config)` | `defineCatalogItem({ ...config, implementation: fromCSF('./Button.stories.tsx') })` from `handoff-app/react` |
|
|
89
|
+
| `defineComponent(config)` | `defineCatalogItem({ ...config, implementation: './Button.tsx' })` from the module for its renderer |
|
|
90
|
+
| `definePattern({ components })` | `defineCatalogItem({ composition })` from `handoff-app/pattern` |
|
|
91
|
+
|
|
92
|
+
Remove the old `renderer`, `entries.component`, `entries.template`, and `entries.story` fields.
|
|
93
|
+
The implementation supplies the renderer and source file.
|
|
94
|
+
Keep the supporting `entries.js`, `entries.scss`, `entries.schema`, and `entries.templates` paths that your item uses.
|
|
95
|
+
Rename the metadata fields:
|
|
96
|
+
|
|
97
|
+
| Old field | Version 2.x.x field |
|
|
98
|
+
| --- | --- |
|
|
99
|
+
| `title` | `name` |
|
|
100
|
+
| `should_do` | `shouldDo` |
|
|
101
|
+
| `should_not_do` | `shouldNotDo` |
|
|
102
|
+
|
|
103
|
+
##### React
|
|
104
|
+
|
|
105
|
+
```ts
|
|
106
|
+
import { defineCatalogItem, type Preview } from 'handoff-app/react';
|
|
107
|
+
import Button from './Button';
|
|
108
|
+
|
|
109
|
+
const item = defineCatalogItem({
|
|
110
|
+
name: 'Button',
|
|
111
|
+
implementation: Button,
|
|
112
|
+
entries: { scss: './button.scss' },
|
|
113
|
+
});
|
|
114
|
+
export default item;
|
|
115
|
+
export const Primary = { args: { children: 'Save' } } satisfies Preview<typeof item>;
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Imported components retain their prop types. A file path also works: `implementation: './Button.tsx'`.
|
|
119
|
+
Keep implementation files inside the item directory to publish them.
|
|
120
|
+
|
|
121
|
+
##### Handlebars and CommonJS
|
|
122
|
+
|
|
123
|
+
```js
|
|
124
|
+
const { defineCatalogItem } = require('handoff-app/handlebars');
|
|
125
|
+
|
|
126
|
+
exports.default = defineCatalogItem({
|
|
127
|
+
name: 'Badge',
|
|
128
|
+
implementation: './Badge.hbs',
|
|
129
|
+
});
|
|
130
|
+
exports.Primary = { args: { children: 'New' } };
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Use this form in `.handoff.js` or `.handoff.cjs`. JavaScript declarations can also use `import` and `export`.
|
|
134
|
+
|
|
135
|
+
##### CSF
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import { defineCatalogItem, fromCSF } from 'handoff-app/react';
|
|
139
|
+
|
|
140
|
+
export default defineCatalogItem({
|
|
141
|
+
name: 'Button',
|
|
142
|
+
implementation: fromCSF('./Button.stories.tsx'),
|
|
143
|
+
});
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
CSF is a React source format. The story file supplies the previews.
|
|
147
|
+
The filename does not select CSF automatically.
|
|
148
|
+
|
|
149
|
+
##### Compositions
|
|
150
|
+
|
|
151
|
+
```ts
|
|
152
|
+
import { defineCatalogItem } from 'handoff-app/pattern';
|
|
153
|
+
|
|
154
|
+
export default defineCatalogItem({
|
|
155
|
+
name: 'Toolbar',
|
|
156
|
+
composition: [{ ref: 'button', preview: 'Primary', args: { children: 'Save' } }],
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Rename `components` to `composition`.
|
|
161
|
+
Rename each member's `id` to `ref`.
|
|
162
|
+
Keep item IDs stable.
|
|
163
|
+
|
|
164
|
+
#### Export previews
|
|
165
|
+
|
|
166
|
+
Remove the inline `previews` map.
|
|
167
|
+
Export each preview beside the default catalog item.
|
|
168
|
+
Rename preview `title` to `name`.
|
|
169
|
+
Rename `values` to `args`:
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
export const Primary = { name: 'Primary action', args: { children: 'Save' } };
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
If a preview key is a valid export name, preserve its spelling and capitalization.
|
|
176
|
+
If a key is not a valid export name, rename it.
|
|
177
|
+
Update composition references to each renamed preview.
|
|
178
|
+
|
|
179
|
+
Previews appear in source export order.
|
|
180
|
+
|
|
181
|
+
For CommonJS declarations, use `exports.default` for the item.
|
|
182
|
+
Use a named export such as `exports.Primary` for each preview.
|
|
183
|
+
|
|
184
|
+
#### Replace declaration types
|
|
185
|
+
|
|
186
|
+
Replace imports of the removed types:
|
|
187
|
+
|
|
188
|
+
| Removed type | Replacement |
|
|
189
|
+
| --- | --- |
|
|
190
|
+
| `Component` | `CatalogItem` |
|
|
191
|
+
| `DeclarationPreview` | `CatalogPreview` or `Preview<typeof item>` |
|
|
192
|
+
| `PatternComponentRef` | `CompositionRef` |
|
|
193
|
+
| `ReactDeclarationConfig`, `HandlebarsDeclarationConfig`, `CsfDeclarationConfig` | The catalog helper's input type |
|
|
194
|
+
| `GenericDeclarationConfig`, `GenericPatternDeclarationConfig` | The catalog helper's input type, or `CatalogItemMeta` for shared metadata |
|
|
195
|
+
|
|
196
|
+
`RendererKind` comes from the catalog API and contains `react` and `handlebars`.
|
|
197
|
+
CSF uses `renderer: 'react'` with `format: 'csf'` inside `implementation`.
|
|
198
|
+
|
|
199
|
+
#### Registry projects
|
|
200
|
+
|
|
201
|
+
Checkout writes only catalog declarations.
|
|
202
|
+
Registry records require explicit renderer and source-format metadata where applicable.
|
|
203
|
+
|
|
204
|
+
### Verify the upgrade
|
|
205
|
+
|
|
206
|
+
After you apply the required migrations, verify the project:
|
|
207
|
+
|
|
208
|
+
1. Build the project with version 2.x.x.
|
|
209
|
+
2. Verify that all expected catalog items appear in the documentation.
|
|
210
|
+
3. Verify the preview order, arguments, and composition references.
|
|
211
|
+
4. Start the workspace with file watchers.
|
|
212
|
+
5. Edit a declaration to verify that its previews update.
|
|
213
|
+
|
|
214
|
+
If the project uses a registry, verify the published items:
|
|
215
|
+
|
|
216
|
+
1. Publish the migrated items.
|
|
217
|
+
2. Verify that checkout produces valid declarations.
|
|
218
|
+
3. Rebuild the checked-out items.
|
|
@@ -54,13 +54,10 @@ const config = {
|
|
|
54
54
|
ports: { app: 3000, websocket: 3001 },
|
|
55
55
|
},
|
|
56
56
|
// These are the entry points used to compile the target application
|
|
57
|
+
catalog: { include: ['./components'] },
|
|
57
58
|
entries: {
|
|
58
59
|
scss: './sass/main.scss',
|
|
59
60
|
js: './js/main.js',
|
|
60
|
-
components: ['./components'],
|
|
61
|
-
// Uncomment to enable pattern documentation pages.
|
|
62
|
-
// Patterns compose component previews into single-page views.
|
|
63
|
-
// patterns: ['./patterns'],
|
|
64
61
|
},
|
|
65
62
|
// These are the asset zip file download links
|
|
66
63
|
assetsZipLinks: {
|
|
@@ -34,11 +34,10 @@ export default defineConfig({
|
|
|
34
34
|
},
|
|
35
35
|
ports: { app: 3000, websocket: 3001 },
|
|
36
36
|
},
|
|
37
|
+
catalog: { include: ['./components'] },
|
|
37
38
|
entries: {
|
|
38
39
|
scss: './sass/main.scss',
|
|
39
40
|
js: './js/main.js',
|
|
40
|
-
components: ['./components'],
|
|
41
|
-
// patterns: ['./patterns'],
|
|
42
41
|
},
|
|
43
42
|
assetsZipLinks: {
|
|
44
43
|
icons: null,
|