@12ui/design 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/README.md +484 -0
  2. package/dist/artifact-materializer.d.ts +17 -0
  3. package/dist/artifact-materializer.d.ts.map +1 -0
  4. package/dist/artifact-materializer.js +66 -0
  5. package/dist/artifact-materializer.js.map +1 -0
  6. package/dist/cli-arguments.d.ts +8 -0
  7. package/dist/cli-arguments.d.ts.map +1 -0
  8. package/dist/cli-arguments.js +39 -0
  9. package/dist/cli-arguments.js.map +1 -0
  10. package/dist/cli-auth-command.d.ts +3 -0
  11. package/dist/cli-auth-command.d.ts.map +1 -0
  12. package/dist/cli-auth-command.js +100 -0
  13. package/dist/cli-auth-command.js.map +1 -0
  14. package/dist/cli-corpus-command.d.ts +12 -0
  15. package/dist/cli-corpus-command.d.ts.map +1 -0
  16. package/dist/cli-corpus-command.js +120 -0
  17. package/dist/cli-corpus-command.js.map +1 -0
  18. package/dist/cli-corpus-evidence.d.ts +17 -0
  19. package/dist/cli-corpus-evidence.d.ts.map +1 -0
  20. package/dist/cli-corpus-evidence.js +150 -0
  21. package/dist/cli-corpus-evidence.js.map +1 -0
  22. package/dist/cli-corpus-reference-downloads.d.ts +8 -0
  23. package/dist/cli-corpus-reference-downloads.d.ts.map +1 -0
  24. package/dist/cli-corpus-reference-downloads.js +111 -0
  25. package/dist/cli-corpus-reference-downloads.js.map +1 -0
  26. package/dist/cli-corpus-reference-receipts.d.ts +36 -0
  27. package/dist/cli-corpus-reference-receipts.d.ts.map +1 -0
  28. package/dist/cli-corpus-reference-receipts.js +137 -0
  29. package/dist/cli-corpus-reference-receipts.js.map +1 -0
  30. package/dist/cli-corpus-run.d.ts +17 -0
  31. package/dist/cli-corpus-run.d.ts.map +1 -0
  32. package/dist/cli-corpus-run.js +94 -0
  33. package/dist/cli-corpus-run.js.map +1 -0
  34. package/dist/cli-corpus-types.d.ts +52 -0
  35. package/dist/cli-corpus-types.d.ts.map +1 -0
  36. package/dist/cli-corpus-types.js +6 -0
  37. package/dist/cli-corpus-types.js.map +1 -0
  38. package/dist/cli-export-command.d.ts +3 -0
  39. package/dist/cli-export-command.d.ts.map +1 -0
  40. package/dist/cli-export-command.js +234 -0
  41. package/dist/cli-export-command.js.map +1 -0
  42. package/dist/cli-image-command.d.ts +8 -0
  43. package/dist/cli-image-command.d.ts.map +1 -0
  44. package/dist/cli-image-command.js +193 -0
  45. package/dist/cli-image-command.js.map +1 -0
  46. package/dist/cli-persistence.d.ts +25 -0
  47. package/dist/cli-persistence.d.ts.map +1 -0
  48. package/dist/cli-persistence.js +253 -0
  49. package/dist/cli-persistence.js.map +1 -0
  50. package/dist/cli-skill-command.d.ts +9 -0
  51. package/dist/cli-skill-command.d.ts.map +1 -0
  52. package/dist/cli-skill-command.js +215 -0
  53. package/dist/cli-skill-command.js.map +1 -0
  54. package/dist/cli.d.ts +3 -0
  55. package/dist/cli.d.ts.map +1 -0
  56. package/dist/cli.js +272 -0
  57. package/dist/cli.js.map +1 -0
  58. package/dist/codex-skill-config.d.ts +3 -0
  59. package/dist/codex-skill-config.d.ts.map +1 -0
  60. package/dist/codex-skill-config.js +83 -0
  61. package/dist/codex-skill-config.js.map +1 -0
  62. package/dist/config.d.ts +7 -0
  63. package/dist/config.d.ts.map +1 -0
  64. package/dist/config.js +34 -0
  65. package/dist/config.js.map +1 -0
  66. package/dist/conversion-client.d.ts +264 -0
  67. package/dist/conversion-client.d.ts.map +1 -0
  68. package/dist/conversion-client.js +445 -0
  69. package/dist/conversion-client.js.map +1 -0
  70. package/dist/conversion-models.d.ts +4 -0
  71. package/dist/conversion-models.d.ts.map +1 -0
  72. package/dist/conversion-models.js +3 -0
  73. package/dist/conversion-models.js.map +1 -0
  74. package/dist/conversion-outputs.d.ts +118 -0
  75. package/dist/conversion-outputs.d.ts.map +1 -0
  76. package/dist/conversion-outputs.js +84 -0
  77. package/dist/conversion-outputs.js.map +1 -0
  78. package/dist/conversion-problems.d.ts +3 -0
  79. package/dist/conversion-problems.d.ts.map +1 -0
  80. package/dist/conversion-problems.js +21 -0
  81. package/dist/conversion-problems.js.map +1 -0
  82. package/dist/corpus-client.d.ts +171 -0
  83. package/dist/corpus-client.d.ts.map +1 -0
  84. package/dist/corpus-client.js +85 -0
  85. package/dist/corpus-client.js.map +1 -0
  86. package/dist/credential-setup.d.ts +27 -0
  87. package/dist/credential-setup.d.ts.map +1 -0
  88. package/dist/credential-setup.js +242 -0
  89. package/dist/credential-setup.js.map +1 -0
  90. package/dist/credential-store.d.ts +12 -0
  91. package/dist/credential-store.d.ts.map +1 -0
  92. package/dist/credential-store.js +103 -0
  93. package/dist/credential-store.js.map +1 -0
  94. package/dist/idempotency-key.d.ts +2 -0
  95. package/dist/idempotency-key.d.ts.map +1 -0
  96. package/dist/idempotency-key.js +19 -0
  97. package/dist/idempotency-key.js.map +1 -0
  98. package/dist/image-generation-evidence.d.ts +26 -0
  99. package/dist/image-generation-evidence.d.ts.map +1 -0
  100. package/dist/image-generation-evidence.js +28 -0
  101. package/dist/image-generation-evidence.js.map +1 -0
  102. package/dist/image-output-width.d.ts +11 -0
  103. package/dist/image-output-width.d.ts.map +1 -0
  104. package/dist/image-output-width.js +55 -0
  105. package/dist/image-output-width.js.map +1 -0
  106. package/dist/image-provider-preflight.d.ts +21 -0
  107. package/dist/image-provider-preflight.d.ts.map +1 -0
  108. package/dist/image-provider-preflight.js +184 -0
  109. package/dist/image-provider-preflight.js.map +1 -0
  110. package/dist/index.d.ts +13 -0
  111. package/dist/index.d.ts.map +1 -0
  112. package/dist/index.js +13 -0
  113. package/dist/index.js.map +1 -0
  114. package/dist/legacy-codex-cleanup.d.ts +11 -0
  115. package/dist/legacy-codex-cleanup.d.ts.map +1 -0
  116. package/dist/legacy-codex-cleanup.js +147 -0
  117. package/dist/legacy-codex-cleanup.js.map +1 -0
  118. package/dist/legacy-skill-catalog.d.ts +5 -0
  119. package/dist/legacy-skill-catalog.d.ts.map +1 -0
  120. package/dist/legacy-skill-catalog.js +123 -0
  121. package/dist/legacy-skill-catalog.js.map +1 -0
  122. package/dist/local-conversion-input.d.ts +21 -0
  123. package/dist/local-conversion-input.d.ts.map +1 -0
  124. package/dist/local-conversion-input.js +54 -0
  125. package/dist/local-conversion-input.js.map +1 -0
  126. package/dist/login-auth.d.ts +63 -0
  127. package/dist/login-auth.d.ts.map +1 -0
  128. package/dist/login-auth.js +282 -0
  129. package/dist/login-auth.js.map +1 -0
  130. package/dist/package-client.d.ts +147 -0
  131. package/dist/package-client.d.ts.map +1 -0
  132. package/dist/package-client.js +119 -0
  133. package/dist/package-client.js.map +1 -0
  134. package/dist/project-profiles.d.ts +45 -0
  135. package/dist/project-profiles.d.ts.map +1 -0
  136. package/dist/project-profiles.js +162 -0
  137. package/dist/project-profiles.js.map +1 -0
  138. package/dist/responsive-quality.d.ts +26 -0
  139. package/dist/responsive-quality.d.ts.map +1 -0
  140. package/dist/responsive-quality.js +68 -0
  141. package/dist/responsive-quality.js.map +1 -0
  142. package/dist/server.d.ts +6 -0
  143. package/dist/server.d.ts.map +1 -0
  144. package/dist/server.js +173 -0
  145. package/dist/server.js.map +1 -0
  146. package/dist/skill-installer.d.ts +51 -0
  147. package/dist/skill-installer.d.ts.map +1 -0
  148. package/dist/skill-installer.js +328 -0
  149. package/dist/skill-installer.js.map +1 -0
  150. package/package.json +53 -0
  151. package/skills/design/SKILL.md +156 -0
  152. package/skills/design/agents/openai.yaml +6 -0
  153. package/skills/design/references/selection-contract.md +44 -0
  154. package/skills/design-convert/SKILL.md +118 -0
  155. package/skills/design-convert/agents/openai.yaml +6 -0
  156. package/skills/design-search/SKILL.md +86 -0
  157. package/skills/design-search/agents/openai.yaml +6 -0
package/README.md ADDED
@@ -0,0 +1,484 @@
1
+ # @12ui/design
2
+
3
+ `@12ui/design` is the canonical 12UI CLI, SDK, MCP server, and agent-skill
4
+ package. The `12ui` binary stays stable while package imports and installation
5
+ use the new name.
6
+
7
+ Install with Node on macOS, Linux, or Windows:
8
+
9
+ ```bash
10
+ npx -y @12ui/design skill install
11
+ ```
12
+
13
+ Or use the genuinely npm-free macOS/Linux installer:
14
+
15
+ ```bash
16
+ curl -fsSL https://12ui.com/install.sh | sh
17
+ ```
18
+
19
+ Both paths pin the exact CLI version, install `design`, `design-search`, and
20
+ `design-convert` into every detected Codex and Claude Code installation, and
21
+ open the 12UI device-approval page. The resulting user-owned credential has
22
+ `design.convert` and `design.corpus.retrieve`, is verified before use, and is
23
+ stored mode-0600 at `$XDG_CONFIG_HOME/12ui/credentials.json` or
24
+ `~/.config/12ui/credentials.json`.
25
+
26
+ An already verified credential is reused. The installer migrates the legacy
27
+ `~/.config/just-every/12ui/credentials.json` location; two conflicting files
28
+ fail closed. Existing unknown or locally modified skills also fail closed
29
+ unless `--force` is explicit. Use `--skill design-search` (or either other
30
+ skill name) to install one skill instead of the complete bundle.
31
+
32
+ ## Three visual interface skills
33
+
34
+ - `design` routes UI, web, and mobile work. Finished screenshots go directly
35
+ to conversion, tiny edits stay code-only, and rough briefs retrieve exactly
36
+ four references, generate four candidates conditioned on all four, select
37
+ one, convert only the winner, integrate it, and verify the real surface.
38
+ - `design-search` returns a ranked, diverse set of real Design Corpus
39
+ references while preserving endpoint order and metrics.
40
+ - `design-convert` turns a finished PNG, JPEG, or WebP into LayerDoc and any
41
+ supported responsive, fixed, project, or document export.
42
+
43
+ The design workflow exists because code-first agents often converge on safe,
44
+ generic visual defaults. Corpus-conditioned image generation expands the
45
+ design space and introduces personality; converting the selected image then
46
+ preserves that direction with near-pixel-perfect fidelity much faster than
47
+ manual recreation.
48
+
49
+ ```bash
50
+ 12ui skill status --json
51
+ 12ui auth status
52
+ 12ui corpus inspire --query-file ./brief.txt --out-dir ./references --count 4
53
+ 12ui image generate --prompt-file ./candidate-1.txt \
54
+ --reference-1 ./references/01.webp \
55
+ --reference-2 ./references/02.webp \
56
+ --reference-3 ./references/03.webp \
57
+ --reference-4 ./references/04.webp \
58
+ --out ./candidate-1.png \
59
+ --aspect landscape \
60
+ --project-root . \
61
+ --provider auto \
62
+ --idempotency-key product-candidate-1
63
+ 12ui export <base-layerdoc-conversion-id> \
64
+ --output html,pdf,psd,pptx,sketch,web_project \
65
+ --out-dir ./exports \
66
+ --web-profile ./web-profile.json \
67
+ --idempotency-key product-exports-v1
68
+ ```
69
+
70
+ `image generate` resolves one provider before dispatch: authenticated Codex,
71
+ then `OPENAI_API_KEY` from the process or exactly `<project-root>/.env`. It
72
+ refuses a Git-tracked `.env`, never stores or prints the key, persists attempt
73
+ evidence, and never switches providers after dispatch. Choose `--aspect`
74
+ explicitly for the target interface; it defaults to `landscape` for
75
+ compatibility.
76
+
77
+ `export` downloads one successful base LayerDoc once and dispatches the chosen
78
+ formats in parallel. Project exports require exact web/native profiles; image
79
+ extraction is not repeated.
80
+
81
+ ## Design Corpus retrieval
82
+
83
+ `TwelveUiCorpusClient` uses an API key with the `design.corpus.retrieve` scope.
84
+ Use `mode: 'record'` for product allocations so exposure history can prevent
85
+ the same references from dominating later runs. Use `mode: 'ignore'` only for
86
+ operator diagnostics and search inspection.
87
+
88
+ ```ts
89
+ import { TwelveUiCorpusClient } from '@12ui/design';
90
+
91
+ const corpus = new TwelveUiCorpusClient({
92
+ origin: process.env.TWELVE_UI_ORIGIN ?? 'https://12ui.com',
93
+ apiKey: process.env.TWELVE_UI_API_KEY!,
94
+ });
95
+
96
+ const status = await corpus.status();
97
+ const retrieved = await corpus.retrieve({
98
+ scope: 'r-track',
99
+ queries: [{
100
+ id: 'home',
101
+ brief: 'Editorial architecture home page',
102
+ direction: 'warm materiality and asymmetric typography',
103
+ targetCount: 6,
104
+ }],
105
+ context: {
106
+ mode: 'record',
107
+ purpose: 'run',
108
+ exposureScope: 'project:example',
109
+ allocationKey: 'example-home-v1',
110
+ },
111
+ });
112
+
113
+ const first = retrieved.allocations[0]!.results[0]!;
114
+ const metadata = await corpus.reference(first.referenceId);
115
+ const image = await corpus.download(first.referenceId, 'ref');
116
+ ```
117
+
118
+ The client sends the allocation key as the idempotency key. The API also
119
+ supports `logo-track`, batched queries, exclusions, preselected references, and
120
+ minimum quality thresholds. See
121
+ [`docs/corpus-v1.openapi.yaml`](https://github.com/just-every/12ui/blob/main/docs/corpus-v1.openapi.yaml).
122
+
123
+ For agent workflows that need four fresh, budget-metered inspiration images,
124
+ the CLI calls `/api/v1/corpus/inspire`, downloads the full reference images in
125
+ parallel, verifies each WebP, and writes a content-hashed manifest:
126
+
127
+ ```bash
128
+ node "$TWELVE_UI_REPO/packages/12ui/dist/cli.js" corpus inspire \
129
+ --query-file ./brief.txt \
130
+ --count 4 \
131
+ --wildness 0.6 \
132
+ --idempotency-key design-run:home-v1 \
133
+ --out-dir ./references
134
+ ```
135
+
136
+ The output directory must not already exist. Before dispatch, the CLI writes
137
+ `inspire-attempt.json` with the exact request and stable idempotency key. A
138
+ successful run also contains `manifest.json`, `inspire-evidence.json` with the
139
+ exact upstream response, four numbered reference files, and a durable digest
140
+ receipt for each image under `.reference-receipts/`. If the HTTP result is
141
+ ambiguous or one or more image downloads fail, finish the same allocation
142
+ without a second paid embedding:
143
+
144
+ ```bash
145
+ node "$TWELVE_UI_REPO/packages/12ui/dist/cli.js" corpus resume \
146
+ --out-dir ./references \
147
+ --origin https://12ui.com
148
+ ```
149
+
150
+ `corpus resume` reuses the attempt's idempotency key. The Worker either returns
151
+ the original stored response or reports the still-pending request; it never
152
+ dispatches a second embedding for that identity. Reusing a key with a different
153
+ validated request returns `409 idempotency_conflict`. A reference already on
154
+ disk is accepted only when its bytes match its exclusive digest receipt.
155
+
156
+ The CLI deliberately does not accept a free-form `--kind`: an unverified value
157
+ can consume the metered request while producing an empty set. Use the SDK's
158
+ `filters.kind` only when an integration has obtained and verified the exact
159
+ corpus kind value.
160
+
161
+ ## Multi-page packages
162
+
163
+ `TwelveUiConversionPackageClient` accepts the version-1 package manifest plus
164
+ explicit screenshot, LayerDoc, and raster-asset parts. It polls one durable
165
+ parent operation while the service converts missing viewports and exports final
166
+ pages in parallel.
167
+
168
+ ```ts
169
+ import { TwelveUiConversionPackageClient } from '@12ui/design';
170
+
171
+ const packages = new TwelveUiConversionPackageClient({
172
+ origin: process.env.TWELVE_UI_ORIGIN ?? 'https://12ui.com',
173
+ apiKey: process.env.TWELVE_UI_API_KEY!,
174
+ });
175
+
176
+ const created = await packages.createPackage({
177
+ manifest: {
178
+ version: 1,
179
+ output: 'layerdoc',
180
+ pages: [{
181
+ id: 'home',
182
+ ordinal: 0,
183
+ viewports: [{ id: 'hero', ordinal: 0, screenshot_part: 'home-hero' }],
184
+ }],
185
+ },
186
+ screenshots: [{
187
+ partId: 'home-hero',
188
+ bytes: screenshotBytes,
189
+ mediaType: 'image/png',
190
+ }],
191
+ });
192
+
193
+ const completed = created.status === 'succeeded'
194
+ ? created
195
+ : await packages.waitForPackage(created.id);
196
+ const home = await packages.downloadPage(completed, 'home');
197
+ ```
198
+
199
+ See [`docs/CONVERSION_PACKAGES.md`](https://github.com/just-every/12ui/blob/main/docs/CONVERSION_PACKAGES.md) for the
200
+ strict manifest, asset mapping, normalization, page-join, and limit contract.
201
+
202
+ ## CLI
203
+
204
+ ```bash
205
+ export TWELVE_UI_API_KEY=your-key
206
+ 12ui convert ./screen.png --output layerdoc --out ./screen.layerdoc.json
207
+ 12ui convert ./screen.png --output html --model pro --width 1440 --out ./screen.html --timeout-ms 7200000
208
+ 12ui convert ./screen.layerdoc.json --output html --out ./screen.html --idempotency-key screen-html-v1
209
+ 12ui convert ./screen.layerdoc.json --output pptx --out ./screen.pptx --idempotency-key screen-pptx-v1
210
+ 12ui convert ./screen.layerdoc.json --output web_project --profile ./react-tailwind.json --out ./screen-react.zip
211
+ 12ui convert ./screen.layerdoc.json --output app_project --profile '{"version":1,"framework":"swiftui","styling":"native","language":"swift","packaging":"project"}' --out ./screen-ios.zip
212
+ 12ui resume conversion-id --output layerdoc --out ./screen.layerdoc.json
213
+ ```
214
+
215
+ Each conversion also writes a verified `<out>.assets/manifest.json` plus every
216
+ signed raster artifact beside the requested result. Set `TWELVE_UI_ORIGIN` to
217
+ override `https://12ui.com`; waits default to the operation expiry and can be
218
+ bounded explicitly with `--timeout-ms`.
219
+
220
+ To retry an ambiguous create request safely, reuse the same explicit
221
+ `--idempotency-key`. When it is omitted, the client generates a new UUID.
222
+
223
+ Image conversions accept `--model fast|standard|pro`; omission selects
224
+ `standard`. In `layerdoc-worker-v148`, Fast, Standard, and Pro all use
225
+ `gpt-5.6-terra-low` for primary extraction. Fast retains color-guided
226
+ deterministic inpainting, source-grounded flat-border cutouts, and 1x source crops without
227
+ secondary metadata refinement, generative cleanup, provider background
228
+ removal, or upscaling. Standard has no secondary metadata refinement and uses
229
+ one atomic GPT Image 2 result for each opaque clean target, with Pixelcut-first
230
+ alpha isolation and Bria admitted only after a durable hard-invalid or
231
+ reconciled terminal Pixelcut failure. Standard performs no Luna candidate
232
+ review. Pro retains a separate `gpt-5.6-terra-low` metadata-refinement call, a
233
+ three-sample atomic opaque-clean portfolio with one comparative Luna review,
234
+ and the complete revision-frozen FAL alpha portfolio. GPT Image 2 is opaque-only.
235
+ Provider-routed cutouts keep enhanced upscaling; accepted deterministic Fast
236
+ cutouts are resized locally. The option is not accepted for LayerDoc input
237
+ because downstream compilation is deterministic.
238
+
239
+ Use `--width <px>` to set the native output canvas width. The CLI resizes image
240
+ input proportionally before upload, upscaling or downscaling as needed. The
241
+ selected model may analyze a smaller internal raster without changing that
242
+ authored width; do not switch to Pro merely because the native canvas exceeds
243
+ Standard's analysis edge. For example, an 800x600 source with `--width 1000`
244
+ becomes a 1000x750 conversion canvas, and a 1536x1024 Standard source remains a
245
+ 1536x1024 native canvas while analysis is bounded to 1500x1000. `--width 390`
246
+ turns a 1170 px-wide 3x phone capture into a 390 px conversion canvas. The
247
+ option is not accepted for LayerDoc input or `resume`.
248
+
249
+ LayerDoc input accepts the public v2 JSON downloaded from the API. Its signed
250
+ raster references must still be valid and must belong to the same authenticated
251
+ account. The service resolves those owned artifacts directly; it does not fetch
252
+ arbitrary remote URLs. LayerDoc input produces `layerdoc`, `html`, `svg`, `png`, `jpg`, `webp`, `pdf`, `psd`,
253
+ `pptx`, `sketch`, `web_project`, or `app_project`. Project outputs require
254
+ `--profile <json|file>`; the CLI also accepts `--profile @file.json`.
255
+
256
+ ## LayerDoc to downstream formats
257
+
258
+ The raw LayerDoc representation can be submitted directly to a second
259
+ conversion. This makes it possible to edit the document's text, geometry, or
260
+ style before compiling responsive HTML or a fixed export while retaining its
261
+ signed asset refs:
262
+
263
+ ```ts
264
+ import fs from 'node:fs';
265
+ import { TwelveUiConversionClient } from '@12ui/design';
266
+
267
+ const client = new TwelveUiConversionClient({
268
+ origin: process.env.TWELVE_UI_ORIGIN ?? 'https://12ui.com',
269
+ apiKey: process.env.TWELVE_UI_API_KEY!,
270
+ });
271
+
272
+ const created = await client.createConversion({
273
+ layerdoc: new Uint8Array(await fs.promises.readFile('./screen.layerdoc.json')),
274
+ filename: 'screen.layerdoc.json',
275
+ output: 'html',
276
+ });
277
+
278
+ const completed = created.status === 'succeeded'
279
+ ? created
280
+ : await client.waitForConversion(created.id, { expiresAt: created.expires_at });
281
+ const html = await client.downloadResult(completed.id, 'html');
282
+ await fs.promises.writeFile('./screen.html', html.bytes);
283
+ ```
284
+
285
+ For generated responsive layouts, derive from the successful image-to-LayerDoc
286
+ operation instead of uploading the image again:
287
+
288
+ ```ts
289
+ const responsive = await client.createConversion({
290
+ sourceConversionId: imageToLayerDoc.id,
291
+ output: 'html',
292
+ responsiveQuality: 'pro', // standard | pro
293
+ });
294
+ ```
295
+
296
+ This authenticated path reuses the canonical LayerDoc and raster assets from
297
+ `imageToLayerDoc`, consumes export quota, and starts directly at responsive
298
+ reference generation. The source conversion must still be retained and must
299
+ have been produced by the current pipeline revision.
300
+
301
+ While the operation is queued or running, poll it normally and read
302
+ `responsive_preview`. Its frames are returned in mobile, tablet, then compact
303
+ desktop plan order. Each frame moves through `waiting`, `generating`,
304
+ `generated`, `extracting`, `binding`, and `complete`; its signed `artifact`
305
+ appears immediately after the real generated reference PNG is durably
306
+ registered. `completed` and `total` count reference, extraction, and binding as
307
+ three durable steps per admitted anchor, while `progress.percent` remains the
308
+ overall conversion progress for a single progress bar.
309
+
310
+ Project output uses the same client method and returns a deterministic ZIP:
311
+
312
+ ```ts
313
+ const createdProject = await client.createConversion({
314
+ layerdoc: new Uint8Array(await fs.promises.readFile('./screen.layerdoc.json')),
315
+ filename: 'screen.layerdoc.json',
316
+ output: 'web_project',
317
+ profile: {
318
+ version: 1,
319
+ framework: 'react',
320
+ styling: 'tailwind',
321
+ language: 'typescript',
322
+ packaging: 'project',
323
+ },
324
+ });
325
+
326
+ const projectOperation = createdProject.status === 'succeeded'
327
+ ? createdProject
328
+ : await client.waitForConversion(createdProject.id, {
329
+ expiresAt: createdProject.expires_at,
330
+ });
331
+ const project = await client.downloadResult(projectOperation.id, 'web_project');
332
+ await fs.promises.writeFile('./screen-react.zip', project.bytes);
333
+ ```
334
+
335
+ The complete version-1 capability matrix is documented in
336
+ [`docs/EXPORT_FORMATS.md`](https://github.com/just-every/12ui/blob/main/docs/EXPORT_FORMATS.md). Unsupported framework,
337
+ styling, language, or packaging combinations fail before upload; the client
338
+ does not substitute a nearby target.
339
+
340
+ The 10 web framework slugs are `html`, `react`, `next`, `vue`, `nuxt`, `svelte`,
341
+ `sveltekit`, `angular`, `astro`, and `lit`. The 9 app framework slugs are `expo`,
342
+ `react_native`, `flutter`, `ionic_capacitor`, `swiftui`, `uikit`,
343
+ `jetpack_compose`, `android_views`, and `compose_multiplatform`. Import
344
+ `WEB_PROJECT_CAPABILITIES` and `APP_PROJECT_CAPABILITIES` from this package to
345
+ enumerate the exact styling, language, and packaging cross-products at runtime.
346
+ For web output, `component` is reusable component source, `page` is a route/page
347
+ entrypoint, and `project` is a runnable scaffold. For app output, `screen` is
348
+ integration-ready screen source for an existing app, while `project` adds the
349
+ runnable scaffold and build configuration.
350
+
351
+ ## Hosted `/convert` two-phase workflow
352
+
353
+ The Node client above remains API-key authenticated and may request any valid
354
+ image output directly. The free hosted web page uses the same HTTP resources
355
+ with an intentionally narrower contract:
356
+
357
+ 1. Create one image conversion with `output: "layerdoc"`.
358
+ 2. Poll the operation and replace the interactive preview only when
359
+ `operation.preview.revision` increases.
360
+ 3. Fetch the final LayerDoc representation after the source succeeds.
361
+ 4. Keep that hydrated JSON in memory and create independent LayerDoc-input jobs
362
+ for `html`, `svg`, `png`, `jpg`, `webp`, `pdf`, `psd`, `pptx`, `sketch`, `web_project`, and
363
+ `app_project`. Different formats and project profiles can
364
+ run in parallel; a repeated completed format should download the cached
365
+ representation rather than create another run.
366
+
367
+ No special export endpoint is involved. The source conversion remains the web
368
+ session root, and each export is an ordinary `POST /api/v1/convert` followed by
369
+ polling `GET /api/v1/convert/:id`. LayerDoc input is accepted only after its
370
+ source run has succeeded because the Worker verifies its signed artifacts,
371
+ expiry, and ownership before importing them.
372
+
373
+ Anonymous hosted-page requests send `X-12UI-Public-Preview: 1` and the same
374
+ browser-generated `X-12UI-Public-Visitor` value. Public image creation also
375
+ includes `cf-turnstile-response` in multipart form data; its verified action is
376
+ `12ui_convert_image`. Public quotas are 5 Fast, 2 Standard, no Pro, and 20
377
+ exports per salted IP hash per UTC day. Signed-in and API accounts receive 50
378
+ Fast, 20 Standard, 2 Pro, and 200 exports per stable account id and UTC day.
379
+ `GET /api/v1/convert/quota` returns all buckets; successful POST responses
380
+ identify the admitted bucket and return its limit and remaining count. Daily
381
+ exhaustion returns `429` with `Retry-After`.
382
+
383
+ All runs are sponsored and do not check or debit Login credits. Provider,
384
+ model, request-id, reservation, actual-cost, principal-tier, and account-id
385
+ records are retained in durable ledgers independent of expiring conversion
386
+ artifacts. Public headers are for the trusted anonymous preview; CLI and MCP
387
+ consumers should keep using a Login-issued API key.
388
+
389
+ Running LayerDoc operations may include an immutable `preview`: `structure`
390
+ contains the final layer tree and prepared source, while `standard` adds 1×
391
+ crops and cleaned plates. `result` remains reserved for the final enhanced,
392
+ manifest-last publication. `progress.active` reports durable completed/total
393
+ counts for each materialization lane.
394
+
395
+ ## Progressive Node consumer
396
+
397
+ `waitForConversion` intentionally returns only the terminal operation. A
398
+ consumer that wants live progress or previews should poll `getConversion` and
399
+ apply every operation snapshot:
400
+
401
+ ```ts
402
+ import fs from 'node:fs';
403
+ import { TwelveUiConversionClient } from '@12ui/design';
404
+
405
+ declare function renderLayerDoc(document: unknown): void;
406
+
407
+ const client = new TwelveUiConversionClient({
408
+ origin: process.env.TWELVE_UI_ORIGIN ?? 'https://12ui.com',
409
+ apiKey: process.env.TWELVE_UI_API_KEY!,
410
+ });
411
+
412
+ const created = await client.createConversion({
413
+ bytes: new Uint8Array(await fs.promises.readFile('./screen.png')),
414
+ filename: 'screen.png',
415
+ mediaType: 'image/png',
416
+ output: 'layerdoc',
417
+ model: 'standard',
418
+ });
419
+
420
+ let operation = created;
421
+ let displayedRevision = 0;
422
+
423
+ while (operation.status === 'queued' || operation.status === 'running') {
424
+ const progress = operation.progress;
425
+ if (progress) {
426
+ console.log(progress.percent, progress.stage, progress.milestone);
427
+ for (const lane of progress.active ?? []) {
428
+ console.log(lane.kind, lane.completed, lane.total, lane.status);
429
+ }
430
+ }
431
+
432
+ if (operation.preview && operation.preview.revision > displayedRevision) {
433
+ displayedRevision = operation.preview.revision;
434
+ renderLayerDoc(operation.preview.document);
435
+ // operation.preview.artifacts contain signed hrefs that are usable now.
436
+ }
437
+
438
+ await new Promise((resolve) => setTimeout(resolve, 1_000));
439
+ operation = await client.getConversion(operation.id);
440
+ }
441
+
442
+ if (operation.status !== 'succeeded' || operation.result?.kind !== 'layerdoc') {
443
+ throw new Error(operation.error?.detail ?? `Conversion ${operation.status}`);
444
+ }
445
+
446
+ // The terminal result is authoritative and replaces any displayed preview.
447
+ renderLayerDoc(operation.result.document);
448
+ ```
449
+
450
+ Raw HTTP consumers should use `Accept: application/json` while polling and
451
+ respect the response's `Retry-After` header (currently one second). `Prefer:
452
+ wait=20` only allows the create request to wait for an early result; it is not
453
+ a streaming connection. There is no SSE or WebSocket contract.
454
+
455
+ Progress and preview rules:
456
+
457
+ - `progress.percent` is the weighted server calculation; do not derive a
458
+ percentage from the stage name.
459
+ - `progress.active` is optional and image-specific. Do not assume every lane
460
+ is present or that lane order is fixed.
461
+ - `milestone` is `structure_ready` or `standard_ready` once that preview is
462
+ available.
463
+ - Previews currently apply to `output=layerdoc`. Downstream HTML and fixed
464
+ export operations still expose progress, but publish only their terminal result.
465
+ - Preview revision 1 is `quality: "structure"`; revision 2 is
466
+ `quality: "standard"`. Treat revisions as immutable snapshots.
467
+ - A preview artifact id is never repointed to different bytes. Signed `href`
468
+ values expire with the operation; re-read the operation to refresh URLs.
469
+ - On `succeeded`, use `result` as authoritative. On `failed` or `expired`, use
470
+ `error` and discard any displayed preview as a non-terminal aid.
471
+
472
+ ## MCP
473
+
474
+ ```bash
475
+ 12ui mcp
476
+ ```
477
+
478
+ The server exposes one tool, `design.convert`, backed by the same
479
+ `POST /api/v1/convert` and `GET /api/v1/convert/:id` contract as the CLI. Pass
480
+ `imagePath` for PNG/JPEG/WebP input or `layerdocPath` for public LayerDoc v2
481
+ JSON input; `layerdocPath` accepts every downstream output. Pass the exact
482
+ `profile` object for `web_project` or `app_project`. Set the optional
483
+ `idempotencyKey` when an ambiguous create may need to be retried with the same
484
+ stable key; otherwise the client generates a new UUID.
@@ -0,0 +1,17 @@
1
+ import { TwelveUiConversionClient, type ConversionOperation } from './conversion-client.js';
2
+ export type MaterializedArtifact = {
3
+ id: string;
4
+ role: string;
5
+ mediaType: string;
6
+ sha256: string;
7
+ sourceHref: string;
8
+ localPath: string;
9
+ };
10
+ export type MaterializedArtifactManifest = {
11
+ conversionId: string;
12
+ operationExpiresAt: string;
13
+ manifestFile: string;
14
+ artifacts: MaterializedArtifact[];
15
+ };
16
+ export declare const materializeConversionArtifacts: (client: TwelveUiConversionClient, operation: ConversionOperation, resultFile: string) => Promise<MaterializedArtifactManifest>;
17
+ //# sourceMappingURL=artifact-materializer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-materializer.d.ts","sourceRoot":"","sources":["../src/artifact-materializer.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,wBAAwB,EAExB,KAAK,mBAAmB,EACzB,MAAM,wBAAwB,CAAC;AAEhC,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC,YAAY,EAAE,MAAM,CAAC;IACrB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,oBAAoB,EAAE,CAAC;CACnC,CAAC;AA6BF,eAAO,MAAM,8BAA8B,GACzC,QAAQ,wBAAwB,EAChC,WAAW,mBAAmB,EAC9B,YAAY,MAAM,KACjB,OAAO,CAAC,4BAA4B,CA2BtC,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { mkdir, writeFile } from 'node:fs/promises';
3
+ import path from 'node:path';
4
+ const extensionForMediaType = (mediaType) => {
5
+ const normalized = mediaType.toLowerCase().split(';', 1)[0]?.trim();
6
+ if (normalized === 'image/png')
7
+ return '.png';
8
+ if (normalized === 'image/jpeg')
9
+ return '.jpg';
10
+ if (normalized === 'image/webp')
11
+ return '.webp';
12
+ if (normalized === 'application/json')
13
+ return '.json';
14
+ if (normalized === 'text/html')
15
+ return '.html';
16
+ if (normalized === 'image/svg+xml')
17
+ return '.svg';
18
+ if (normalized === 'application/pdf')
19
+ return '.pdf';
20
+ if (normalized === 'image/vnd.adobe.photoshop')
21
+ return '.psd';
22
+ if (normalized === 'application/vnd.openxmlformats-officedocument.presentationml.presentation')
23
+ return '.pptx';
24
+ if (normalized === 'application/zip')
25
+ return '.sketch';
26
+ return '.bin';
27
+ };
28
+ const safeArtifactName = (artifact) => {
29
+ const stem = artifact.id.replace(/[^A-Za-z0-9._-]+/g, '-').replace(/^-+|-+$/g, '') || 'artifact';
30
+ return `${stem}-${artifact.sha256.slice(0, 12).toLowerCase()}${extensionForMediaType(artifact.media_type)}`;
31
+ };
32
+ const assertDigest = (artifact, bytes) => {
33
+ const digest = createHash('sha256').update(bytes).digest('hex');
34
+ if (digest !== artifact.sha256.toLowerCase()) {
35
+ throw new Error(`Conversion artifact ${artifact.id} failed SHA-256 verification`);
36
+ }
37
+ };
38
+ export const materializeConversionArtifacts = async (client, operation, resultFile) => {
39
+ const artifacts = operation.result?.artifacts ?? [];
40
+ const directory = `${resultFile}.assets`;
41
+ await mkdir(directory, { recursive: true });
42
+ const materialized = await Promise.all(artifacts.map(async (artifact) => {
43
+ const downloaded = await client.downloadArtifact(artifact);
44
+ assertDigest(artifact, downloaded.bytes);
45
+ const localPath = path.join(directory, safeArtifactName(artifact));
46
+ await writeFile(localPath, downloaded.bytes);
47
+ return {
48
+ id: artifact.id,
49
+ role: artifact.role,
50
+ mediaType: downloaded.mediaType,
51
+ sha256: artifact.sha256,
52
+ sourceHref: artifact.href,
53
+ localPath,
54
+ };
55
+ }));
56
+ const manifestFile = path.join(directory, 'manifest.json');
57
+ const manifest = {
58
+ conversionId: operation.id,
59
+ operationExpiresAt: operation.expires_at,
60
+ manifestFile,
61
+ artifacts: materialized,
62
+ };
63
+ await writeFile(manifestFile, `${JSON.stringify(manifest, null, 2)}\n`, 'utf8');
64
+ return manifest;
65
+ };
66
+ //# sourceMappingURL=artifact-materializer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-materializer.js","sourceRoot":"","sources":["../src/artifact-materializer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export type CliFlags = Record<string, string | true>;
2
+ export declare const parseCliArguments: (argv: string[]) => {
3
+ command: string[];
4
+ flags: CliFlags;
5
+ };
6
+ export declare const stringFlag: (flags: CliFlags, name: string) => string | undefined;
7
+ export declare const booleanFlag: (flags: CliFlags, name: string) => boolean;
8
+ //# sourceMappingURL=cli-arguments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-arguments.d.ts","sourceRoot":"","sources":["../src/cli-arguments.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;AAWrD,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,EAAE,KACb;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAA;CAqBtC,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,OAAO,QAAQ,EAAE,MAAM,MAAM,KAAG,MAAM,GAAG,SAGnE,CAAC;AAEF,eAAO,MAAM,WAAW,GAAI,OAAO,QAAQ,EAAE,MAAM,MAAM,KAAG,OAA+B,CAAC"}
@@ -0,0 +1,39 @@
1
+ const booleanFlags = new Set([
2
+ 'detach',
3
+ 'force',
4
+ 'help',
5
+ 'json',
6
+ 'skip-auth',
7
+ 'version',
8
+ ]);
9
+ export const parseCliArguments = (argv) => {
10
+ const command = [];
11
+ const flags = {};
12
+ for (let index = 0; index < argv.length; index += 1) {
13
+ const value = argv[index];
14
+ if (!value?.startsWith('--')) {
15
+ if (value)
16
+ command.push(value);
17
+ continue;
18
+ }
19
+ const name = value.slice(2);
20
+ if (!name)
21
+ throw new Error('Invalid empty flag');
22
+ if (booleanFlags.has(name)) {
23
+ flags[name] = true;
24
+ continue;
25
+ }
26
+ const next = argv[index + 1];
27
+ if (!next || next.startsWith('--'))
28
+ throw new Error(`--${name} requires a value`);
29
+ flags[name] = next;
30
+ index += 1;
31
+ }
32
+ return { command, flags };
33
+ };
34
+ export const stringFlag = (flags, name) => {
35
+ const value = flags[name];
36
+ return typeof value === 'string' ? value : undefined;
37
+ };
38
+ export const booleanFlag = (flags, name) => flags[name] === true;
39
+ //# sourceMappingURL=cli-arguments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-arguments.js","sourceRoot":"","sources":["../src/cli-arguments.ts"],"names":[],"mappings":"AAEA,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC;IAC3B,QAAQ;IACR,OAAO;IACP,MAAM;IACN,MAAM;IACN,WAAW;IACX,SAAS;CACV,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,IAAc,EAC0B,EAAE;IAC1C,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,IAAI,KAAK;gBAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC/B,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACjD,IAAI,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;YACnB,SAAS;QACX,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QAC7B,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,KAAK,IAAI,mBAAmB,CAAC,CAAC;QAClF,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QACnB,KAAK,IAAI,CAAC,CAAC;IACb,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AAC5B,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,KAAe,EAAE,IAAY,EAAsB,EAAE;IAC9E,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,KAAe,EAAE,IAAY,EAAW,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { type CliFlags } from './cli-arguments.js';
2
+ export declare const runAuthCommand: (action: string | undefined, flags: CliFlags) => Promise<void>;
3
+ //# sourceMappingURL=cli-auth-command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-auth-command.d.ts","sourceRoot":"","sources":["../src/cli-auth-command.ts"],"names":[],"mappings":"AAMA,OAAO,EAA2B,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAgD5E,eAAO,MAAM,cAAc,GACzB,QAAQ,MAAM,GAAG,SAAS,EAC1B,OAAO,QAAQ,KACd,OAAO,CAAC,IAAI,CA+Dd,CAAC"}