stillmade-sdk 0.1.46 → 0.1.48
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/.stillmade/sdk-baseline.json +1 -1
- package/AGENTS.md +6 -2
- package/FRAME_VIEWS.md +71 -5
- package/INTERFACE_DESIGN.md +105 -15
- package/MODULES.md +26 -3
- package/PASTE_TO_LLM.md +27 -10
- package/README.md +15 -0
- package/SDK.md +393 -64
- package/UI_AESTHETIC.md +13 -0
- package/blocks/native/sm.board-editor/versions/3.0.0/package.js +921 -0
- package/blocks/native/sm.editor/versions/3.0.0/package.js +751 -0
- package/blocks/native/sm.panel-strip/versions/3.0.0/package.js +350 -0
- package/blocks/native/sm.photo-editor/versions/1.0.0/package.js +6693 -0
- package/blocks/native/sm.voiceover/versions/3.0.0/package.js +513 -0
- package/docs/build/block-builder-contract.md +2 -2
- package/docs/build/custom-interface.md +23 -3
- package/docs/build/frame-views.md +71 -5
- package/docs/build/hosted-text.md +8 -3
- package/docs/build/interface-design.md +105 -15
- package/docs/build/media-analysis.md +18 -1
- package/docs/build/modules.md +26 -3
- package/docs/build/with-your-ai.md +14 -0
- package/docs/build/workspaces.md +42 -0
- package/docs/reference/authoring-guide.md +5 -4
- package/docs/reference/cli.md +8 -3
- package/docs/reference/execution.md +13 -5
- package/docs/reference/first-party-blocks.md +5 -4
- package/docs/reference/generation-models.md +4 -0
- package/docs/reference/limits.md +9 -2
- package/docs/reference/permissions.md +4 -0
- package/docs/reference/view-bridge.md +6 -3
- package/docs/reference/view-rules.md +2 -1
- package/docs/tools/llm.md +27 -10
- package/examples/custom-interface.stillmade.json +2 -2
- package/package.json +1 -1
- package/packages/block-cli/cli.js +124 -12
- package/packages/block-cli/dev-host/assets/host.js +63 -37
- package/packages/block-cli/dev-host/assets/index.css +1 -1
- package/packages/block-cli/dev-server.js +74 -23
- package/packages/block-cli/format.js +20 -1
- package/packages/block-cli/ready-gate.js +34 -2
- package/packages/block-cli/templates.js +61 -0
- package/packages/block-cli/type-packages.js +7 -4
- package/packages/block-cli/workspace-dev.js +124 -0
- package/packages/block-cli/workspace-pack.js +62 -0
- package/packages/block-cli/workspace.js +304 -0
- package/packages/block-platform/block-readiness.js +5 -4
- package/packages/block-platform/catalog.js +5 -3
- package/packages/block-platform/node-defaults.js +2 -2
- package/packages/block-platform/plain-descriptions.js +1 -0
- package/packages/block-platform/type-workspace.js +8 -0
- package/packages/block-sdk/admission.js +2 -2
- package/packages/block-sdk/builder-contract.js +3 -3
- package/packages/block-sdk/capabilities.js +32 -12
- package/packages/block-sdk/contracts.js +11 -2
- package/packages/block-sdk/examples.js +2 -2
- package/packages/block-sdk/first-party-identities.js +9 -0
- package/packages/block-sdk/first-party-packages.js +9 -1
- package/packages/block-sdk/folder-package.js +34 -2
- package/packages/block-sdk/generation-catalog.js +7 -0
- package/packages/block-sdk/index.d.ts +13 -5
- package/packages/block-sdk/index.js +1 -1
- package/packages/block-sdk/mock-host.js +7 -0
- package/packages/block-sdk/module-hosted.js +11 -1
- package/packages/block-sdk/module-media-access.js +5 -3
- package/packages/block-sdk/permission-summary.js +1 -1
- package/packages/block-sdk/portable-media-actions.d.ts +4 -1
- package/packages/block-sdk/portable-media-actions.js +16 -1
- package/packages/block-sdk/remix-policy.js +2 -2
- package/packages/block-sdk/staged-releases.js +5 -0
- package/packages/block-sdk/stillmade-pack.js +64 -0
- package/packages/block-sdk/testing.js +2 -2
- package/packages/block-sdk/view-bridge.js +6 -3
- package/packages/block-sdk/view-design.js +65 -17
- package/packages/block-sdk/view-renderer.js +17 -1
- package/packages/block-sdk/view.js +47 -9
- package/packages/design-system/block-kit.css +23 -0
- package/packages/design-system/theme.css +10 -7
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"examples/clean-text.stillmade.json": "973a688879d51f7cf6c86c3a0698b68489e20946a7d28d234944f22548d24ed3",
|
|
10
10
|
"examples/comfy-invert.stillmade.json": "126bd3a8a88e14c08ae11c62a441ed099d83e16830e2062f936e14e56cb297eb",
|
|
11
11
|
"examples/comfy-text-to-image.stillmade.json": "957a616887115984c1888cf9c0eee2fe771dcbf041166ad112fb6c3feb7ad4dd",
|
|
12
|
-
"examples/custom-interface.stillmade.json": "
|
|
12
|
+
"examples/custom-interface.stillmade.json": "13c9df1bf0556e6880ed21dc8ea75a19f1c6183104778c6f7a98fa6af23321af",
|
|
13
13
|
"examples/describe-image.stillmade.json": "de5634639c7e0364d5ae9e6ac7a2bd4004eb3289c1767b3e7527166f2015f7e9",
|
|
14
14
|
"examples/docs-only-campfire-narrator.stillmade.json": "87c6a3b643b1ee007487e162aeced6f6302648f4c4a58b015e7df2ab9f2959be",
|
|
15
15
|
"examples/docs-only-custom-ui.stillmade.json": "4602fd6b9576d364e16b79d2f08b196a251a8e98cf3149576686a96680a5dfe6",
|
package/AGENTS.md
CHANGED
|
@@ -6,7 +6,7 @@ This folder is the StillMade Block SDK. Read this file before writing code; it i
|
|
|
6
6
|
|
|
7
7
|
Do not tell the user a Block is ready, done or working until `node packages/block-cli/cli.js gate .` (`gate <block-folder>` for a Block outside this SDK folder) passes after your last edit, and report the exact status it prints. In this folder Claude Code (`.claude/settings.json`) and Cursor (`.cursor/hooks.json`) run the gate when you finish a turn and send any failures back to you, but only in a session started in this folder: if you downloaded the SDK during the current session, run the gate yourself. Other agents must also run it themselves. A module Block runs code, so the gate a hook starts does not run it and says so: run `gate` or `ready` on it yourself. If you cannot fix a failure, say plainly that the Block is not ready and list the failing checks.
|
|
8
8
|
|
|
9
|
-
Contract `stillmade.block-builder@1.
|
|
9
|
+
Contract `stillmade.block-builder@1.18.0`. Humans, coding agents, imported source, GitHub repositories and generated code all adapt to the Block platform; anything that becomes a StillMade Block obeys this contract.
|
|
10
10
|
|
|
11
11
|
## Source of truth
|
|
12
12
|
|
|
@@ -75,7 +75,7 @@ These are StillMade's defaults: unless the person or the creator asked for somet
|
|
|
75
75
|
|
|
76
76
|
## Interface
|
|
77
77
|
|
|
78
|
-
If the capability needs UI, use the Block UI SDK: generated `manifest.ui` controls first; a sandboxed custom view (`view.html`/`view.css`/`view.js`) only when the core interaction needs one. Build custom views from the Block kit the host injects (`block-kit.css`): the result in `sm-stage`, drawn before the first run in the shape and size of what is coming (`data-ratio="9:16"` for a vertical clip, lines for text, a player bar for sound) so every part of the screen is in place at once and the result fills a place the person already sees instead of popping in somewhere unexpected; StillMade draws it the same way on the Steps it draws; on a wide screen what goes in sits on the left and the result on the right, side by side, and they stack only on narrow screens and phones, the result's place
|
|
78
|
+
If the capability needs UI, use the Block UI SDK: generated `manifest.ui` controls first; a sandboxed custom view (`view.html`/`view.css`/`view.js`) only when the core interaction needs one. Build custom views from the Block kit the host injects (`block-kit.css`): the result in `sm-stage`, drawn before the first run in the shape and size of what is coming (`data-ratio="9:16"` for a vertical clip, lines for text, a player bar for sound) so every part of the screen is in place at once and the result fills a place the person already sees instead of popping in somewhere unexpected; StillMade draws it the same way on the Steps it draws; on a wide screen what goes in sits on the left and the result on the right, side by side, and they stack only on narrow screens and phones, the result's place after the inputs with the job's action row on it (`sm-actions` and `sm-status` inside `sm-stage`: the kit puts the status top-left and the actions top-right in the player's cream blocks, over a band above the media; the run button is always the rightmost, so a button that spends credits never moves and making again is pressed where it made the first time, with Download and other result actions to its left), picks as pictures in `sm-choices`, the picked one in the kit's ink fill (never restyled to an outline, a tint or the page's background) so it reads at a glance, one solid `sm-primary` naming the action in the job's words ("Plan the tour", "Generate voiceover"; never "Run" or "Make it") and no price (StillMade's run button adds it), extras in a closed `sm-more`; a look the person names wins. Fit one laptop screen without scrolling: label beside control, status in a few words, files as tiles, rare tools as icons, (i) on unclear controls. These compact rules are for a job or an ingredient. Size the view to the Block's tier (block-tier.js): an app, a workspace a person works in for a while (video editor, 3D configurator, CAD or drawing tool, photo editor), declares `manifest.kind: "workspace"` and looks and works like that kind of app instead of a compact page, and StillMade's checks (admission, readiness, its own builder) then apply the app rules instead of the compact ones: no limit on controls in view, no Block kit page, its own layout, the craft's own words, and only its run button (`data-stillmade-action="run"`) held to naming what it makes: its canvas or stage fills the view, with the panels, toolbars, inspector or timeline such an app has, direct manipulation (select, drag, zoom), keyboard shortcuts and undo; it keeps the host appearance and Block kit controls, its panels may scroll, and on a phone its tools fold into sheets while the canvas stays usable. Never shrink an app into a form of fields and one button. StillMade centers a standard view narrower than its Step and zooms a view to fill its space; a stage shows what it holds in its middle as one group (a caption stays with its picture) and several results fill its width as one row, on a Block's screen and on the pages StillMade draws; an app that lays itself out (full-size canvas or WebGL, its own scroll, pan or zoom, its own Ctrl/Cmd +/- keys) puts `data-stillmade-layout="own"` on its outermost element, and StillMade then never centers, zooms or takes those keys. StillMade draws one player for every `<video controls>` (play, timeline, time, sound and full screen, shown for 3 s the first time it comes into view, then while the pointer is on the video, with keys and touch) and a full-screen button on result pictures in `sm-stage` or `sm-gallery` and on any element marked `data-stillmade-expand` (the same value makes one set of pictures, `off` removes it); `data-stillmade-player="native"` keeps the browser's controls, and a `<video>` without `controls` is the Block's own and is never touched. A picture or clip that cannot show here (kept on another device, or it did not open) keeps its place as a quiet `sm-media-off` tile in its own shape with the `image-off` glyph and the reason in its label, never words in its place. Drop words nobody needs; put helpful ones in a closed `sm-hint`. Mark each button `data-stillmade-action` (`run` on the one that runs the Block, which the device checks press once; a page that checks first keeps `run` on that button for both presses; what it does on the others, `"play sample"`) and label each field: Chat presses and fills them. Expose the capability, not the implementation: sensible defaults, previews, progress, clear errors, visible outputs. Show no raw JSON, internal IDs, filesystem details, provider terms or developer settings unless the Block is a developer tool. When a person chooses among options they need to hear or see (voices, music, fonts, looks, templates, images), let them preview each option before choosing: a sample or thumbnail from the Block's own files or the host's free samples, never a paid generation. Skip previews only when there is nothing to preview. Choices StillMade owns (voices, models in the run review) already show samples. Follow the host appearance (Light, Dark and White) and one elastic layout: stacked on a 320px phone with no sideways scroll (the inputs, the button in normal flow, never pinned, then the result's place under it), and from 860px the controls left (≤380px), the result filling the right. Short settings sit side by side, each label beside its control (`sm-field`, `sm-settings`; three or four short options as one `data-segmented` row); many items are one line each (`sm-list`) that open in place; input files are small tiles (`sm-gallery data-size="small"`); on a phone chip rows scroll sideways and long lists show three. Compacting moves controls, never deletes them.
|
|
79
79
|
|
|
80
80
|
## Shared editing
|
|
81
81
|
|
|
@@ -155,6 +155,10 @@ A Block is done only when every applicable item holds. Passing a compile, one un
|
|
|
155
155
|
- E: Runtime or language incompatibility
|
|
156
156
|
- F: Fundamentally incompatible capability
|
|
157
157
|
|
|
158
|
+
## Several Blocks for one person
|
|
159
|
+
|
|
160
|
+
More than one Block, a Block that uses a signed-in app, an automation, or a workflow that joins Blocks: build them in one workspace (`npx stillmade-block init <folder>`, then `add` for each Block), as `docs/build/workspaces.md` says. The workspace's own AGENTS.md says where each new Block goes; `gate` and `pack` in its folder cover every Block and workflow.
|
|
161
|
+
|
|
158
162
|
## Guides in this folder
|
|
159
163
|
|
|
160
164
|
Every guide on the StillMade site is in `docs/` here as Markdown, so you can read them offline: a link to `/docs/<path>` (in `SDK.md`, `PASTE_TO_LLM.md` or anywhere else) is the file `docs/<path>.md`, and `/docs` itself is `docs/index.md`. Start with `docs/build/quickstart.md` for a Block and `docs/project-types/build.md` for a Project Type, which also says how a Type embeds module Blocks. `docs/reference/cli.md` lists every command, `docs/reference/generation-models.md` the hosted models and `docs/reference/limits.md` the limits.
|
package/FRAME_VIEWS.md
CHANGED
|
@@ -28,7 +28,8 @@ esbuild src/view.jsx --bundle --format=iife --minify --jsx=automatic \
|
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
Limits: markup and each stylesheet up to 256 KiB, `view.js` up to 4 MiB,
|
|
31
|
-
|
|
31
|
+
up to 32 asset files with 8 MiB in total, and up to 64 code files (below) of
|
|
32
|
+
up to 4 MiB each and 16 MiB in total.
|
|
32
33
|
|
|
33
34
|
## The `StillMade` object
|
|
34
35
|
|
|
@@ -41,6 +42,57 @@ and the rest of the interface bridge. In addition:
|
|
|
41
42
|
| --- | --- |
|
|
42
43
|
| `StillMade.asset(path)` | A `blob:` URL for one of the view's asset files, for `<img>`, `new FontFace()` or `<video>`. |
|
|
43
44
|
| `StillMade.assetBytes(path)` | A copy of an asset file's bytes as an `ArrayBuffer`. |
|
|
45
|
+
| `StillMade.loadCode(path)` | Runs one of the view's code files once and resolves when it has run (see Code files). |
|
|
46
|
+
|
|
47
|
+
## A full-screen app
|
|
48
|
+
|
|
49
|
+
A frame view grows with its content: StillMade sizes the frame to the page.
|
|
50
|
+
An app that lays itself out in a fixed area (an editor with a timeline at the
|
|
51
|
+
bottom) marks its root `data-stillmade-layout="own"` and sizes it to the space
|
|
52
|
+
StillMade gives the Step, which the frame receives as the CSS variable
|
|
53
|
+
`--stillmade-space-height`:
|
|
54
|
+
|
|
55
|
+
```css
|
|
56
|
+
#root { height: max(560px, var(--stillmade-space-height, 100vh)); }
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Code files: load the rest of a large interface when it is needed
|
|
60
|
+
|
|
61
|
+
An interface too large for one `view.js` (a full editor with its export and
|
|
62
|
+
effects code) starts with a small `view.js` and keeps the rest as code files:
|
|
63
|
+
`.js` files in `src/view-files/`, for example `src/view-files/code/editor.js`.
|
|
64
|
+
`await StillMade.loadCode('code/editor.js')` runs one when the view needs it.
|
|
65
|
+
The frame still has no network and runs no generated code: StillMade reads
|
|
66
|
+
the file, checks it against the SHA-256 the package names, checks that it is
|
|
67
|
+
one classic script without `import()`, compiles the task guard into it, and
|
|
68
|
+
runs it in the frame. A file runs once; asking again resolves at once. A file
|
|
69
|
+
that is not one of the view's code files, does not match its digest or stops
|
|
70
|
+
with an error rejects the call with the reason.
|
|
71
|
+
|
|
72
|
+
Each code file is a classic script that registers what it defines, for
|
|
73
|
+
example on a global your `view.js` set up:
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
// src/view.js
|
|
77
|
+
globalThis.parts = {};
|
|
78
|
+
StillMade.loadCode('code/chart.js').then(() => parts.drawChart(document.getElementById('root')));
|
|
79
|
+
|
|
80
|
+
// src/view-files/code/chart.js
|
|
81
|
+
parts.drawChart = root => { root.textContent = 'Chart'; };
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
A bundler can write them: split at the `import()` boundaries of your
|
|
85
|
+
interface and wrap each chunk so it registers itself (StillMade's own Editor
|
|
86
|
+
is built this way, `scripts/frame-blocks/bundle.mjs` in the StillMade
|
|
87
|
+
repository). Code files are not asset files: `StillMade.asset` does not open
|
|
88
|
+
them and they do not count toward the asset limits. `validate`, `test` and
|
|
89
|
+
`pack` check each one as StillMade does.
|
|
90
|
+
|
|
91
|
+
An original screen ported into a frame view can use the SDK's helpers in
|
|
92
|
+
`packages/block-sdk/frame-hosts/`: `media-urls.js` loads the saved media its
|
|
93
|
+
markup names through `previewMedia`, and `dialogs.jsx` draws the screen's alerts and
|
|
94
|
+
confirms; a confirm that names a total in credits ("Build 30 panels (~60 credits)?")
|
|
95
|
+
becomes one `StillMade.allowSpending`, so StillMade's own dialog asks.
|
|
44
96
|
|
|
45
97
|
`StillMade.live` gives any view the camera and microphone as they happen, after the
|
|
46
98
|
person presses Start (see Live camera and microphone in
|
|
@@ -92,6 +144,18 @@ values. StillMade hides `[data-stillmade-add]` tiles from viewers and for
|
|
|
92
144
|
inputs an earlier Step fills. In the SDK preview, the tile opens your
|
|
93
145
|
computer's file chooser and the preview keeps the files like your own picks.
|
|
94
146
|
|
|
147
|
+
### File inputs your view does not add itself
|
|
148
|
+
|
|
149
|
+
StillMade draws nothing beside or over a Block's own screen for its file inputs.
|
|
150
|
+
A file input the view does not fill with a `data-stillmade-add` tile or
|
|
151
|
+
`StillMade.addFiles` opens from the inputs icon on the Step's pill. That icon
|
|
152
|
+
shows only when an earlier Step makes something the Block takes: there the
|
|
153
|
+
person picks which earlier item, or items, this Block works on (for example one
|
|
154
|
+
photo of several for a one-photo editor, or several to edit and hand all on),
|
|
155
|
+
and adds their own file to an optional input. A required file still missing is
|
|
156
|
+
asked for in one row beside the screen until it is there. To let people add
|
|
157
|
+
files on the screen itself, use the add tile or `addFiles` above.
|
|
158
|
+
|
|
95
159
|
### Removing and reordering files
|
|
96
160
|
|
|
97
161
|
A list input's files are removed and put in order on the same screen, so a
|
|
@@ -174,15 +238,17 @@ or zoom, its own Ctrl/Cmd +/- keys, as in a CAD or drawing tool) puts
|
|
|
174
238
|
<div id="root" data-stillmade-layout="own"></div>
|
|
175
239
|
```
|
|
176
240
|
|
|
177
|
-
StillMade then never centers or zooms it
|
|
178
|
-
|
|
241
|
+
StillMade then never centers or zooms it, gives its page no padding, makes the
|
|
242
|
+
frame as tall as the space its Step has (so a root at `height: 100vh` fills the
|
|
243
|
+
Step, and follows the window) and leaves Ctrl/Cmd +, - and 0 to the app. Without the attribute StillMade also stays out of the way when the view
|
|
179
244
|
looks like an app: no page padding, a clipped page, a root as tall as the frame,
|
|
180
245
|
fixed over half of it or scrolling over half of it, a canvas, SVG or
|
|
181
246
|
`touch-action: none` surface over 40% of it, or a canvas or SVG of 300x200 or
|
|
182
247
|
more with `touch-action: none` (as Three.js's controls set it). Mark the root
|
|
183
248
|
anyway, in `view.html` rather than from code: StillMade reads it before the view
|
|
184
|
-
starts, so the app never
|
|
185
|
-
|
|
249
|
+
starts, so the app never loses a key to it, even while it is still loading.
|
|
250
|
+
StillMade draws no size control over any view; it sizes the view to fit, and
|
|
251
|
+
Ctrl/Cmd +, - and 0 change that size for the visit unless the view keeps them.
|
|
186
252
|
|
|
187
253
|
A `<video controls>` plays in StillMade's player, the same one as everywhere in
|
|
188
254
|
StillMade: play, timeline, time, sound and full screen along the bottom, shown
|
package/INTERFACE_DESIGN.md
CHANGED
|
@@ -9,6 +9,27 @@ Most Blocks need no custom view: generated `manifest.ui` controls already
|
|
|
9
9
|
follow these rules. Write a custom view only when the core interaction needs
|
|
10
10
|
one, and start it from the Block kit.
|
|
11
11
|
|
|
12
|
+
## Two modes: job and app
|
|
13
|
+
|
|
14
|
+
A Block's interface is one of two kinds, and its manifest says which.
|
|
15
|
+
|
|
16
|
+
- **Job** (the default, `"kind": "task"`): one thing a person makes in a few
|
|
17
|
+
steps, often in words that belong to their trade: a listing tour, a sermon
|
|
18
|
+
clip, a weekly caption. Everything in this guide applies: the result biggest,
|
|
19
|
+
one action, a compact page from the Block kit, the job's own words.
|
|
20
|
+
- **App** (`"kind": "workspace"`): software a person works in for a while: a
|
|
21
|
+
CAD or 3D tool, a photo editor, a timeline, a canvas, a studio. It keeps the
|
|
22
|
+
rules every Block shares (the job's words, pictures over words, files through
|
|
23
|
+
StillMade, dates picked, no notes on how it works), and the
|
|
24
|
+
[app rules](#4a-app-rules) replace the job-only ones: one action, one compact
|
|
25
|
+
screen, the Block kit page, settings folded away, the result filling the
|
|
26
|
+
right. StillMade's checks hold it to the app rules, never to the compact ones.
|
|
27
|
+
|
|
28
|
+
Both modes keep what the SDK is for: inputs and outputs, multiplayer, hosted
|
|
29
|
+
operations and credits, StillMade's file picker, no prices on screen, a run
|
|
30
|
+
button that names what it makes. The mode changes how the screen is laid out
|
|
31
|
+
and worded; it grants no extra runtime or host access.
|
|
32
|
+
|
|
12
33
|
## 1. Start from the Block kit
|
|
13
34
|
|
|
14
35
|
StillMade adds the Block kit stylesheet (`packages/design-system/block-kit.css`)
|
|
@@ -38,12 +59,11 @@ piece in Light, Dark and White.
|
|
|
38
59
|
<div class="sm-fields"><!-- secondary settings --></div>
|
|
39
60
|
</details>
|
|
40
61
|
|
|
41
|
-
<div class="sm-actions">
|
|
42
|
-
<button type="button" class="sm-primary" id="run" data-stillmade-action="run">Make the clip</button>
|
|
43
|
-
<p class="sm-status" id="status" role="status"></p>
|
|
44
|
-
</div>
|
|
45
|
-
|
|
46
62
|
<section class="sm-stage" id="stage" data-ratio="16:9" aria-live="polite">
|
|
63
|
+
<p class="sm-status" id="status" role="status"></p>
|
|
64
|
+
<div class="sm-actions">
|
|
65
|
+
<button type="button" class="sm-primary" id="run" data-stillmade-action="run">Make the clip</button>
|
|
66
|
+
</div>
|
|
47
67
|
<div class="sm-empty" id="empty">
|
|
48
68
|
<span class="sm-glyph" data-glyph="video" aria-hidden="true"></span>
|
|
49
69
|
<p>Your clip</p>
|
|
@@ -55,20 +75,24 @@ piece in Light, Dark and White.
|
|
|
55
75
|
With an `sm-stage` as its direct child and no `data-layout`, `sm-block` puts
|
|
56
76
|
the inputs on the left and the stage on the right from 860 px wide. Under that
|
|
57
77
|
everything stacks in the page's order, so the stage comes last in the markup:
|
|
58
|
-
the inputs,
|
|
78
|
+
the inputs, then the result's place. The job's status and actions go inside
|
|
79
|
+
the stage: the kit puts `sm-status` top-left and `sm-actions` top-right, in
|
|
80
|
+
the cream blocks of StillMade's player, over a band kept above the media. The
|
|
81
|
+
run button is always the rightmost, so making again is pressed in the same
|
|
82
|
+
place (rule 24).
|
|
59
83
|
|
|
60
84
|
| Class | Use it for |
|
|
61
85
|
| --- | --- |
|
|
62
86
|
| `sm-block` | The one workspace. With an `sm-stage` child, the controls sit left and the stage right from 860 px; narrower, they stack in the page's order. `data-layout="stack"` keeps one column; `"split"` is an older layout with the stage on the left. |
|
|
63
|
-
| `sm-stage` | The thing being made: preview, media or result. `data-ratio="16:9"`, `"9:16"` or `"1:1"`. |
|
|
87
|
+
| `sm-stage` | The thing being made: preview, media or result. `data-ratio="16:9"`, `"9:16"` or `"1:1"`. A job's `sm-actions` and `sm-status` go inside it, over its top corners. |
|
|
64
88
|
| `sm-empty` | An empty stage: a glyph, at most five words, one action. |
|
|
65
89
|
| `sm-choices` | Picks shown as pictures (`img`, `.sm-swatch`, `.sm-glyph`) and one or two words. `data-compact` for short text chips, `data-segmented` for one connected row of three or four short options. The pick is filled with the kit's ink, so it reads at a glance; a `disabled` fieldset keeps its pick and fades the rest. Chips and segments scroll sideways on a phone. Give the `fieldset` an `id` and `data-stillmade-share` so teammates see the same pick. |
|
|
66
90
|
| `sm-field`, `sm-fields` | One short setting on one row, its label beside the control; a responsive group of them. On a phone the control wraps under its label only when both do not fit. A textarea, picture choices, file tiles or a list keep the label above. |
|
|
67
91
|
| `sm-settings` | Short settings side by side, each label beside its control; a narrow cell wraps the control under its label. |
|
|
68
92
|
| `sm-list` | Many items, one line each: a thumbnail, one line of text, a short fact. An item that opens in place is an `li` holding a `details`. `data-peek` shows three on a phone, with a last `li.sm-list-more` button that sets `data-open`. |
|
|
69
93
|
| `sm-clamp` | Long text that shows five lines on a phone until it gets `data-open`. |
|
|
70
|
-
| `sm-actions` | One `sm-primary`, then `sm-quiet` buttons and `sm-icon` buttons (each with `aria-label` and `title`). |
|
|
71
|
-
| `sm-status` | Live state
|
|
94
|
+
| `sm-actions` | One `sm-primary`, then `sm-quiet` buttons and `sm-icon` buttons (each with `aria-label` and `title`). Inside `sm-stage` it sits top-right and the run button (`data-stillmade-action="run"`) is always its rightmost. |
|
|
95
|
+
| `sm-status` | Live state in a few words: `data-state="loading"`, `"success"`, `"waiting"` or `"error"`. Inside `sm-stage` it sits top-left, opposite the actions. |
|
|
72
96
|
| `sm-more` | A closed `<details>` for secondary settings. |
|
|
73
97
|
| `sm-hint` | A closed `<details>` (i) for an explanation that might help. Its words show on hover or focus, or a tap on touch screens. |
|
|
74
98
|
| `sm-gallery` | A grid of results or media. `data-size="small"` for input files: more tiles per row as the screen widens. |
|
|
@@ -225,10 +249,10 @@ exception, never unrelated technical UI.
|
|
|
225
249
|
16. Use the width. From 860 px wide, the kit puts the controls on the left
|
|
226
250
|
at a reading width (300–380 px) and the result (`sm-stage`, a direct
|
|
227
251
|
child of `sm-block`) fills the right, in its real shape. Under that the
|
|
228
|
-
page is one column in the page's order: the inputs, the
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
inputs
|
|
252
|
+
page is one column in the page's order: the inputs, then the result's
|
|
253
|
+
place with the job's action row on it (rule 24; rule 5: never a sticky
|
|
254
|
+
bar), so `sm-stage` comes after the inputs in the markup. Keep the
|
|
255
|
+
inputs short enough that a phone reaches the stage and its button
|
|
232
256
|
without scrolling far; fold the rest into `sm-more`. Extra width goes to the result, never to wider text
|
|
233
257
|
fields. Before there is a result, the stage previews what will be made
|
|
234
258
|
from the inputs given so far, not an empty box. `data-layout="stack"`
|
|
@@ -283,9 +307,70 @@ exception, never unrelated technical UI.
|
|
|
283
307
|
a second Block or Step. A workspace the person works in for a while (a
|
|
284
308
|
CAD tool, a canvas, an editor) is its own Block, and turning what it made
|
|
285
309
|
into something else is the next one.
|
|
310
|
+
24. Actions on the stage (owner, November 5, 2026). A job's `sm-actions` and
|
|
311
|
+
`sm-status` go inside its `sm-stage`. The kit lays them over the stage,
|
|
312
|
+
the status top-left and the actions top-right, in the cream blocks of
|
|
313
|
+
StillMade's player, and keeps a band above the media so they never cover
|
|
314
|
+
it; the media fills the rest of the stage. On a narrow stage the actions
|
|
315
|
+
take a second row under the status. A button that spends credits never
|
|
316
|
+
moves: the run button (`data-stillmade-action="run"`) is always the
|
|
317
|
+
rightmost, and it stays in that spot when it makes again ("Make video",
|
|
318
|
+
then "Make video again"); what the result adds (Download, Share) goes to
|
|
319
|
+
its left. Controls on media (StillMade's player, the full-screen square)
|
|
320
|
+
show for 3 seconds the first time the media comes into view, then only
|
|
321
|
+
while it is hovered or tapped. StillMade's own Step pages do the same. An
|
|
322
|
+
app that lays itself out keeps its own toolbar.
|
|
323
|
+
|
|
324
|
+
```html
|
|
325
|
+
<section class="sm-stage" data-ratio="9:16">
|
|
326
|
+
<p class="sm-status" role="status">Saved</p>
|
|
327
|
+
<div class="sm-actions">
|
|
328
|
+
<button type="button" class="sm-quiet" data-stillmade-action="download">Download</button>
|
|
329
|
+
<button type="button" class="sm-primary" data-stillmade-action="run">Make video again</button>
|
|
330
|
+
</div>
|
|
331
|
+
<video controls src="blob:..."></video>
|
|
332
|
+
</section>
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## 4a. App rules
|
|
336
|
+
|
|
337
|
+
An app (`"kind": "workspace"`) follows these instead of the job-only rules
|
|
338
|
+
(`APP_INTERFACE_PRINCIPLES`):
|
|
339
|
+
|
|
340
|
+
1. Its work surface (viewport, canvas, image, timeline) owns the page, laid
|
|
341
|
+
out like the best apps of its kind: tool rail, panels, inspector, layers,
|
|
342
|
+
timeline and menus, with as many controls as the craft needs. Never a form
|
|
343
|
+
of fields and one button.
|
|
344
|
+
2. It lays itself out: `data-stillmade-layout="own"` on its outermost element,
|
|
345
|
+
so StillMade never centers or zooms it and leaves Ctrl/Cmd +/- to it.
|
|
346
|
+
Full-size panels, fixed toolbars and its own scroll, pan and zoom are fine.
|
|
347
|
+
3. Work happens on the surface: select, drag, zoom and pan, keyboard shortcuts
|
|
348
|
+
for the common tools, undo and redo.
|
|
349
|
+
4. Speak the craft: Exposure, Keyframe, Extrude, Layers, Mask, as people of that
|
|
350
|
+
craft say them. A button that spends credits still names what it makes
|
|
351
|
+
("Generate fill"), carries `data-stillmade-action="run"` and shows no price.
|
|
352
|
+
5. Order, not sparseness: tools grouped in panels that fold, the most used in
|
|
353
|
+
view, rare ones in menus. No intros or paragraphs on the surface.
|
|
354
|
+
6. StillMade's appearance (Light, Dark and White) and the kit's controls
|
|
355
|
+
wherever they fit; the layout is the app's own. A look the person names wins.
|
|
356
|
+
7. On a phone the work surface stays usable and the panels fold into sheets or
|
|
357
|
+
one tool strip.
|
|
358
|
+
8. What the person makes leaves the app as the Block's outputs (and, while they
|
|
359
|
+
work, its shared state), so the next Step and the other people in the
|
|
360
|
+
project get it.
|
|
286
361
|
|
|
287
362
|
## 5. What StillMade checks
|
|
288
363
|
|
|
364
|
+
For an app (`"kind": "workspace"`) only the shared checks run: a file input of
|
|
365
|
+
its own, the price and page-heading rules, the wording notes that are not about
|
|
366
|
+
layout (a vague progress line, how the Block works, a typed date, where a file
|
|
367
|
+
is kept), and the action-name rules on its run button
|
|
368
|
+
(`data-stillmade-action="run"`) alone, so "OK" and "Go" are fine on its dialogs
|
|
369
|
+
and tools. It is never asked for the Block kit page, a control or row count,
|
|
370
|
+
labels beside fields, `data-stillmade-action` on every tool, or a visual
|
|
371
|
+
surface instead of text (a code editor is an app). Everything below is the job
|
|
372
|
+
check list.
|
|
373
|
+
|
|
289
374
|
- Admission rejects a primary textarea of 12 or more rows when no task
|
|
290
375
|
presentation (stage, media, list or `StillMade.render`) is detected
|
|
291
376
|
(`INTERFACE_DESIGN_RULES`).
|
|
@@ -329,8 +414,13 @@ exception, never unrelated technical UI.
|
|
|
329
414
|
- HTML, JavaScript, permission and appearance validation are separate checks.
|
|
330
415
|
Simplicity never bypasses safety or approval.
|
|
331
416
|
|
|
332
|
-
The SDK exports the ordered principles as `BLOCK_INTERFACE_PRINCIPLES`
|
|
333
|
-
|
|
417
|
+
The SDK exports the ordered principles as `BLOCK_INTERFACE_PRINCIPLES` (a job's
|
|
418
|
+
full list), split into `SHARED_INTERFACE_PRINCIPLES` and
|
|
419
|
+
`JOB_INTERFACE_PRINCIPLES`, the app rules as `APP_INTERFACE_PRINCIPLES`,
|
|
420
|
+
`interfaceMode(manifest)` (one of `INTERFACE_MODES`: `"job"` or `"app"`) and
|
|
421
|
+
`interfacePrinciples(mode)`;
|
|
422
|
+
`reviewViewDesign(view, {mode})` and `blockKitProblems(view, {mode})` take the
|
|
423
|
+
mode. The kit vocabulary is `BLOCK_KIT_CLASSES`. `INTERFACE_DESIGN_CONVENTIONS`,
|
|
334
424
|
`INTERFACE_DESIGN_PRINCIPLES` and `INTERFACE_AUTHORING_RULES` remain as
|
|
335
425
|
compatibility names for the same list.
|
|
336
426
|
|
package/MODULES.md
CHANGED
|
@@ -60,7 +60,7 @@ against the manifest's port types.
|
|
|
60
60
|
| `files.read(ref)` | The bytes, as an `ArrayBuffer`, of a saved image, video, audio, asset or file (a PDF, text, CSV, Markdown or JSON file on a `file` input) the Block received as input, or that StillMade made in this run: files it wrote, transform results and generated media. Media the person kept on their device (a `sm-media://device/...` address in a project Step) reads the same way, without leaving the device. Other files cannot be read, and transforms, hosted calls and actions accept only these references too; a hosted call or action gets a cloud copy of device media, made once per version. A reference is the file its `kind`, `assetId`, `versionId` and `url` name, so `{kind, assetId, versionId, url}` rebuilt from a `media.generate` result item (without its `key`) is the same file; any other file is refused with `MODULE_FILE_READ`, by `stillmade-block test --mock`, `ready` and `gate` as by StillMade. |
|
|
61
61
|
| `files.write(data, {mediaType, name})` | Saves PNG, JPEG, WebP, GIF, MP4, WebM, MP3, WAV, M4A or OGG media, or a PDF, TXT, CSV, Markdown, JSON or ZIP file (`application/pdf`, `text/plain`, `text/csv`, `text/markdown`, `application/json`, `application/zip`; a `{kind: 'file'}` reference), to the runner's library and returns a reference you can return as an output. At most 64 files per run. |
|
|
62
62
|
| `media.transform(request)` | On-device media work done by StillMade: decode audio to samples, extract or loudness-normalise audio, cut, join or re-encode video, and take thumbnails. Results are saved like `files.write`. See [Media processing](#media-processing). |
|
|
63
|
-
| `actions.run(action)` | Runs a declared portable action. `media.generate` opens one approval for its whole batch, naming the most it can cost in StillMade credits; `stock.search`
|
|
63
|
+
| `actions.run(action)` | Runs a declared portable action. `media.generate` opens one approval for its whole batch, naming the most it can cost in StillMade credits; `stock.search`, `stock.select`, `stock.auto`, `gif.search`, `gif.save` and `final.render` run directly. |
|
|
64
64
|
| `hosted.run(operation, request)` | Calls a hosted operation the manifest lists in `permissions.capabilities` (for example `text.generate`, `image.generate`, `audio.speech`, `web.research`). Each call is quoted and approved like a capability Block and paid with StillMade credits. |
|
|
65
65
|
| `net.fetch(url, {method, headers, body})` | Calls one of the origins declared in `permissions.network` through StillMade, which adds the person's own key or OAuth token. Returns a standard `Response`. See [Outside APIs](/docs/build/outside-apis). |
|
|
66
66
|
| `net.connect(url, {protocols})` | Opens a live WebSocket to the `wss://` form of a declared origin and resolves with the open socket. No key is added. See [Live connections](#live-connections). |
|
|
@@ -86,7 +86,10 @@ const voice = await stillmade.hosted.run('audio.speech', { text: plan.script, se
|
|
|
86
86
|
saved video, whose own sound it transcribes, so there is no need to extract the
|
|
87
87
|
audio first. `media.analyze` returns `{schemaVersion: 1, items}`, one item per
|
|
88
88
|
picture or video, and for one video takes an optional `range: {start, end}` in
|
|
89
|
-
seconds, at most 12 apart, to look closely at that part. `
|
|
89
|
+
seconds, at most 12 apart, to look closely at that part. With `reply: 'text'` it asks your own `question`
|
|
90
|
+
(and optional `instructions`, `maxTokens` up to 4,000) about one to ten saved pictures in one call and returns the
|
|
91
|
+
answer as text, priced per picture. `text.generate` takes `system` up to 32,000 and `prompt` up to 64,000 characters
|
|
92
|
+
and `maxTokens` up to 24,000; a call past the flat size is priced by its size. `image.generate` takes `prompt` and optional
|
|
90
93
|
`references`, one to eight saved images the new picture keeps. `video.generate` takes `prompt` and optional
|
|
91
94
|
`firstFrame` (a saved image the video starts on, for image-to-video), `lastFrame` (one it ends on; needs
|
|
92
95
|
`firstFrame`), `negativePrompt` (up to 2,000 characters) and `settings`; a model named in `settings` must take
|
|
@@ -147,7 +150,27 @@ per photo, which asks again from the second call. Video items take the same
|
|
|
147
150
|
|
|
148
151
|
It throws when no item was made, when the person declines (`MODULE_ACTION_DECLINED`)
|
|
149
152
|
and when the action is not declared (`MODULE_PERMISSION`). `stock.search` resolves
|
|
150
|
-
with `{results}`.
|
|
153
|
+
with `{results}`.
|
|
154
|
+
|
|
155
|
+
Stock media and GIFs:
|
|
156
|
+
|
|
157
|
+
| Action | Request | Resolves with | Credits |
|
|
158
|
+
| --- | --- | --- | --- |
|
|
159
|
+
| `stock.search` | `{query, type}` (`photo`, `video` or `audio`) | `{results}` | free |
|
|
160
|
+
| `stock.select` | `{result}`, one of those results | `{asset}`: the media to return as an output, with its license and receipt | as StillMade's own stock picker: at most 1 per pull bucket |
|
|
161
|
+
| `stock.auto` | `{queries, kind, excludeUrls}`: 1 to 10 searches, `photo` or `video`, up to 300 addresses to skip | `{asset, result}`, or `{asset: null, noMatch: true}` (or `transient: true` when the sources are busy) | as `stock.select`, only when something is found |
|
|
162
|
+
| `gif.search` | `{query, limit}`: up to 200 characters, 1 to 24 results | `{enabled, results: [{id, title, url, previewUrl, width, height}]}` | free |
|
|
163
|
+
| `gif.save` | `{url}`, a result's `url` | `{asset}`: the GIF kept in StillMade's storage | free |
|
|
164
|
+
|
|
165
|
+
A result's own address is not media the Block can show or return; keep it first with
|
|
166
|
+
`stock.select` or `gif.save`.
|
|
167
|
+
|
|
168
|
+
Rendering a video or a sound: `final.render` with `{schemaVersion: 1, kind: 'video' | 'audio', timeline, settings,
|
|
169
|
+
source}` (the Editor's render plan: clips, audio, overlays, `targetDuration`; settings `fps` 24/30/60, `resolution`
|
|
170
|
+
720/1080/2160, `quality`) resolves with `{asset}`, the MP4 or MP3 kept like `files.write`, to return as an output.
|
|
171
|
+
StillMade renders it on the person's device under its export rules (plan, watermark). Every address the
|
|
172
|
+
timeline holds, in any field, must be a file the run received or made; StillMade's own built-in sounds
|
|
173
|
+
(`/sounds/...`, `/sfx/...`) need nothing. With `--mock` or a `tests/mocks.json`, `media.generate` answers
|
|
151
174
|
with stand-in media and no failures; record your own answer under
|
|
152
175
|
`actions["media.generate"]`.
|
|
153
176
|
|
package/PASTE_TO_LLM.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- builder-contract:start (generated by npm run build:sdk; do not edit) -->
|
|
4
4
|
|
|
5
|
-
## Block builder contract (stillmade.block-builder@1.
|
|
5
|
+
## Block builder contract (stillmade.block-builder@1.18.0)
|
|
6
6
|
|
|
7
|
-
Contract `stillmade.block-builder@1.
|
|
7
|
+
Contract `stillmade.block-builder@1.18.0`. Humans, coding agents, imported source, GitHub repositories and generated code all adapt to the Block platform; anything that becomes a StillMade Block obeys this contract.
|
|
8
8
|
|
|
9
9
|
### Source of truth
|
|
10
10
|
|
|
@@ -73,7 +73,7 @@ These are StillMade's defaults: unless the person or the creator asked for somet
|
|
|
73
73
|
|
|
74
74
|
### Interface
|
|
75
75
|
|
|
76
|
-
If the capability needs UI, use the Block UI SDK: generated `manifest.ui` controls first; a sandboxed custom view (`view.html`/`view.css`/`view.js`) only when the core interaction needs one. Build custom views from the Block kit the host injects (`block-kit.css`): the result in `sm-stage`, drawn before the first run in the shape and size of what is coming (`data-ratio="9:16"` for a vertical clip, lines for text, a player bar for sound) so every part of the screen is in place at once and the result fills a place the person already sees instead of popping in somewhere unexpected; StillMade draws it the same way on the Steps it draws; on a wide screen what goes in sits on the left and the result on the right, side by side, and they stack only on narrow screens and phones, the result's place
|
|
76
|
+
If the capability needs UI, use the Block UI SDK: generated `manifest.ui` controls first; a sandboxed custom view (`view.html`/`view.css`/`view.js`) only when the core interaction needs one. Build custom views from the Block kit the host injects (`block-kit.css`): the result in `sm-stage`, drawn before the first run in the shape and size of what is coming (`data-ratio="9:16"` for a vertical clip, lines for text, a player bar for sound) so every part of the screen is in place at once and the result fills a place the person already sees instead of popping in somewhere unexpected; StillMade draws it the same way on the Steps it draws; on a wide screen what goes in sits on the left and the result on the right, side by side, and they stack only on narrow screens and phones, the result's place after the inputs with the job's action row on it (`sm-actions` and `sm-status` inside `sm-stage`: the kit puts the status top-left and the actions top-right in the player's cream blocks, over a band above the media; the run button is always the rightmost, so a button that spends credits never moves and making again is pressed where it made the first time, with Download and other result actions to its left), picks as pictures in `sm-choices`, the picked one in the kit's ink fill (never restyled to an outline, a tint or the page's background) so it reads at a glance, one solid `sm-primary` naming the action in the job's words ("Plan the tour", "Generate voiceover"; never "Run" or "Make it") and no price (StillMade's run button adds it), extras in a closed `sm-more`; a look the person names wins. Fit one laptop screen without scrolling: label beside control, status in a few words, files as tiles, rare tools as icons, (i) on unclear controls. These compact rules are for a job or an ingredient. Size the view to the Block's tier (block-tier.js): an app, a workspace a person works in for a while (video editor, 3D configurator, CAD or drawing tool, photo editor), declares `manifest.kind: "workspace"` and looks and works like that kind of app instead of a compact page, and StillMade's checks (admission, readiness, its own builder) then apply the app rules instead of the compact ones: no limit on controls in view, no Block kit page, its own layout, the craft's own words, and only its run button (`data-stillmade-action="run"`) held to naming what it makes: its canvas or stage fills the view, with the panels, toolbars, inspector or timeline such an app has, direct manipulation (select, drag, zoom), keyboard shortcuts and undo; it keeps the host appearance and Block kit controls, its panels may scroll, and on a phone its tools fold into sheets while the canvas stays usable. Never shrink an app into a form of fields and one button. StillMade centers a standard view narrower than its Step and zooms a view to fill its space; a stage shows what it holds in its middle as one group (a caption stays with its picture) and several results fill its width as one row, on a Block's screen and on the pages StillMade draws; an app that lays itself out (full-size canvas or WebGL, its own scroll, pan or zoom, its own Ctrl/Cmd +/- keys) puts `data-stillmade-layout="own"` on its outermost element, and StillMade then never centers, zooms or takes those keys. StillMade draws one player for every `<video controls>` (play, timeline, time, sound and full screen, shown for 3 s the first time it comes into view, then while the pointer is on the video, with keys and touch) and a full-screen button on result pictures in `sm-stage` or `sm-gallery` and on any element marked `data-stillmade-expand` (the same value makes one set of pictures, `off` removes it); `data-stillmade-player="native"` keeps the browser's controls, and a `<video>` without `controls` is the Block's own and is never touched. A picture or clip that cannot show here (kept on another device, or it did not open) keeps its place as a quiet `sm-media-off` tile in its own shape with the `image-off` glyph and the reason in its label, never words in its place. Drop words nobody needs; put helpful ones in a closed `sm-hint`. Mark each button `data-stillmade-action` (`run` on the one that runs the Block, which the device checks press once; a page that checks first keeps `run` on that button for both presses; what it does on the others, `"play sample"`) and label each field: Chat presses and fills them. Expose the capability, not the implementation: sensible defaults, previews, progress, clear errors, visible outputs. Show no raw JSON, internal IDs, filesystem details, provider terms or developer settings unless the Block is a developer tool. When a person chooses among options they need to hear or see (voices, music, fonts, looks, templates, images), let them preview each option before choosing: a sample or thumbnail from the Block's own files or the host's free samples, never a paid generation. Skip previews only when there is nothing to preview. Choices StillMade owns (voices, models in the run review) already show samples. Follow the host appearance (Light, Dark and White) and one elastic layout: stacked on a 320px phone with no sideways scroll (the inputs, the button in normal flow, never pinned, then the result's place under it), and from 860px the controls left (≤380px), the result filling the right. Short settings sit side by side, each label beside its control (`sm-field`, `sm-settings`; three or four short options as one `data-segmented` row); many items are one line each (`sm-list`) that open in place; input files are small tiles (`sm-gallery data-size="small"`); on a phone chip rows scroll sideways and long lists show three. Compacting moves controls, never deletes them.
|
|
77
77
|
|
|
78
78
|
### Shared editing
|
|
79
79
|
|
|
@@ -167,7 +167,7 @@ Every finished Block must support automatic remixing through the standard SDK co
|
|
|
167
167
|
|
|
168
168
|
### Package format
|
|
169
169
|
|
|
170
|
-
A Block package is StillMade SDK 0.1.0 JSON. Prefer {manifest,recipe,tests} for supported operations. Otherwise use {manifest,code,tests} with runtime:"javascript": code is a synchronous function body receiving input and returning declared output bindings, e.g. return {text:input.text.toUpperCase()}. JavaScript runs in isolated QuickJS: no fetch, DOM, Node APIs, modules, dependencies, timers, or host services; no promises, imports, require, eval or Function. Limits: 500 ms execution, 16 MiB heap, 256 KiB code, 4 MiB JSON I/O. Include concrete passing fixtures that reflect the requested behavior, including an edge case; never approximate a hosted model call with fabricated deterministic output. Manifest fields: schemaVersion:1,sdkVersion:"0.1.0",id:"creator.name",version:"1.0.0",name,description,kind:"task",runtime:"recipe", "javascript", "comfyui", or "capability",inputs/outputs as named {type,default?,min?,max?,role?,primary?}. Usually mark one primary input and output with primary:true. Semantic roles such as source_image and character_reference are distinct and must never be guessed,permissions:{project:[],network:[],filesystem:[],secrets:[]},ui:[{control,port}]. Recipe: {schemaVersion:1,steps:[{id,op,args}],outputs}. References: {"$input":"port"}, {"$step":"step-id"}. Supported operations: {"value.copy":{"description":"Copy a JSON value without changing it.","args":["value"]},"text.trim":{"description":"Remove leading and trailing whitespace.","args":["text"]},"text.replace":{"description":"Replace literal text; no regular expressions.","args":["text","find","replacement"]},"text.join":{"description":"Join an array of text values.","args":["items","separator"]},"image.thicken-lines":{"description":"Expand dark outlines while preserving other colors.","args":["image","thickness","threshold"]}}. Port types: text, number, integer, boolean, json, object, image, video, audio, asset, script, transcript, brief, bible, shot-plan, panel-document, board-document, scene-document, timeline, timeline-edit, file-bundle, workspace-edit, timeline-range, research, character, location, style, pipeline, approval, scene, shot, mask, depth, pose, metadata, project-context, file, document, table, url, date, color. A value is exactly: text: a string; number: a number; integer: a whole number; boolean: true or false; json: any JSON value; object: a plain JSON object; image: {kind: 'image'; assetId: string; versionId: string; url: string; mimeType?: string; bytes?: number; name?: string; role?: string; width?: number; height?: number}; video: {kind: 'video'; assetId: string; versionId: string; url: string; mimeType?: string; bytes?: number; name?: string; role?: string; width?: number; height?: number; duration?: number}; audio: {kind: 'audio'; assetId: string; versionId: string; url: string; mimeType?: string; bytes?: number; name?: string; role?: string; duration?: number; sampleRate?: number; channels?: number}; asset: {kind: 'image' | 'video' | 'audio' | 'asset'; assetId: string; versionId: string; url: string; mimeType?: string; bytes?: number; name?: string; role?: string}; script: {schemaVersion: 1; text: string; [key: string]: unknown}; transcript: {schemaVersion: 1; text: string; words: Array<{text: string; start: number; end: number}>}; file: {kind: 'file'; assetId: string; versionId: string; mimeType: 'application/pdf' | 'text/plain' | 'text/csv' | 'text/markdown' | 'application/json' | 'application/zip'; url?: string; name?: string; bytes?: number}; document: {schemaVersion: 1; format: 'markdown' | 'plain'; text: string; title?: string}; table: {schemaVersion?: 1; columns: string[]; rows: Array<Record<string, string | number | boolean | null>>}; url: an absolute http or https address string; date: an ISO 8601 date string ('2026-10-09' or '2026-10-09T14:30'); color: a hex color string ('#ff8800' or '#ff8800cc'). A file value is a saved file: one the person gives the Block (a module Block reads its bytes with stillmade.files.read) or what stillmade.files.write returns in a module Block; an image may also be decoded RGBA pixels {width, height, data} in recipe and JavaScript Blocks, which hold only 4 MiB of JSON (a picture of about 300 by 300 pixels), so a Block that joins photos into one picture (side by side, a grid, a contact sheet, a poster) is a module Block calling media.transform image.compose. Every other type is {schemaVersion: 1; [key: string]: unknown} with the fields its own section gives. A type ending in [] is a plain array of those values (audio[] is a list of audio references, never objects that wrap them). Include test {name,input,expected} where expected is output bindings.
|
|
170
|
+
A Block package is StillMade SDK 0.1.0 JSON. Prefer {manifest,recipe,tests} for supported operations. Otherwise use {manifest,code,tests} with runtime:"javascript": code is a synchronous function body receiving input and returning declared output bindings, e.g. return {text:input.text.toUpperCase()}. JavaScript runs in isolated QuickJS: no fetch, DOM, Node APIs, modules, dependencies, timers, or host services; no promises, imports, require, eval or Function. Limits: 500 ms execution, 16 MiB heap, 256 KiB code, 4 MiB JSON I/O. Include concrete passing fixtures that reflect the requested behavior, including an edge case; never approximate a hosted model call with fabricated deterministic output. Manifest fields: schemaVersion:1,sdkVersion:"0.1.0",id:"creator.name",version:"1.0.0",name,description,kind:"task" (or "workspace" for an app a person works in, such as a CAD tool or photo editor),runtime:"recipe", "javascript", "comfyui", or "capability",inputs/outputs as named {type,default?,min?,max?,role?,primary?}. Usually mark one primary input and output with primary:true. Semantic roles such as source_image and character_reference are distinct and must never be guessed,permissions:{project:[],network:[],filesystem:[],secrets:[]},ui:[{control,port}]. Recipe: {schemaVersion:1,steps:[{id,op,args}],outputs}. References: {"$input":"port"}, {"$step":"step-id"}. Supported operations: {"value.copy":{"description":"Copy a JSON value without changing it.","args":["value"]},"text.trim":{"description":"Remove leading and trailing whitespace.","args":["text"]},"text.replace":{"description":"Replace literal text; no regular expressions.","args":["text","find","replacement"]},"text.join":{"description":"Join an array of text values.","args":["items","separator"]},"image.thicken-lines":{"description":"Expand dark outlines while preserving other colors.","args":["image","thickness","threshold"]}}. Port types: text, number, integer, boolean, json, object, image, video, audio, asset, script, transcript, brief, bible, shot-plan, panel-document, board-document, scene-document, timeline, timeline-edit, file-bundle, workspace-edit, timeline-range, research, character, location, style, pipeline, approval, scene, shot, mask, depth, pose, metadata, project-context, file, document, table, url, date, color. A value is exactly: text: a string; number: a number; integer: a whole number; boolean: true or false; json: any JSON value; object: a plain JSON object; image: {kind: 'image'; assetId: string; versionId: string; url: string; mimeType?: string; bytes?: number; name?: string; role?: string; width?: number; height?: number}; video: {kind: 'video'; assetId: string; versionId: string; url: string; mimeType?: string; bytes?: number; name?: string; role?: string; width?: number; height?: number; duration?: number}; audio: {kind: 'audio'; assetId: string; versionId: string; url: string; mimeType?: string; bytes?: number; name?: string; role?: string; duration?: number; sampleRate?: number; channels?: number}; asset: {kind: 'image' | 'video' | 'audio' | 'asset'; assetId: string; versionId: string; url: string; mimeType?: string; bytes?: number; name?: string; role?: string}; script: {schemaVersion: 1; text: string; [key: string]: unknown}; transcript: {schemaVersion: 1; text: string; words: Array<{text: string; start: number; end: number}>}; file: {kind: 'file'; assetId: string; versionId: string; mimeType: 'application/pdf' | 'text/plain' | 'text/csv' | 'text/markdown' | 'application/json' | 'application/zip'; url?: string; name?: string; bytes?: number}; document: {schemaVersion: 1; format: 'markdown' | 'plain'; text: string; title?: string}; table: {schemaVersion?: 1; columns: string[]; rows: Array<Record<string, string | number | boolean | null>>}; url: an absolute http or https address string; date: an ISO 8601 date string ('2026-10-09' or '2026-10-09T14:30'); color: a hex color string ('#ff8800' or '#ff8800cc'). A file value is a saved file: one the person gives the Block (a module Block reads its bytes with stillmade.files.read) or what stillmade.files.write returns in a module Block; an image may also be decoded RGBA pixels {width, height, data} in recipe and JavaScript Blocks, which hold only 4 MiB of JSON (a picture of about 300 by 300 pixels), so a Block that joins photos into one picture (side by side, a grid, a contact sheet, a poster) is a module Block calling media.transform image.compose. Every other type is {schemaVersion: 1; [key: string]: unknown} with the fields its own section gives. A type ending in [] is a plain array of those values (audio[] is a list of audio references, never objects that wrap them). Include test {name,input,expected} where expected is output bindings.
|
|
171
171
|
|
|
172
172
|
### Feature map
|
|
173
173
|
|
|
@@ -231,7 +231,7 @@ Write the description in third-grade language: one short sentence, ideally 8–1
|
|
|
231
231
|
|
|
232
232
|
### Compact interface
|
|
233
233
|
|
|
234
|
-
Every job or ingredient Block interface, generated or custom, follows StillMade's compact rules: Compact: the whole Block fits one laptop screen without scrolling. A short setting is one row, its label beside the control; no card around a single control. Status is a dot or a few words ("No narration yet"), never a paragraph; the reason sits behind an `sm-hint`. Files are tiles: a saved file is a thumbnail or chip and adding one is the + tile (`<button class="sm-add" data-stillmade-add="<input>">`), which opens StillMade's picker. Never an `<input type="file">` or the bare browser file picker, and no size limits in view until a file is too big. An (i) beside anything a newcomer could misread: a setting, status or number whose effect is not obvious from its label gets a closed `sm-hint` with one or two sentences. Give every input that needs one a `description`; StillMade shows it as that (i). Obvious controls get none. Use the width: from 860px wide the kit puts the controls on the left at a reading width (300–380px) and the result (`sm-stage`) fills the right, in its real shape; under that everything stacks in the page's order: the inputs, the
|
|
234
|
+
Every job or ingredient Block interface, generated or custom, follows StillMade's compact rules: Compact: the whole Block fits one laptop screen without scrolling. A short setting is one row, its label beside the control; no card around a single control. Status is a dot or a few words ("No narration yet"), never a paragraph; the reason sits behind an `sm-hint`. Files are tiles: a saved file is a thumbnail or chip and adding one is the + tile (`<button class="sm-add" data-stillmade-add="<input>">`), which opens StillMade's picker. Never an `<input type="file">` or the bare browser file picker, and no size limits in view until a file is too big. An (i) beside anything a newcomer could misread: a setting, status or number whose effect is not obvious from its label gets a closed `sm-hint` with one or two sentences. Give every input that needs one a `description`; StillMade shows it as that (i). Obvious controls get none. Use the width: from 860px wide the kit puts the controls on the left at a reading width (300–380px) and the result (`sm-stage`) fills the right, in its real shape; under that everything stacks in the page's order: the inputs, then the result's place with its actions on it (never a pinned bar), so `sm-stage` comes after the inputs. Extra width goes to the result, never to wider text fields. Before there is a result, the stage previews what will be made from the inputs. `data-layout="stack"` opts out. StillMade draws generated manifest.ui controls this way itself (label beside control, files as tiles, the result filling the right on wide screens); you supply at most four inputs that matter in view, sensible defaults, and a short `description` on every input whose effect is not obvious from its name, which StillMade shows as its (i). An app is different: when the request is for software a person works in (an editor, a canvas, a 3D or CAD tool, a photo editor, a studio), set manifest.kind:"workspace", which makes it an app, and lay it out like that app: its work surface (viewport, canvas, timeline, panels, tool rails) owns the page with as much tooling as the app needs, and the compact rules apply to its settings, dialogs and status, never to the work surface. Never shrink an app to one screen of four inputs.
|
|
235
235
|
|
|
236
236
|
### Generated controls first
|
|
237
237
|
|
|
@@ -243,7 +243,7 @@ Optional custom view interfaces are supported, but generated manifest.ui control
|
|
|
243
243
|
|
|
244
244
|
*When:* StillMade's builder adds this section when the person asks for an interface, preview or controls, or refines a Block that has one.
|
|
245
245
|
|
|
246
|
-
A custom interface is the optional package-level view:{html,css?,themedCss?,javascript?}; when refining, preserve and refine base.view. Design it by StillMade's interface principles, in order: Function first: unless the person asks for a design direction, build from the Block kit (`sm-block`, `sm-stage`, `sm-choices`, `sm-actions`, `sm-more`) and ship little or no CSS of your own. A direction the person names wins over the kit. Show the thing being made: the preview, media or result gets the largest area (`sm-stage`), and every part shows at once: before the first run the result's place is drawn in the shape and size of what is coming (a 9:16 frame for a vertical clip, lines for text, a player bar for sound), so the result fills it instead of popping in. On a wide screen what goes in sits on the left and the result on the right; they stack only on narrow screens and phones. A picture or clip the Block makes fills it in its own shape, as large as fits; several fill it as a grid, each big enough to watch. Small tiles are for the files a person gives the Block, never for what it makes. A clip is a `<video controls>`, which StillMade plays in its own player with full screen, and a picture in `sm-stage` or `sm-gallery` (or marked `data-stillmade-expand`) gets StillMade's full-screen button; leave out `controls` only when the Block drives playback itself. Never a JSON dump, source editor, manifest or diagnostic panel unless the task is about source. One obvious next action: one solid `sm-primary` in the kit's ink, never restyled to the background or a ghost outline; peers are `sm-quiet` buttons or named icons, and close is an X icon. Seven or fewer choices in view. Speak the job unless the person or creator asks otherwise. The action button names what it does in the job's words (`manifest.action`: "Plan the tour"; AI pictures, video and sound start with Generate and say what, the person's own media cut or rendered says Make: "Generate voiceover", "Make 6 clips"), never "Make it", "Run", "Run step", "Submit", "Process" or a bare "Generate"; progress counts the job's units ("4 of 9 rooms"), never "Processing"; results and problems use its words in one line. Show no credit numbers: StillMade puts the price beside the verb on its own run button ("Write · 1 credit"), with a chip for the model, quality or count when they can change. Pressing it runs at that price; a confirmation appears only when the server price is higher than the one shown. Pictures over words: choices people see or hear are thumbnails, swatches, samples or glyphs (`sm-choices`), not word lists. Icons carry an accessible name and tooltip; never emoji. A picked option reads at a glance: keep the kit's ink fill on an `sm-choices` pick, never restyled to an outline, a tint or the page's background. Media that cannot show here (on another device, or it did not open) keeps its place as a quiet `sm-media-off` tile in its own shape, never words in its place. Words only when needed. Drop what nobody needs to finish the task (intros, "how it works", restating the Block name). Words that might help start collapsed (`sm-hint`, `sm-more`). Errors, spending approvals, stale inputs and destructive steps stay visible, in few words. Strong defaults; secondary settings go in `sm-more`, closed. Compact: the whole Block fits one laptop screen without scrolling. A short setting is one row, its label beside the control; no card around a single control. Status is a dot or a few words ("No narration yet"), never a paragraph; the reason sits behind an `sm-hint`. Files are tiles: a saved file is a thumbnail or chip and adding one is the + tile (`<button class="sm-add" data-stillmade-add="<input>">`), which opens StillMade's picker. Never an `<input type="file">` or the bare browser file picker, and no size limits in view until a file is too big. Rare tools (update, schedule, history, reload) are named icon buttons beside the action, never sections under the work. An (i) beside anything a newcomer could misread: a setting, status or number whose effect is not obvious from its label gets a closed `sm-hint` with one or two sentences. Give every input that needs one a `description`; StillMade shows it as that (i). Obvious controls get none. One workspace: no cards inside cards, no second title, step counter or Back/Next bar; the host owns navigation. One page per job (November 3, 2026): a guided job's screen holds the inputs and settings, then a cheap check before the expensive run (the script and a voice sample before the video, a second `StillMade.run` that StillMade prices on its own), then the result; never a second Block or Step for the check. A workspace a person works in (a CAD tool, a canvas, an editor) is its own Block, and turning what it made into something else is the next one. Status sits beside the action it describes (`sm-status`), in a few words. Keep the page in normal scroll flow; no sticky media or control strips unless the editing task needs them. Use the width: from 860px wide the kit puts the controls on the left at a reading width (300–380px) and the result (`sm-stage`) fills the right, in its real shape; under that everything stacks in the page's order: the inputs, the action in normal flow (never pinned), then the result's place under it, so put `sm-stage` after `sm-actions`. Extra width goes to the result, never to wider text fields. Before there is a result, the stage previews what will be made from the inputs. `data-layout="stack"` opts out. Size with the kit, never fixed sizes: no fixed pixel widths or heights for the workspace or stage, no 100vh, no position:fixed panels. StillMade zooms a Block's screen to fill the space it has (up to 150%, never down to a phone layout on a computer), so a Block laid out with the kit's spacing fills its Step without empty space, and it centers a standard view narrower than its Step. The kit's `sm-stage` shows what it holds in its middle as one group (a caption stays with its picture), and several results in a stage fill its width as one row; the pages StillMade draws follow the same rule. An app that lays itself out (full-size canvas or WebGL, its own scroll, pan or zoom, its own Ctrl/Cmd +/- keys) puts `data-stillmade-layout="own"` on its outermost element, and StillMade then never centers, zooms or takes those keys. Group what the person sets in one `sm-fields` (or `sm-settings` for short ones): the kit gives the group its own surface, so the inputs, the settings and the result read as separate parts. Settings sit side by side (`sm-settings`), next to what they change. Three or four short options are one segmented row (`data-segmented`), not a row of big tiles. Lists fill the width at a small size: input files are small tiles (`sm-gallery data-size="small"`), many items are one line each (`sm-list`): a thumbnail, one line of text, a short fact. Tapping an item opens all of its fields in place. Extra width means more items per row, never bigger cards. On a phone chip and segment rows scroll sideways instead of wrapping; long lists show their first three with "N more" (`data-peek`) and long text five lines until tapped (`sm-clamp`). Nothing is lost when a Block gets smaller: every control stays on the screen, behind an (i), in `sm-more`, or inside the item it belongs to. Compacting moves controls; it never deletes them. Text scene descriptions are planning notes, never a storyboard or an approved frame. Say nothing about how the Block works: no notes on where it runs (this device, StillMade Desktop, the cloud), saving, syncing, recovery, accounts, credits or where a file is kept. StillMade tells the person what they need as one short notification, or nothing; never a sentence on the page, and never the same line under each item. References fill your inputs: every drop area in StillMade offers "Use a reference", and the person's saved photos, videos and notes fill the Step with no typing. Media inputs fill by kind, so take `video` or `asset` wherever a clip works as well as a photo; text inputs fill by plain names and labels (`productName`, `website`, `brandColors`, `fonts`, `voice`, and `details` or `notes` for the reference's note). Never build your own reference picker or library upload. Days and times are picked, never typed: a `date` input is a calendar, with a list of times when it is about a time (`postAt`, `startsAt`, a label with Time, When or Starts). In a custom view use `<input type="date">` or `type="datetime-local"`, never a text box for a date. Posting is its own Step: sending a result to Instagram, TikTok, email or any app is a connector Step after the Block, worded by StillMade ("Post to Instagram"). A Block never posts from inside itself. Its DOM controller is separate from manifest runtime code. The view may also declare appearance:"original" or "host". For an imported design, preserve its colors with appearance:"original" and view.css; no themed replacement is required. Preserve base.view.appearance when refining unless the user requests a change. Omitted/host appearance retains the existing Light, Dark and White requirement: supply semantic colors in view.css or a complete replacement view.themedCss. An original-style view may optionally supply valid themedCss for a StillMade appearance preview. Use StillMade variables (--bg,--fg,--fg-muted,--border-tok,--r-3) only when opting into host styling; do not redefine host tokens in the themed variant. Appearance never relaxes sandbox constraints: no CSS escapes/filters/blending, imports/url(), or element.style mutations in JS. Use classes for UI state; media pixels retain their colors. Both CSS fields have the same 32 KiB limit; all existing shared-state, security and permission checks still apply. Declare elements in html, bind with document.getElementById/querySelector and addEventListener; use literal property access, array methods, textContent, input.value, button.disabled and canvas. Initial values: StillMade.onInput(values=>{...}); await StillMade.run(inputBindings) returns validated output bindings from the isolated package runtime; catch errors and show results. No computation in the DOM controller; put it in code/recipe. Disable the action button while pending.
|
|
246
|
+
A custom interface is the optional package-level view:{html,css?,themedCss?,javascript?}; when refining, preserve and refine base.view. Design it by StillMade's interface principles. Every Block: Speak the job unless the person or creator asks otherwise. The action button names what it does in the job's words (`manifest.action`: "Plan the tour"; AI pictures, video and sound start with Generate and say what, the person's own media cut or rendered says Make: "Generate voiceover", "Make 6 clips"), never "Make it", "Run", "Run step", "Submit", "Process" or a bare "Generate"; progress counts the job's units ("4 of 9 rooms"), never "Processing"; results and problems use its words in one line. Show no credit numbers: StillMade puts the price beside the verb on its own run button ("Write · 1 credit"), with a chip for the model, quality or count when they can change. Pressing it runs at that price; a confirmation appears only when the server price is higher than the one shown. Pictures over words: choices people see or hear are thumbnails, swatches, samples or glyphs (`sm-choices`), not word lists. Icons carry an accessible name and tooltip; never emoji. A picked option reads at a glance: keep the kit's ink fill on an `sm-choices` pick, never restyled to an outline, a tint or the page's background. Media that cannot show here (on another device, or it did not open) keeps its place as a quiet `sm-media-off` tile in its own shape, never words in its place. Words only when needed. Drop what nobody needs to finish the task (intros, "how it works", restating the Block name). Words that might help start collapsed (`sm-hint`, `sm-more`). Errors, spending approvals, stale inputs and destructive steps stay visible, in few words. Status is a dot or a few words ("No narration yet"), never a paragraph; the reason sits behind an `sm-hint`. Files are tiles: a saved file is a thumbnail or chip and adding one is the + tile (`<button class="sm-add" data-stillmade-add="<input>">`), which opens StillMade's picker. Never an `<input type="file">` or the bare browser file picker, and no size limits in view until a file is too big. An (i) beside anything a newcomer could misread: a setting, status or number whose effect is not obvious from its label gets a closed `sm-hint` with one or two sentences. Give every input that needs one a `description`; StillMade shows it as that (i). Obvious controls get none. Nothing is lost when a Block gets smaller: every control stays on the screen, behind an (i), in `sm-more`, or inside the item it belongs to. Compacting moves controls; it never deletes them. Text scene descriptions are planning notes, never a storyboard or an approved frame. Say nothing about how the Block works: no notes on where it runs (this device, StillMade Desktop, the cloud), saving, syncing, recovery, accounts, credits or where a file is kept. StillMade tells the person what they need as one short notification, or nothing; never a sentence on the page, and never the same line under each item. References fill your inputs: every drop area in StillMade offers "Use a reference", and the person's saved photos, videos and notes fill the Step with no typing. Media inputs fill by kind, so take `video` or `asset` wherever a clip works as well as a photo; text inputs fill by plain names and labels (`productName`, `website`, `brandColors`, `fonts`, `voice`, and `details` or `notes` for the reference's note). Never build your own reference picker or library upload. Days and times are picked, never typed: a `date` input is a calendar, with a list of times when it is about a time (`postAt`, `startsAt`, a label with Time, When or Starts). In a custom view use `<input type="date">` or `type="datetime-local"`, never a text box for a date. Posting is its own Step: sending a result to Instagram, TikTok, email or any app is a connector Step after the Block, worded by StillMade ("Post to Instagram"). A Block never posts from inside itself. A job (the default; manifest.kind "task" or none) also: Function first: unless the person asks for a design direction, build from the Block kit (`sm-block`, `sm-stage`, `sm-choices`, `sm-actions`, `sm-more`) and ship little or no CSS of your own. A direction the person names wins over the kit. Show the thing being made: the preview, media or result gets the largest area (`sm-stage`), and every part shows at once: before the first run the result's place is drawn in the shape and size of what is coming (a 9:16 frame for a vertical clip, lines for text, a player bar for sound), so the result fills it instead of popping in. On a wide screen what goes in sits on the left and the result on the right; they stack only on narrow screens and phones. A picture or clip the Block makes fills it in its own shape, as large as fits; several fill it as a grid, each big enough to watch. Small tiles are for the files a person gives the Block, never for what it makes. A clip is a `<video controls>`, which StillMade plays in its own player with full screen, and a picture in `sm-stage` or `sm-gallery` (or marked `data-stillmade-expand`) gets StillMade's full-screen button; leave out `controls` only when the Block drives playback itself. Never a JSON dump, source editor, manifest or diagnostic panel unless the task is about source. One obvious next action: one solid `sm-primary` in the kit's ink, never restyled to the background or a ghost outline; peers are `sm-quiet` buttons or named icons, and close is an X icon. Seven or fewer choices in view. Actions on the stage (owner, November 5, 2026): a job's `sm-actions` and `sm-status` go inside its `sm-stage`, and the kit lays them over it, the status top-left and the actions top-right, in the cream blocks of StillMade's player, with a band kept above the media so they never cover it; the media fills the rest of the stage. A button that spends credits never moves: the run button (`data-stillmade-action="run"`) is always the rightmost and stays in that spot when it makes again ("Make video", then "Make video again"), and what the result adds (Download, Share) goes to its left. Controls on media (StillMade's player, the full-screen square) show for 3 seconds the first time it comes into view, then only while it is hovered or tapped. StillMade's own Step pages do the same. An app that lays itself out keeps its own toolbar. Strong defaults; secondary settings go in `sm-more`, closed. Compact: the whole Block fits one laptop screen without scrolling. A short setting is one row, its label beside the control; no card around a single control. Rare tools (update, schedule, history, reload) are named icon buttons beside the action, never sections under the work. One workspace: no cards inside cards, no second title, step counter or Back/Next bar; the host owns navigation. One page per job (November 3, 2026): a guided job's screen holds the inputs and settings, then a cheap check before the expensive run (the script and a voice sample before the video, a second `StillMade.run` that StillMade prices on its own), then the result; never a second Block or Step for the check. A workspace a person works in (a CAD tool, a canvas, an editor) is its own Block, and turning what it made into something else is the next one. Status goes in `sm-status`, in a few words: top-left on the stage when the actions are there, otherwise beside the action it describes. Keep the page in normal scroll flow; no sticky media or control strips unless the editing task needs them. Use the width: from 860px wide the kit puts the controls on the left at a reading width (300–380px) and the result (`sm-stage`) fills the right, in its real shape; under that everything stacks in the page's order: the inputs, then the result's place with its actions on it (never a pinned bar), so `sm-stage` comes after the inputs. Extra width goes to the result, never to wider text fields. Before there is a result, the stage previews what will be made from the inputs. `data-layout="stack"` opts out. Size with the kit, never fixed sizes: no fixed pixel widths or heights for the workspace or stage, no 100vh, no position:fixed panels. StillMade zooms a Block's screen to fill the space it has (up to 150%, never down to a phone layout on a computer), so a Block laid out with the kit's spacing fills its Step without empty space, and it centers a standard view narrower than its Step. The kit's `sm-stage` shows what it holds in its middle as one group (a caption stays with its picture), and several results in a stage fill its width as one row; the pages StillMade draws follow the same rule. An app that lays itself out (full-size canvas or WebGL, its own scroll, pan or zoom, its own Ctrl/Cmd +/- keys) puts `data-stillmade-layout="own"` on its outermost element, and StillMade then never centers, zooms or takes those keys. Group what the person sets in one `sm-fields` (or `sm-settings` for short ones): the kit gives the group its own surface, so the inputs, the settings and the result read as separate parts. Settings sit side by side (`sm-settings`), next to what they change. Three or four short options are one segmented row (`data-segmented`), not a row of big tiles. Lists fill the width at a small size: input files are small tiles (`sm-gallery data-size="small"`), many items are one line each (`sm-list`): a thumbnail, one line of text, a short fact. Tapping an item opens all of its fields in place. Extra width means more items per row, never bigger cards. On a phone chip and segment rows scroll sideways instead of wrapping; long lists show their first three with "N more" (`data-peek`) and long text five lines until tapped (`sm-clamp`). An app (manifest.kind "workspace"; software a person works in, like a CAD tool or a photo editor) follows these instead of the job-only ones, and StillMade's checks hold it to them: An app (manifest.kind "workspace") is software a person works in for a while: a CAD or 3D tool, a photo editor, a timeline, a canvas, a studio. Its work surface (viewport, canvas, image, timeline) owns the page, laid out like the best apps of its kind, with the tool rail, panels, inspector, layers, timeline and menus the craft needs and as many controls as it needs. Never shrink it into a form of fields and one button. It lays itself out: `data-stillmade-layout="own"` on its outermost element, so StillMade never centers or zooms it and leaves Ctrl/Cmd +/- to it. Full-size panels, fixed toolbars and its own scroll, pan and zoom are fine. Work happens on the surface: select, drag, zoom and pan, keyboard shortcuts for the common tools, undo and redo. Speak the craft: tools and panels use the words people of that craft use (Exposure, Keyframe, Extrude, Layers, Mask), never a plain-language rewrite. A button that spends credits still names what it makes ("Generate fill"), carries `data-stillmade-action="run"` and shows no price; StillMade adds it. Order, not sparseness: tools grouped in panels that fold, the most used in view, rare ones in menus. No intros or paragraphs on the surface; a tool that needs explaining gets a tooltip or an (i). StillMade's appearance (Light, Dark and White) and the Block kit's controls (buttons, fields, sliders, `sm-choices` with thumbnails for presets) wherever they fit; the layout is the app's own. A look the person names wins. On a phone the work surface stays usable and the panels fold into sheets or one tool strip. What the person makes leaves the app as the Block's outputs (and, while they work, its shared state), so the next Step and the other people in the project get it. Its DOM controller is separate from manifest runtime code. The view may also declare appearance:"original" or "host". For an imported design, preserve its colors with appearance:"original" and view.css; no themed replacement is required. Preserve base.view.appearance when refining unless the user requests a change. Omitted/host appearance retains the existing Light, Dark and White requirement: supply semantic colors in view.css or a complete replacement view.themedCss. An original-style view may optionally supply valid themedCss for a StillMade appearance preview. Use StillMade variables (--bg,--fg,--fg-muted,--border-tok,--r-3) only when opting into host styling; do not redefine host tokens in the themed variant. Appearance never relaxes sandbox constraints: no CSS escapes/filters/blending, imports/url(), or element.style mutations in JS. Use classes for UI state; media pixels retain their colors. Both CSS fields have the same 32 KiB limit; all existing shared-state, security and permission checks still apply. Declare elements in html, bind with document.getElementById/querySelector and addEventListener; use literal property access, array methods, textContent, input.value, button.disabled and canvas. Initial values: StillMade.onInput(values=>{...}); await StillMade.run(inputBindings) returns validated output bindings from the isolated package runtime; catch errors and show results. No computation in the DOM controller; put it in code/recipe. Disable the action button while pending.
|
|
247
247
|
Standard custom view code (no `view.config.json` frame runtime) is checked before it runs. These rules come straight from the validator; frame views run in their own sandbox and may build the page with ordinary DOM calls such as `createElement`:
|
|
248
248
|
|
|
249
249
|
- **HTML elements:** only `div`, `section`, `article`, `header`, `footer`, `main`, `aside`, `nav`, `h1`, `h2`, `h3`, `h4`, `p`, `span`, `strong`, `em`, `i`, `small`, `br`, `hr`, `label`, `input`, `textarea`, `button`, `select`, `option`, `optgroup`, `fieldset`, `legend`, `output`, `progress`, `meter`, `ul`, `ol`, `li`, `dl`, `dt`, `dd`, `figure`, `figcaption`, `img`, `video`, `audio`, `source`, `canvas`, `table`, `thead`, `tbody`, `tfoot`, `tr`, `th`, `td`, `pre`, `code`, `details`, `summary`. No scripts, iframes, SVG, forms, comments or inline event attributes; media URLs must be `data:` or `blob:`.
|
|
@@ -254,8 +254,9 @@ Standard custom view code (no `view.config.json` frame runtime) is checked befor
|
|
|
254
254
|
- **Property access with brackets needs a literal key:** `items[0]` and `record["title"]` are accepted; `items[index]` is rejected. Iterate with `map`/`forEach` or call `items.at(index)`.
|
|
255
255
|
- **No named recursive functions** and no listeners on the global frame; attach events to declared controls.
|
|
256
256
|
- **Dynamic elements:** `StillMade.render` can create `div`, `section`, `article`, `header`, `footer`, `p`, `span`, `strong`, `em`, `i`, `small`, `h1`, `h2`, `h3`, `h4`, `label`, `button`, `input`, `textarea`, `select`, `option`, `ul`, `ol`, `li`, `table`, `thead`, `tbody`, `tr`, `th`, `td`, `details`, `summary`, `output`, `progress`, `img`; give repeated items stable IDs derived from their identity. An `img` gets its picture when you set its `src` to the data URL `StillMade.previewImage` returns, after rendering; the renderer keeps Block-owned `src`. `previewImage` works on items of an `image[]` input.
|
|
257
|
+
- **Preview controls:** a button whose whole text is `Preview` shows the StillMade preview icon alone (an eye in viewfinder corners), with `Preview` as its accessible name; give it a `label` such as `Preview clip 2` when several sit together. Do not draw your own eye or play icon for a preview.
|
|
257
258
|
- **Shared writes are queued in order:** if one `StillMade.updateShared` write is rejected (conflict, read-only or timeout), the writes queued behind it are rejected too. Send dependent edits one at a time or through `StillMade.scheduleSharedEdit`, keep the person's draft, and retry from the latest `onShared` value. `{merge: true}` merges independent fields of an object value; create an absent field with the precondition `{exists: false}`.
|
|
258
|
-
- **Limits:** HTML 64 KiB, CSS 32 KiB, JavaScript 64 KiB;
|
|
259
|
+
- **Limits:** HTML 64 KiB, CSS 32 KiB, JavaScript 64 KiB; 120 runs and 240 image previews per minute.
|
|
259
260
|
## Shared project interfaces
|
|
260
261
|
Every meaningful edit and generated result must be visible to collaborators.
|
|
261
262
|
Prefer ordinary manifest.ui controls and declared outputs when those express
|
|
@@ -960,8 +961,9 @@ Standard custom view code (no `view.config.json` frame runtime) is checked befor
|
|
|
960
961
|
- **Property access with brackets needs a literal key:** `items[0]` and `record["title"]` are accepted; `items[index]` is rejected. Iterate with `map`/`forEach` or call `items.at(index)`.
|
|
961
962
|
- **No named recursive functions** and no listeners on the global frame; attach events to declared controls.
|
|
962
963
|
- **Dynamic elements:** `StillMade.render` can create `div`, `section`, `article`, `header`, `footer`, `p`, `span`, `strong`, `em`, `i`, `small`, `h1`, `h2`, `h3`, `h4`, `label`, `button`, `input`, `textarea`, `select`, `option`, `ul`, `ol`, `li`, `table`, `thead`, `tbody`, `tr`, `th`, `td`, `details`, `summary`, `output`, `progress`, `img`; give repeated items stable IDs derived from their identity. An `img` gets its picture when you set its `src` to the data URL `StillMade.previewImage` returns, after rendering; the renderer keeps Block-owned `src`. `previewImage` works on items of an `image[]` input.
|
|
964
|
+
- **Preview controls:** a button whose whole text is `Preview` shows the StillMade preview icon alone (an eye in viewfinder corners), with `Preview` as its accessible name; give it a `label` such as `Preview clip 2` when several sit together. Do not draw your own eye or play icon for a preview.
|
|
963
965
|
- **Shared writes are queued in order:** if one `StillMade.updateShared` write is rejected (conflict, read-only or timeout), the writes queued behind it are rejected too. Send dependent edits one at a time or through `StillMade.scheduleSharedEdit`, keep the person's draft, and retry from the latest `onShared` value. `{merge: true}` merges independent fields of an object value; create an absent field with the precondition `{exists: false}`.
|
|
964
|
-
- **Limits:** HTML 64 KiB, CSS 32 KiB, JavaScript 64 KiB;
|
|
966
|
+
- **Limits:** HTML 64 KiB, CSS 32 KiB, JavaScript 64 KiB; 120 runs and 240 image previews per minute.
|
|
965
967
|
|
|
966
968
|
<!-- view-rules:end -->
|
|
967
969
|
|
|
@@ -1240,10 +1242,25 @@ renders leave the previous controls intact. Text is always literal; scripts,
|
|
|
1240
1242
|
inline handlers, links, file inputs, network attributes, and raw HTML are rejected.
|
|
1241
1243
|
|
|
1242
1244
|
|
|
1245
|
+
### Spending approvals
|
|
1246
|
+
|
|
1247
|
+
A press of the Block's own button pays for one run's hosted calls at StillMade's
|
|
1248
|
+
price. A screen whose button starts many runs (a build that makes thirty pictures,
|
|
1249
|
+
one run each) asks once instead: from that press, call
|
|
1250
|
+
`await StillMade.allowSpending({credits, label})` with the total the button showed
|
|
1251
|
+
and its words. StillMade shows its own dialog; when the person allows it, that
|
|
1252
|
+
Step's later runs spend from the total silently, each call at StillMade's own
|
|
1253
|
+
price, for 30 minutes, and a call past what is left asks as usual. It resolves
|
|
1254
|
+
with `{allowed, credits}`. It works only from a person's click or key press in a
|
|
1255
|
+
project Step (never from Chat), up to 2,000 credits (`VIEW_LIMITS.allowanceCredits`).
|
|
1256
|
+
|
|
1243
1257
|
### Audio and video playback
|
|
1244
1258
|
|
|
1245
|
-
`await StillMade.previewMedia(reference)` opens an authorized `audio` or `video`
|
|
1246
|
-
reference as a temporary
|
|
1259
|
+
`await StillMade.previewMedia(reference)` opens an authorized `image`, `audio` or `video`
|
|
1260
|
+
reference as a temporary copy and returns `{kind, url, mimeType, bytes}`. A picture comes back as the
|
|
1261
|
+
original file at full size (an animated GIF keeps moving); `previewImage` gives a small still instead.
|
|
1262
|
+
A frame view keeps up to `FRAME_VIEW_LIMITS.mediaPreviews` media previews open at once (a standard view two);
|
|
1263
|
+
release one with `StillMade.releaseMedia(url)` when it scrolls away or closes.
|
|
1247
1264
|
Assign its URL to an existing `<audio controls>` or `<video controls>` element.
|
|
1248
1265
|
The host requires an exact reference from this Block’s bound input, an explicitly
|
|
1249
1266
|
selected project asset, permitted project context, or a host-recorded output.
|