stillmade-sdk 0.1.49 → 0.1.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/AGENTS.md +6 -2
  2. package/AGENT_CONTROL.md +15 -0
  3. package/FRAME_VIEWS.md +30 -0
  4. package/INTERFACE_DESIGN.md +84 -7
  5. package/MODULES.md +2 -2
  6. package/PASTE_TO_LLM.md +26 -19
  7. package/SDK.md +180 -45
  8. package/UI_AESTHETIC.md +15 -0
  9. package/blocks/generate/package.js +1 -1
  10. package/blocks/generate/versions/1.1.0/package.js +471 -0
  11. package/blocks/generate/versions/1.2.0/package.js +555 -0
  12. package/blocks/native/sm.board-editor/versions/3.0.0/package.js +50 -17
  13. package/blocks/native/sm.board-editor/versions/3.1.0/package.js +1037 -0
  14. package/blocks/native/sm.editor/versions/3.0.0/package.js +128 -83
  15. package/blocks/native/sm.editor/versions/3.1.0/package.js +1299 -0
  16. package/blocks/native/sm.panel-strip/versions/3.0.0/package.js +45 -12
  17. package/blocks/native/sm.panel-strip/versions/3.1.0/package.js +479 -0
  18. package/blocks/native/sm.voiceover/versions/3.0.0/package.js +9 -3
  19. package/docs/build/block-builder-contract.md +6 -2
  20. package/docs/build/frame-views.md +30 -0
  21. package/docs/build/interface-design.md +84 -7
  22. package/docs/build/modules.md +2 -2
  23. package/docs/reference/authoring-guide.md +4 -4
  24. package/docs/reference/errors.md +1 -1
  25. package/docs/reference/execution.md +18 -4
  26. package/docs/reference/first-party-blocks.md +4 -4
  27. package/docs/reference/parity.md +1 -1
  28. package/docs/reference/ports.md +1 -1
  29. package/docs/reference/view-bridge.md +3 -0
  30. package/docs/tools/llm.md +26 -19
  31. package/package.json +1 -1
  32. package/packages/block-cli/dev-host/assets/host.js +161 -33
  33. package/packages/block-cli/dev-host/assets/index.css +1 -1
  34. package/packages/block-platform/block-readiness.js +16 -3
  35. package/packages/block-platform/canvas.js +4 -1
  36. package/packages/block-platform/catalog.js +32 -5
  37. package/packages/block-platform/flow-inspection.js +30 -2
  38. package/packages/block-platform/listings.js +16 -2
  39. package/packages/block-platform/steps.js +4 -1
  40. package/packages/block-sdk/admission.js +2 -2
  41. package/packages/block-sdk/agent-inputs.js +4 -2
  42. package/packages/block-sdk/appearance.js +19 -4
  43. package/packages/block-sdk/builder-contract.js +7 -4
  44. package/packages/block-sdk/first-party-identities.js +9 -1
  45. package/packages/block-sdk/first-party-packages.js +11 -1
  46. package/packages/block-sdk/generation-catalog.js +55 -5
  47. package/packages/block-sdk/generation-models.js +60 -0
  48. package/packages/block-sdk/index.d.ts +18 -4
  49. package/packages/block-sdk/index.js +2 -1
  50. package/packages/block-sdk/input-source-policy.js +2 -1
  51. package/packages/block-sdk/module-hosted.js +13 -5
  52. package/packages/block-sdk/module-worker.js +1 -1
  53. package/packages/block-sdk/port-types.js +6 -2
  54. package/packages/block-sdk/semantic-contracts.d.ts +1 -1
  55. package/packages/block-sdk/semantic-relationships.js +3 -0
  56. package/packages/block-sdk/semantic-schema.js +4 -1
  57. package/packages/block-sdk/shared-controls.js +4 -1
  58. package/packages/block-sdk/staged-releases.js +2 -1
  59. package/packages/block-sdk/testing.js +3 -0
  60. package/packages/block-sdk/view-bridge.js +3 -0
  61. package/packages/block-sdk/view-design.js +56 -12
  62. package/packages/block-sdk/view-renderer.js +19 -6
  63. package/packages/block-sdk/view.js +3 -2
  64. package/packages/design-system/block-kit.css +12 -3
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.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.
9
+ Contract `stillmade.block-builder@1.21.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 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.
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 (`data-stillmade-action="download"`, which needs no code: StillMade saves the stage's picture or clip under the export policy) 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 adds it) once the view says what its next run makes (`StillMade.nextRun`: its `media.generate` items or hosted operations), 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 unless it sets view `appearance: "none"` (`src/view.config.json`), which only an app may: StillMade then adds none of its theme, colors, fonts, page or Block kit, the app's own CSS styles everything from the browser's defaults and the style checks are its own call, while shared state, inputs and outputs, hosted operations, the run button's price and StillMade's picker work as before; 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
 
@@ -85,6 +85,10 @@ Projects are multiplayer, and StillMade builds it: every ordinary control on a B
85
85
 
86
86
  Reach external services only through StillMade's hosted operations, the connections service (`connection.execute`), or, in a module Block, `stillmade.net.fetch` to origins declared in `permissions.network` (with the key each needs), `stillmade.net.connect` for a live WebSocket to one of them, and `stillmade.connections.call` to adapters or catalog apps in `permissions.connections`; never put keys in code, inputs or headers: StillMade adds each person's own key on its servers. The host owns the model and provider choice, BYOK keys, StillMade credits, spending consent, authorization, token refresh, rate limits, retries and provider errors; a Block never receives a secret and never names a provider unless it must. Treat provider unavailability, timeout, cancellation and partial failure as outcomes the Block reports, not crashes: a call the result needs throws and fails the run (see Useful failures); an optional part's failure is caught, given its fallback and named in an optional `notes` text output. Generated images, video, voices, music and sound effects come from hosted operations or the `media.generate` action, paid with the user's StillMade credits at StillMade's prices; for structured model output declare a `json` output with `capability.schema` instead of parsing prose. When a Block needs npm libraries, WebAssembly (threaded: `"threads": true` in module.json) or heavy compute, use `runtime: "module"` and reach hosted operations through `stillmade.hosted.run` with the operations listed in `permissions.capabilities`. Decode, cut, join, re-encode, extract or normalise audio and video with `stillmade.media.transform` on the device; never ask for a server render. For a rich interactive interface (React or another framework, SVG, canvas, drag), use a frame view: `src/view.config.json` with `{"runtime":"frame"}` and `src/view.js` bundled as one IIFE, colored with StillMade's theme variables. For files and structured data use the `file`, `document`, `table`, `url`, `date` and `color` types and their generated controls and presentations, not JSON text.
87
87
 
88
+ ## Models come from StillMade
89
+
90
+ A Block never names a model, in its capability, its module code or its screen, and never keeps a list of models: the person picks the model on the Step from the models StillMade runs that day, so models StillMade adds or retires later reach the Block with no new version (owner, November 8, 2026). Ask for what the result needs instead, in `settings` (`aspectRatio`, `resolution`, `quality`, `duration`, `generateAudio`): with no model picked StillMade runs its default model, or the first one that makes what was asked, and a value the chosen model does not make falls back to its own. A screen that offers its own model picker draws it from `StillMade.models(operation)` when it opens (each model's settings arrive as data, so a setting StillMade adds later draws too) and passes the picked `id` as `settings.model`. A model StillMade retires runs on the one that replaced it.
91
+
88
92
  ## Dependencies
89
93
 
90
94
  A Block must declare everything it requires and must not assume anything is installed. Portable packages carry no package dependencies (`portable.dependencies` is empty): inline small, license-compatible code and record its license and notice in `manifest.license` and `manifest.provenance`. The copyright holder in the Block's own `provenance.notice` is the person it is made for: replace the placeholder `create` writes with their name, never StillMade, the SDK or yourself. Desktop-only tools are reached solely through declared desktop permissions and the host desktop bridge. If a dependency cannot be delivered through the Block runtime, report the incompatibility instead of assuming the user's machine has it.
package/AGENT_CONTROL.md CHANGED
@@ -127,6 +127,21 @@ returns its exact current dependency vector as ordinal `native-control-signals`.
127
127
  That fallback prevents a changed control revision from silently returning stale
128
128
  persisted state, but named fields remain the optimized manual for small models.
129
129
 
130
+ A mounted module can also pass `undo: {read, restore, same}` to
131
+ `useNativeAgentControls`. With it, every `edit` control that has no undo of its
132
+ own gets one, so a change Chat made can be undone from Chat's change card.
133
+ `read()` returns what the workspace holds now; `same(a, b)` says whether two reads
134
+ hold the same work (default `Object.is`; leave view-only details such as a
135
+ playhead out of it); `restore(before, now)` puts an earlier read back. The undo
136
+ restores the earlier state only while the workspace still holds exactly what the
137
+ edit left. Anything changed since is kept, and the undo says so. The Editor's
138
+ `editor/agentUndo.js` is one example.
139
+
140
+ Screen Blocks get the same undo from the host with nothing to write: a Chat press on
141
+ a marked control is undone by putting each shared view field it changed back to
142
+ its earlier value, on the condition that the field still holds what the press
143
+ left. A press that created a new shared field has no undo.
144
+
130
145
  `pause_app_context` stores the exact visible revision baseline and blocks new app
131
146
  actions. `resume_app_context` does not clear that pause until the tab publishes a
132
147
  matching `manualHandoff.pauseId` for every current surface. Changed shared Blocks
package/FRAME_VIEWS.md CHANGED
@@ -196,6 +196,30 @@ view, and also when the file at that place changed after the view was given it
196
196
  tries again. StillMade hides these buttons wherever it hides the + tile. The SDK
197
197
  preview changes its example input the same way.
198
198
 
199
+ ## What Chat can use
200
+
201
+ The project's Chat reads and uses a frame view's controls the way a person does:
202
+ every labelled field (`<label>`, `aria-label` or `title`), and every button
203
+ with words of its own, by those words. A frame view's screen is built by its
204
+ code as it runs, so no check reads it beforehand; a button marked
205
+ `data-stillmade-action` is offered by that name instead (`run` for the button
206
+ that runs the Block). A button with no words, an icon alone, needs an
207
+ `aria-label` to be offered. Fields inside `data-stillmade-local` are the
208
+ person's own and never offered. Whatever a press starts keeps its own
209
+ approval: spending still asks the person (`StillMade.allowSpending` refuses
210
+ Chat).
211
+
212
+ The one exception is a run of every Step that the person approved on Chat's
213
+ card for the whole project. There StillMade presses the screen's run control
214
+ for them: the button marked `data-stillmade-action="run"`, else the button
215
+ worded as the Block's `manifest.action.label`. Move that mark to whichever
216
+ button moves the job forward now (plan, then build, then save): StillMade
217
+ presses it, waits for the runs it starts, and presses the next one until the
218
+ Step's result is saved. Only while StillMade presses it, the runs it starts,
219
+ and one `StillMade.allowSpending` request for each press, draw on that approval,
220
+ and only while they fit what is left; past it, or at any other time, the person
221
+ is asked as usual.
222
+
199
223
  ## Theming
200
224
 
201
225
  The theme variables from StillMade's design system are always defined:
@@ -205,6 +229,12 @@ rest. Colors written with them follow Light, Dark and White automatically.
205
229
  Frame views are not required to use them; the appearance check reports
206
230
  hard-coded colors as advice instead of refusing the view.
207
231
 
232
+ An app (`"kind": "workspace"`) that wants none of StillMade's style sets
233
+ `"appearance": "none"` in `src/view.config.json`: StillMade then defines none of
234
+ these variables and adds no fonts, page styles or Block kit, so the app's own CSS
235
+ styles everything
236
+ ([An app with its own style](INTERFACE_DESIGN.md#an-app-with-its-own-style)).
237
+
208
238
  A color the check takes is a theme variable, `transparent` or `currentColor`,
209
239
  or a gradient of them (`linear-gradient(to top, var(--bg), transparent)`).
210
240
  `opacity` is not a color and is always allowed. `color-mix()`, `rgba()`,
@@ -30,10 +30,14 @@ operations and credits, StillMade's file picker, no prices on screen, a run
30
30
  button that names what it makes. The mode changes how the screen is laid out
31
31
  and worded; it grants no extra runtime or host access.
32
32
 
33
+ An app can also drop StillMade's style: see
34
+ [An app with its own style](#an-app-with-its-own-style). A job always keeps it.
35
+
33
36
  ## 1. Start from the Block kit
34
37
 
35
38
  StillMade adds the Block kit stylesheet (`packages/design-system/block-kit.css`)
36
- to every Block view, standard and frame. Use its classes and ship little or no
39
+ to every Block view, standard and frame, except an app that sets
40
+ `appearance: "none"`. Use its classes and ship little or no
37
41
  CSS of your own. Every kit rule has zero specificity, so your own CSS always
38
42
  wins. Open `packages/design-system/block-kit.html` in a browser to see every
39
43
  piece in Light, Dark and White.
@@ -99,7 +103,7 @@ place (rule 24).
99
103
  | `sm-media-off` | A picture or clip that cannot show here (on another device, or it did not open): a quiet tile in its own shape (`--sm-photo-ratio`, the tile's shape in a gallery) holding the `image-off` glyph, the reason in `aria-label` and `title`, no words inside. |
100
104
  | `sm-add` | The + tile that adds files to an input: `<button type="button" class="sm-add" data-stillmade-add="listingPhotos" aria-label="Add photos">`. StillMade opens its own picker and saves the files; they arrive through `onInput`. In an `sm-gallery` it takes the tile's shape. |
101
105
  | `sm-scrim` | Words over a photo or video, inside a positioned box such as an `sm-stage`: a see-through shade of the page under them, in every theme. `var(--scrim)` is the same shade for your own rules. |
102
- | `sm-glyph` | A small icon in `currentColor`: `play`, `pause`, `plus`, `close`, `check`, `chevron`, `chevron-left`, `chevron-right`, `upload`, `image`, `image-off`, `video`, `audio`, `text`, `spark`, `info`, `warning`, `spinner`. Works in standard views, which cannot use SVG. |
106
+ | `sm-glyph` | A small icon in `currentColor`: `play`, `pause`, `plus`, `close`, `check`, `chevron`, `chevron-left`, `chevron-right`, `upload`, `download`, `image`, `image-off`, `video`, `audio`, `text`, `spark`, `info`, `warning`, `spinner`. Works in standard views, which cannot use SVG. |
103
107
 
104
108
  **Function first.** When the person building a Block does not ask for a look,
105
109
  use the kit as is: they want it to work and be easy to use. When they name a
@@ -131,6 +135,17 @@ the same single priced button. Pressing a priced button runs at that price; a
131
135
  confirmation appears only when the server's price is higher than the one shown.
132
136
  Do not write credit numbers in the Block.
133
137
 
138
+ A custom view's own run button gets its price the same way (November 8, 2026):
139
+ the view tells StillMade what its next run makes, and StillMade writes the price
140
+ after the button's words, "Generate image · 4 credits". Call
141
+ `StillMade.nextRun({items})` with the `media.generate` items the run will ask for
142
+ (the prompt left out), or `StillMade.nextRun({hosted: ["text.generate"]})` for
143
+ the hosted operations it calls, whenever a choice that changes the price changes.
144
+ StillMade waits until the choices settle, prices them as the run will be priced,
145
+ leaves the button where it is, shows no price while the run works or to a
146
+ viewer, and the Block never sees the number. `StillMade.nextRun(null)` takes it
147
+ off.
148
+
134
149
  ## 3. Speak the job
135
150
 
136
151
  These are StillMade's defaults for every Block, and they apply wherever the
@@ -287,7 +302,9 @@ exception, never unrelated technical UI.
287
302
  segmented control in StillMade); never restyle it to an outline, a tint or
288
303
  the page's background. A locked row (`disabled`, or a person who can only
289
304
  view) keeps its pick filled, fades the other options and does not react to
290
- the pointer.
305
+ the pointer. A picture, or a pick shown by its picture (a thumbnail, a
306
+ shot, a swatch), is a rounded rectangle in the kit's radii, never a circle,
307
+ unless the person asks for one; readiness notes a circle.
291
308
  22. Media that cannot show here (kept on another device, or it did not open)
292
309
  keeps its place as a quiet `sm-media-off` tile in its own shape with the
293
310
  `image-off` glyph, the reason in its `aria-label` and `title`. Never words
@@ -318,8 +335,12 @@ exception, never unrelated technical UI.
318
335
  then "Make video again"); what the result adds (Download, Share) goes to
319
336
  its left. Controls on media (StillMade's player, the full-screen square)
320
337
  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.
338
+ while it is hovered or tapped. Under a rendered video the stage shows its
339
+ shots with their times and the line being said: a video from
340
+ `timeline.render` carries them as `parts` (`shots` with `start`, `end` and
341
+ the `source` each shows, `lines` with `start`, `end` and `text`), and the
342
+ status carries its length. StillMade's own Step pages do the same. An app
343
+ that lays itself out keeps its own toolbar.
323
344
 
324
345
  ```html
325
346
  <section class="sm-stage" data-ratio="9:16">
@@ -332,6 +353,17 @@ exception, never unrelated technical UI.
332
353
  </section>
333
354
  ```
334
355
 
356
+ The Download button needs no code (November 8, 2026): StillMade saves the
357
+ largest picture or clip the stage shows (one the view showed with
358
+ `previewImage` or `previewMedia`) through its own download, under the
359
+ export policy, as the Library does. It works in frame views. An icon fits
360
+ as well: `<button type="button" class="sm-icon" data-stillmade-action="download"
361
+ aria-label="Download" title="Download"><span class="sm-glyph"
362
+ data-glyph="download" aria-hidden="true"></span></button>`. From the view's
363
+ own code, `StillMade.download(media)` saves one picture, clip or sound
364
+ StillMade gave the screen. The run button's price is StillMade's too
365
+ (`StillMade.nextRun`, under "Decide every sentence").
366
+
335
367
  ## 4a. App rules
336
368
 
337
369
  An app (`"kind": "workspace"`) follows these instead of the job-only rules
@@ -353,12 +385,48 @@ An app (`"kind": "workspace"`) follows these instead of the job-only rules
353
385
  view, rare ones in menus. No intros or paragraphs on the surface.
354
386
  6. StillMade's appearance (Light, Dark and White) and the kit's controls
355
387
  wherever they fit; the layout is the app's own. A look the person names wins.
388
+ An app may drop StillMade's style instead (below).
356
389
  7. On a phone the work surface stays usable and the panels fold into sheets or
357
390
  one tool strip.
358
391
  8. What the person makes leaves the app as the Block's outputs (and, while they
359
392
  work, its shared state), so the next Step and the other people in the
360
393
  project get it.
361
394
 
395
+ ### An app with its own style
396
+
397
+ An app that should look like nothing but itself (a photo editor in its own
398
+ dark chrome, a CAD tool with its own palette) sets the view's appearance to
399
+ `"none"`: in `src/view.config.json` for an SDK folder, or `view.appearance` in
400
+ a package.
401
+
402
+ ```json
403
+ {"runtime": "frame", "appearance": "none"}
404
+ ```
405
+
406
+ StillMade then adds none of its style to the view: no theme variables (`--bg`,
407
+ `--fg` and the rest are undefined unless the app defines them), no StillMade
408
+ fonts, no page padding or background, no control styles and no Block kit, in
409
+ the local preview and in the app alike. The page starts from the browser's own
410
+ defaults, as if it were opened on its own (an opaque page in the canvas color
411
+ of its `color-scheme`, so the Step behind it never shows through), and the
412
+ app's CSS styles everything. The preview's appearance picker does not apply to
413
+ it. `<html data-mode>` still says whether the person uses Light, Dark or White,
414
+ for an app that wants to follow it.
415
+
416
+ Only an app may set it: `validatePackage` refuses `appearance: "none"` on a job
417
+ (`"kind": "task"`, or a capability Block with one hosted operation), which
418
+ keeps StillMade's style. The style rules are then the app's own call: its own
419
+ colors and tokens, filters, blending and animations are fine, the appearance
420
+ check passes, and the kit checks on round pictures and the page heading do not
421
+ apply. Everything else stays exactly as it is: shared state and multiplayer
422
+ controls, inputs and outputs, hosted operations and credits, the run button's
423
+ name and the price StillMade writes on it, StillMade's file picker
424
+ (`data-stillmade-add`), StillMade's player on `<video controls>`, the wording
425
+ rules and every security check. A standard (non-frame) view still uses no CSS
426
+ escapes and sets no styles from code: both guard its no-remote-resources rule.
427
+ Layout is separate: `data-stillmade-layout="own"` still decides whether
428
+ StillMade centers or zooms the view.
429
+
362
430
  ## 5. What StillMade checks
363
431
 
364
432
  For an app (`"kind": "workspace"`) only the shared checks run: a file input of
@@ -368,7 +436,9 @@ is kept), and the action-name rules on its run button
368
436
  (`data-stillmade-action="run"`) alone, so "OK" and "Go" are fine on its dialogs
369
437
  and tools. It is never asked for the Block kit page, a control or row count,
370
438
  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
439
+ surface instead of text (a code editor is an app). An app with
440
+ `appearance: "none"` is also not asked for theme colors, rounded rather than
441
+ round pictures, or no page heading. Everything below is the job
372
442
  check list.
373
443
 
374
444
  - Admission rejects a primary textarea of 12 or more rows when no task
@@ -395,7 +465,14 @@ check list.
395
465
  - Admission also warns, and `stillmade-block ready` fails the "UI works" check
396
466
  (DOD-15), when a button says "Run", "Run step" or "Submit", when the
397
467
  interface shows a credit price, or when it has a page heading
398
- (`blockKitProblems`; the failing rules are `BLOCK_KIT_READINESS_RULES`). StillMade's own Block builder also sends back a custom
468
+ (`blockKitProblems`; the failing rules are `BLOCK_KIT_READINESS_RULES`).
469
+ The same goes, standard and frame views alike, for a job page built from the
470
+ kit (`sm-block`) whose result is a picture, clip, sound, asset or document
471
+ and that has no `sm-stage`, or whose own run button
472
+ (`data-stillmade-action="run"`) is not in the stage's own `sm-actions` with
473
+ an `sm-status` beside it on the stage (rule 24; November 8, 2026). A page not
474
+ built from the kit is held to the kit rule instead, and a frame view that
475
+ builds its stage in code is not checked by the source. StillMade's own Block builder also sends back a custom
399
476
  view that is not built from `sm-block`, unless the person asked for their
400
477
  own look (`appearance: "original"`).
401
478
  - Admission warns, and readiness lists a "Wording" limitation, when a button
package/MODULES.md CHANGED
@@ -54,7 +54,7 @@ against the manifest's port types.
54
54
  | --- | --- |
55
55
  | `input` | The validated input values (the same object as the first argument). |
56
56
  | `signal` | An `AbortSignal` that fires when the person cancels. |
57
- | `progress(value, label)` | Reports progress from 0 to 1 with a short label. Each report extends the run limit. |
57
+ | `progress(value, label, items)` | Reports progress from 0 to 1 with a short label. Each report extends the run limit. `items` (`{done, total}`, optional) says how many of the run's items are finished, such as pictures made; StillMade shows it ("9 of 14") while Chat runs the project's Steps. |
58
58
  | `log(...values)` | Adds a line to the run log (up to 500 lines). |
59
59
  | `asset(path)` | A copy of one of the module's own files, such as a `.wasm` build, as an `ArrayBuffer`. |
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. |
@@ -117,7 +117,7 @@ const { value, failures } = await stillmade.actions.run({
117
117
  resultPort: null,
118
118
  request: { items: [
119
119
  { key: 'front', operation: 'image', prompt: `The front of ${input.address} at dusk`,
120
- settings: { model: 'nano-banana-pro', aspectRatio: '16:9' } },
120
+ settings: { aspectRatio: '16:9' } },
121
121
  { key: 'tour', operation: 'speech', prompt: input.script },
122
122
  ] },
123
123
  });