claude-artifact-framework 0.14.0 → 0.14.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/README.md +32 -0
- package/llms.txt +90 -0
- package/package.json +9 -4
package/README.md
CHANGED
|
@@ -890,3 +890,35 @@ board.stop(); // stop polling, e.g. on teardown
|
|
|
890
890
|
Conflict handling is last-write-wins: if two viewers change the same key
|
|
891
891
|
within one poll window, whichever write reaches storage last overwrites the
|
|
892
892
|
other. There is no merge/CRDT logic.
|
|
893
|
+
|
|
894
|
+
## Hard rules — the short list
|
|
895
|
+
|
|
896
|
+
The rules that decide whether a generated app works, all in one place
|
|
897
|
+
(each is explained in its section above):
|
|
898
|
+
|
|
899
|
+
1. **Indented, never minified** — the only measured syntax errors came from
|
|
900
|
+
single-line output.
|
|
901
|
+
2. **Theme variables, never hardcoded hex** — `var(--caf-text)`,
|
|
902
|
+
`var(--caf-surface)`, `var(--caf-accent)`, `var(--caf-border)`,
|
|
903
|
+
`var(--caf-sunken)`, `var(--caf-muted)`, `var(--caf-danger)`, and
|
|
904
|
+
`ctx.colors(n)` for series. A custom block painted with `#fff` or
|
|
905
|
+
`#ef4444` breaks in dark mode.
|
|
906
|
+
3. **Never render a `<form>`** — the published sandbox lacks `allow-forms`;
|
|
907
|
+
use inputs plus a button with `onClick`.
|
|
908
|
+
4. **Never write big strings into `data`** (data URLs, file contents) —
|
|
909
|
+
the whole pool shares one ~5MB key; big things live in `React.useState`
|
|
910
|
+
or `ctx.files`.
|
|
911
|
+
5. **Phases belong to the `machine`** — never track game/process phases
|
|
912
|
+
with hand-rolled flags and `setTimeout`; `ctx.send` is the only door.
|
|
913
|
+
6. **Never skip a middle positional argument** — `run: (r, d, viewerId)`,
|
|
914
|
+
never `run: (r, viewerId)`.
|
|
915
|
+
7. **One `big: true` per screen** — it marks THE result, not every stat.
|
|
916
|
+
8. **The constructive action takes `kind: "primary"`**; a counter changed
|
|
917
|
+
by pressing is an `action`, not an editable `number` field.
|
|
918
|
+
9. **Parts of a record are `items`** — never JSON in a `textarea`.
|
|
919
|
+
10. **Don't hand-build empty/loading/error states** — the framework owns
|
|
920
|
+
them.
|
|
921
|
+
11. **CDN libs: call the method, not the global** (`marked.parse`, not
|
|
922
|
+
`marked(...)`); pin versions; when unsure of the file path use the bare
|
|
923
|
+
package URL.
|
|
924
|
+
12. **Framework ids are strings** — never `Number(record.id)`.
|
package/llms.txt
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# claude-artifact-framework
|
|
2
|
+
|
|
3
|
+
> Declarative framework for building apps inside Claude Artifacts. Declare what
|
|
4
|
+
> the app IS (fields, records, steps, chat with tools, workspace, documents);
|
|
5
|
+
> the framework owns persistence, hydration, validation, empty/loading/error
|
|
6
|
+
> states, light+dark theming, navigation, and the Claude tool loop.
|
|
7
|
+
> Full documentation: README.md (this file is the compact digest).
|
|
8
|
+
|
|
9
|
+
Load (classic script, global `ArtifactKit`; call `ArtifactKit.useReact(React)` once):
|
|
10
|
+
https://cdn.jsdelivr.net/npm/claude-artifact-framework/dist/index.global.js
|
|
11
|
+
|
|
12
|
+
## Registries (any other name throws, naming the valid set)
|
|
13
|
+
|
|
14
|
+
- Top-level keys: title, subtitle, theme:{seed}, layout, blocks, records,
|
|
15
|
+
steps, chat, main, sidebar, documents, data, shared, libs, machine
|
|
16
|
+
- Layouts: panel (default), records, steps, chat, workspace, documents
|
|
17
|
+
- Block types: fields, output, text, list, chart, timer, actions, chat, tabs,
|
|
18
|
+
records, custom — plus per-block title, when:(d)=>bool, state:"fase",
|
|
19
|
+
collapsible, wide, fill (custom only)
|
|
20
|
+
- Field types: text, textarea, number, money, percent, check, date, select,
|
|
21
|
+
file — attrs: key, label, value, required, min, max, step, placeholder,
|
|
22
|
+
hint, rows, options (array or (d)=>array), accept
|
|
23
|
+
- records spec: label, fields, title, subtitle, sort, summary, empty, search,
|
|
24
|
+
compute, items, actions (+ key when used as a block)
|
|
25
|
+
- documents: label, title, blocks OR types, empty; machine: key, initial,
|
|
26
|
+
states, events (event: from, do, then); chat: system, greeting, placeholder,
|
|
27
|
+
tools, model, maxTokens; steps step: title, text, fields, result
|
|
28
|
+
- Formats: money, percent (0-100), number, date. Output/chart/compute items:
|
|
29
|
+
{ label, value, format, big }
|
|
30
|
+
|
|
31
|
+
## Hard rules
|
|
32
|
+
|
|
33
|
+
1. Write the spec INDENTED, never minified (measured: minified output drops
|
|
34
|
+
closing braces).
|
|
35
|
+
2. Theme variables, never hardcoded hex: var(--caf-text), var(--caf-surface),
|
|
36
|
+
var(--caf-accent), var(--caf-border), var(--caf-sunken), var(--caf-muted),
|
|
37
|
+
var(--caf-danger); ctx.colors(n) for series. Hardcoded #fff breaks dark mode.
|
|
38
|
+
3. Never render a <form> (sandbox lacks allow-forms) — inputs + button onClick.
|
|
39
|
+
4. Never write big strings (data URLs, file contents) into data — one ~5MB
|
|
40
|
+
storage key holds the whole pool; big things live in React.useState or
|
|
41
|
+
ctx.files.
|
|
42
|
+
5. Phases (games, turns, processes) belong to `machine` — ctx.send(event,
|
|
43
|
+
payload) is the only door; events are no-ops outside their `from` states;
|
|
44
|
+
`after: {seconds, then, do}` timers are framework-owned.
|
|
45
|
+
6. Row actions receive (record, data, viewerId); block actions (data,
|
|
46
|
+
viewerId). Stop early if you like, but never skip a middle argument.
|
|
47
|
+
7. One big:true per screen; the constructive action takes kind:"primary"; a
|
|
48
|
+
counter changed by pressing is an action, not an editable number field.
|
|
49
|
+
8. Parts of a record are `items` — never JSON in a textarea.
|
|
50
|
+
9. Don't hand-build empty/loading/error states — the framework owns them.
|
|
51
|
+
10. CDN libs via libs:[urls]: call the method, not the global (marked.parse);
|
|
52
|
+
pin versions; unsure of the file path → bare package URL
|
|
53
|
+
(https://cdn.jsdelivr.net/npm/<pkg>@<version>).
|
|
54
|
+
11. Framework record ids are strings — never Number(record.id).
|
|
55
|
+
12. In custom blocks: return strings/React elements (never DOM elements — use
|
|
56
|
+
ref + React.useEffect for libs that write into an element); hooks are
|
|
57
|
+
allowed; persistent state via ctx.update, ephemeral via React.useState,
|
|
58
|
+
never createStore for UI state.
|
|
59
|
+
|
|
60
|
+
## Canonical example
|
|
61
|
+
|
|
62
|
+
ArtifactKit.createApp({
|
|
63
|
+
title: "Gastos",
|
|
64
|
+
theme: { seed: "#c2410c" },
|
|
65
|
+
layout: "records",
|
|
66
|
+
shared: false,
|
|
67
|
+
records: {
|
|
68
|
+
label: "gasto",
|
|
69
|
+
fields: [
|
|
70
|
+
{ key: "concepto", label: "Concepto", type: "text", required: true },
|
|
71
|
+
{ key: "monto", label: "Monto", type: "money", value: 0, min: 0 },
|
|
72
|
+
{ key: "categoria", label: "Categoría", type: "select", options: ["comida", "transporte", "otros"] },
|
|
73
|
+
],
|
|
74
|
+
subtitle: (r) => r.categoria,
|
|
75
|
+
summary: (all) => [
|
|
76
|
+
{ label: "Total", value: all.reduce((s, r) => s + (Number(r.monto) || 0), 0), format: "money", big: true },
|
|
77
|
+
],
|
|
78
|
+
actions: [{ label: "Duplicar", run: (r, d) => { d.records = [...d.records, { ...r, id: undefined }]; } }],
|
|
79
|
+
},
|
|
80
|
+
blocks: [
|
|
81
|
+
{ chart: (d) => ({ type: "donut", format: "money", items: porCategoria(d.records) }), title: "Por categoría" },
|
|
82
|
+
],
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
Chat with tools (workspace copilot): sidebar block
|
|
86
|
+
{ title: "Asistente", chat: { system: (d) => "...", tools: { nombre: {
|
|
87
|
+
description: "...", input: { campo: "string" }, run: (input, ctx) => {
|
|
88
|
+
ctx.update((d) => { /* mutate */ }); return { ok: true }; } } } } }
|
|
89
|
+
— the artifact runtime proxies api.anthropic.com with no API key; default
|
|
90
|
+
model claude-sonnet-4-6; conversation persists under data.chat.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-artifact-framework",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"description": "Utilities for building apps inside Claude Artifacts: platform storage, chat tool-calling loops, and other primitives verified against the real runtime.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.esm.js",
|
|
@@ -12,16 +12,21 @@
|
|
|
12
12
|
},
|
|
13
13
|
"files": [
|
|
14
14
|
"dist",
|
|
15
|
-
"src"
|
|
15
|
+
"src",
|
|
16
|
+
"llms.txt"
|
|
16
17
|
],
|
|
17
18
|
"scripts": {
|
|
18
19
|
"build": "node scripts/build.mjs",
|
|
19
20
|
"build:watch": "node scripts/build.mjs --watch",
|
|
21
|
+
"test": "npm run build && node test/e2e.mjs",
|
|
20
22
|
"prepublishOnly": "npm run build",
|
|
21
|
-
"release": "node scripts/check-docs.mjs && bash scripts/publish.sh"
|
|
23
|
+
"release": "node scripts/check-docs.mjs && npm test && bash scripts/publish.sh"
|
|
22
24
|
},
|
|
23
25
|
"devDependencies": {
|
|
24
|
-
"esbuild": "^0.25.0"
|
|
26
|
+
"esbuild": "^0.25.0",
|
|
27
|
+
"playwright-core": "^1.45.0",
|
|
28
|
+
"react": "^18.3.0",
|
|
29
|
+
"react-dom": "^18.3.0"
|
|
25
30
|
},
|
|
26
31
|
"license": "MIT",
|
|
27
32
|
"author": "Alejandro Cuartas",
|