stillmade-sdk 0.1.42 → 0.1.43
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 +6 -8
- package/AGENTS.md +15 -10
- package/FRAME_VIEWS.md +113 -0
- package/INTERFACE_DESIGN.md +62 -22
- package/MOBILE_UI.md +4 -2
- package/MODULES.md +152 -6
- package/PASTE_TO_LLM.md +35 -25
- package/README.md +3 -2
- package/SDK.md +994 -550
- package/UI_AESTHETIC.md +22 -2
- package/blocks/generate/package.js +1 -0
- package/blocks/generate/versions/1.0.0/package.js +463 -0
- package/docs/build/audio-to-editor.md +36 -0
- package/docs/build/block-builder-contract.md +150 -0
- package/docs/build/comfyui.md +227 -0
- package/docs/build/concepts.md +40 -0
- package/docs/build/context.md +159 -0
- package/docs/build/cookbook.md +57 -0
- package/docs/build/custom-interface.md +617 -0
- package/docs/build/data-types.md +83 -0
- package/docs/build/frame-views.md +259 -0
- package/docs/build/generate-media.md +59 -0
- package/docs/build/github-applications.md +314 -0
- package/docs/build/hosted-images.md +214 -0
- package/docs/build/hosted-music.md +39 -0
- package/docs/build/hosted-speech.md +157 -0
- package/docs/build/hosted-text.md +246 -0
- package/docs/build/image-description.md +49 -0
- package/docs/build/interface-design.md +343 -0
- package/docs/build/javascript.md +63 -0
- package/docs/build/local-preview.md +61 -0
- package/docs/build/media-analysis.md +27 -0
- package/docs/build/media.md +400 -0
- package/docs/build/mobile-ui.md +106 -0
- package/docs/build/modules.md +487 -0
- package/docs/build/original-blocks.md +70 -0
- package/docs/build/outside-apis.md +128 -0
- package/docs/build/production-context-templates.md +12 -0
- package/docs/build/project-storage.md +94 -0
- package/docs/build/quickstart.md +48 -0
- package/docs/build/recipes.md +103 -0
- package/docs/build/script-handoff.md +45 -0
- package/docs/build/script-writer.md +34 -0
- package/docs/build/state.md +223 -0
- package/docs/build/testing.md +112 -0
- package/docs/build/timeline-edits.md +116 -0
- package/docs/build/timeline-proposals.md +76 -0
- package/docs/build/transcription.md +59 -0
- package/docs/build/triggers.md +59 -0
- package/docs/build/tutorial.md +52 -0
- package/docs/build/typescript.md +34 -0
- package/docs/build/video-generation.md +61 -0
- package/docs/build/web-reading.md +37 -0
- package/docs/build/with-your-ai.md +27 -0
- package/docs/changelog.md +9 -0
- package/docs/creators.md +21 -0
- package/docs/distribute/discovery.md +43 -0
- package/docs/distribute/imports.md +58 -0
- package/docs/distribute/publishing.md +29 -0
- package/docs/distribute/sdk-versions.md +36 -0
- package/docs/distribute/selling.md +14 -0
- package/docs/distribute/teams.md +60 -0
- package/docs/distribute/versioning.md +28 -0
- package/docs/examples.md +23 -0
- package/docs/gallery.md +26 -0
- package/docs/index.md +50 -0
- package/docs/native-mcp.md +307 -0
- package/docs/project-types/automation.md +43 -0
- package/docs/project-types/batches.md +50 -0
- package/docs/project-types/build.md +42 -0
- package/docs/project-types/completion.md +15 -0
- package/docs/project-types/conditions.md +21 -0
- package/docs/project-types/hosted-review.md +115 -0
- package/docs/project-types/onboarding.md +75 -0
- package/docs/project-types/running.md +309 -0
- package/docs/project-types/testing.md +72 -0
- package/docs/reference/application-artifacts.md +87 -0
- package/docs/reference/authoring-guide.md +134 -0
- package/docs/reference/browser-applications.md +267 -0
- package/docs/reference/capabilities.md +45 -0
- package/docs/reference/cli.md +71 -0
- package/docs/reference/connection-api.md +59 -0
- package/docs/reference/cooperative-jobs.md +13 -0
- package/docs/reference/desktop-capabilities.md +172 -0
- package/docs/reference/desktop-execution.md +77 -0
- package/docs/reference/errors.md +233 -0
- package/docs/reference/execution.md +800 -0
- package/docs/reference/first-party-blocks.md +40 -0
- package/docs/reference/generation-models.md +59 -0
- package/docs/reference/limits.md +306 -0
- package/docs/reference/manifest-kinds-controls.md +36 -0
- package/docs/reference/manifest.md +181 -0
- package/docs/reference/operations.md +36 -0
- package/docs/reference/package-jobs.md +35 -0
- package/docs/reference/parity.md +55 -0
- package/docs/reference/permissions.md +86 -0
- package/docs/reference/ports.md +26 -0
- package/docs/reference/types.md +268 -0
- package/docs/reference/universal-resolver.md +303 -0
- package/docs/reference/view-bridge.md +60 -0
- package/docs/reference/view-rules.md +15 -0
- package/docs/reference/workspace-sync.md +25 -0
- package/docs/sdk.md +34 -0
- package/docs/tools/block-remix.md +211 -0
- package/docs/tools/llm.md +2213 -0
- package/docs/tools/repository-adaptation.md +613 -0
- package/examples/check-clip.stillmade.json +4 -1
- package/examples/generate-video.stillmade.json +6 -2
- package/examples/research-topic.stillmade.json +5 -1
- package/examples/text-workflow.stillmade.json +3 -32
- package/examples/timeline-polish.stillmade.json +11 -3
- package/examples/transcribe-audio.stillmade.json +11 -3
- package/package.json +1 -1
- package/packages/block-cli/cli.js +13 -6
- package/packages/block-cli/dev-host/assets/host.js +76 -38
- package/packages/block-cli/dev-host/assets/index.css +1 -1
- package/packages/block-cli/format.js +1 -1
- package/packages/block-cli/templates.js +31 -13
- package/packages/block-cli/type-packages.js +119 -0
- package/packages/block-platform/block-readiness.js +5 -0
- package/packages/block-platform/canvas.js +2 -1
- package/packages/block-platform/catalog.js +27 -48
- package/packages/block-platform/native-host-inventory.js +0 -226
- package/packages/block-platform/plain-descriptions.js +1 -25
- package/packages/block-platform/project-type-starters.js +13 -53
- package/packages/block-platform/script-handoff.js +2 -4
- package/packages/block-platform/type-workspace.js +2 -0
- package/packages/block-sdk/appearance.js +3 -1
- package/packages/block-sdk/block-tier.js +1 -1
- package/packages/block-sdk/builder-contract.js +10 -8
- package/packages/block-sdk/capabilities.js +1 -1
- package/packages/block-sdk/contracts.js +6 -2
- package/packages/block-sdk/first-party-identities.js +1 -84
- package/packages/block-sdk/first-party-packages.js +3 -85
- package/packages/block-sdk/generation-catalog.js +15 -3
- package/packages/block-sdk/index.d.ts +2 -1
- package/packages/block-sdk/media-analysis-example.js +1 -1
- package/packages/block-sdk/mock-host.js +7 -1
- package/packages/block-sdk/module-host-calls.js +35 -10
- package/packages/block-sdk/module-hosted.js +15 -2
- package/packages/block-sdk/module-media-access.js +71 -0
- package/packages/block-sdk/module-node.js +1 -1
- package/packages/block-sdk/portable-media-actions.js +1 -1
- package/packages/block-sdk/runtime.js +1 -1
- package/packages/block-sdk/timeline-proposal-example.js +1 -1
- package/packages/block-sdk/transcription-example.js +1 -1
- package/packages/block-sdk/video-generation-example.js +1 -1
- package/packages/block-sdk/view-bridge.js +4 -1
- package/packages/block-sdk/view-design.js +17 -14
- package/packages/block-sdk/web-example.js +1 -1
- package/packages/design-system/block-kit.css +48 -12
- package/packages/design-system/block-kit.html +3 -2
- package/blocks/mcp-motion-planner/versions/1.1.0/package.js +0 -97
- package/blocks/motion-designer/versions/1.0.1/package.js +0 -173318
- package/blocks/motion-designer/versions/1.0.2/package.js +0 -173318
- package/blocks/motion-frame-review/versions/1.1.1/package.js +0 -465
- package/blocks/motion-frame-review/versions/1.1.2/package.snapshot.js +0 -572
- package/blocks/narration/package.js +0 -1
- package/blocks/narration/versions/1.0.0/package.js +0 -221
- package/blocks/narration/versions/1.0.1/package.js +0 -221
- package/blocks/native/sm.animated-scene/versions/2.0.0/package.js +0 -475
- package/blocks/native/sm.animated-scene/versions/2.1.0/package.js +0 -498
- package/blocks/native/sm.animated-scene/versions/2.2.0/package.js +0 -524
- package/blocks/native/sm.animated-scene/versions/2.3.0/package.js +0 -618
- package/blocks/native/sm.animated-scene/versions/2.3.1/package.js +0 -618
- package/blocks/native/sm.animated-scene/versions/2.3.2/package.js +0 -723
- package/blocks/native/sm.animated-scene/versions/2.3.3/package.js +0 -723
- package/blocks/native/sm.animated-scene/versions/2.3.4/package.js +0 -676
- package/blocks/native/sm.animated-scene/versions/2.3.5/package.js +0 -693
- package/blocks/native/sm.animated-scene/versions/2.3.6/package.js +0 -700
- package/blocks/native/sm.animated-scene/versions/2.3.7/package.js +0 -747
- package/blocks/native/sm.animated-scene/versions/2.3.8/package.js +0 -769
- package/blocks/native/sm.animated-scene/versions/2.3.9/package.js +0 -769
- package/blocks/native/sm.animated-scene-assistant/versions/1.0.0/package.js +0 -183
- package/blocks/native/sm.blueprint/versions/2.0.0/package.js +0 -358
- package/blocks/native/sm.blueprint/versions/2.1.0/package.js +0 -358
- package/blocks/native/sm.blueprint/versions/2.1.1/package.js +0 -358
- package/blocks/native/sm.blueprint/versions/2.1.2/package.js +0 -358
- package/blocks/native/sm.blueprint/versions/2.1.3/package.js +0 -381
- package/blocks/native/sm.blueprint/versions/2.1.4/package.js +0 -381
- package/blocks/native/sm.blueprint/versions/2.1.5/package.js +0 -339
- package/blocks/native/sm.blueprint/versions/2.1.6/package.js +0 -356
- package/blocks/native/sm.blueprint/versions/2.1.7/package.js +0 -363
- package/blocks/native/sm.blueprint/versions/2.1.8/package.js +0 -410
- package/blocks/native/sm.blueprint/versions/2.1.9/package.js +0 -422
- package/blocks/native/sm.blueprint-assistant/versions/1.0.0/package.js +0 -172
- package/blocks/native/sm.chat/versions/2.0.0/package.js +0 -144
- package/blocks/native/sm.chat/versions/2.0.1/package.js +0 -97
- package/blocks/native/sm.chat/versions/2.0.2/package.js +0 -100
- package/blocks/native/sm.chat/versions/2.0.3/package.js +0 -100
- package/blocks/native/sm.continue-if/versions/1.0.0/package.js +0 -168
- package/blocks/native/sm.describe-media/versions/2.0.0/package.js +0 -153
- package/blocks/native/sm.describe-media/versions/2.0.1/package.js +0 -156
- package/blocks/native/sm.describe-media/versions/2.1.0/package.js +0 -140
- package/blocks/native/sm.image-editor/versions/2.0.0/package.js +0 -183
- package/blocks/native/sm.image-editor/versions/2.0.1/package.js +0 -190
- package/blocks/native/sm.new-items/versions/1.0.0/package.js +0 -191
- package/blocks/native/sm.pick-photos/versions/1.0.0/package.js +0 -334
- package/blocks/native/sm.quality-audit/versions/1.0.0/package.js +0 -192
- package/blocks/native/sm.quality-audit/versions/1.0.1/package.js +0 -192
- package/blocks/native/sm.quality-audit/versions/1.0.2/package.js +0 -195
- package/blocks/native/sm.research/versions/2.0.0/package.js +0 -175
- package/blocks/native/sm.research/versions/2.0.1/package.js +0 -184
- package/blocks/native/sm.research/versions/2.0.2/package.js +0 -187
- package/blocks/native/sm.script/versions/2.0.0/package.js +0 -144
- package/blocks/native/sm.script/versions/2.1.0/package.js +0 -144
- package/blocks/native/sm.script/versions/2.1.1/package.js +0 -144
- package/blocks/native/sm.script/versions/2.1.2/package.js +0 -105
- package/blocks/native/sm.script/versions/2.1.3/package.js +0 -152
- package/blocks/native/sm.script/versions/2.1.4/package.js +0 -156
- package/blocks/native/sm.script/versions/2.1.5/package.js +0 -156
- package/blocks/native/sm.shot-plan/versions/2.0.0/package.js +0 -301
- package/blocks/native/sm.shot-plan/versions/2.1.0/package.js +0 -528
- package/blocks/native/sm.shot-plan/versions/2.1.1/package.js +0 -528
- package/blocks/native/sm.shot-plan/versions/2.1.2/package.js +0 -528
- package/blocks/native/sm.shot-plan/versions/2.1.3/package.js +0 -536
- package/blocks/native/sm.shot-plan/versions/2.2.0/package.js +0 -800
- package/blocks/native/sm.shot-plan/versions/2.2.1/package.js +0 -920
- package/blocks/native/sm.shot-plan-assistant/versions/1.0.0/package.js +0 -173
- package/blocks/native/sm.stock-search/versions/2.0.0/package.js +0 -174
- package/blocks/native/sm.thumbnail/versions/2.0.0/package.js +0 -137
- package/blocks/native/sm.thumbnail/versions/2.0.1/package.js +0 -140
- package/blocks/native/sm.transcribe/versions/2.0.0/package.js +0 -163
- package/blocks/native/sm.transcribe/versions/2.0.1/package.js +0 -168
- package/blocks/native/sm.whiteboard-assistant/versions/1.0.0/package.js +0 -175
- package/blocks/native/sm.youtube/versions/2.0.0/package.js +0 -217
- package/blocks/occasion-story/package.js +0 -1
- package/blocks/occasion-story/versions/1.0.0/package.js +0 -1658
- package/blocks/occasion-story/versions/1.0.1/package.js +0 -1699
- package/blocks/occasion-story/versions/1.0.2/package.js +0 -1682
- package/blocks/photo-reel-composer/versions/1.0.0/package.js +0 -3043
- package/blocks/photo-reel-composer/versions/1.0.1/package.js +0 -3026
- package/blocks/photo-reel-composer/versions/1.0.2/package.js +0 -4149
- package/blocks/product-ad-variants/versions/1.0.0/package.js +0 -2911
- package/blocks/product-launch-director/versions/1.0.0/package.js +0 -103
- package/blocks/release-visuals/package.js +0 -1
- package/blocks/release-visuals/versions/1.0.0/package.js +0 -1492
- package/blocks/release-visuals/versions/1.0.1/package.js +0 -1517
- package/blocks/release-visuals/versions/1.0.2/package.js +0 -1500
- package/blocks/screen-recorder/package.js +0 -1
- package/blocks/screen-recorder/versions/1.0.0/package.js +0 -223
- package/blocks/screen-recorder/versions/1.0.1/package.js +0 -223
- package/blocks/short-form-finish/package.js +0 -1
- package/blocks/short-form-finish/versions/1.0.0/package.js +0 -1043
- package/blocks/short-form-finish/versions/1.0.1/package.js +0 -1043
- package/blocks/short-form-finish/versions/1.0.2/package.js +0 -1043
- package/blocks/short-form-finish/versions/1.0.3/package.js +0 -1026
- package/examples/saas-product-launch-reviewed-source.stillmade.json +0 -383
- package/examples/saas-product-launch.stillmade.json +0 -304
- package/packages/block-platform/dealer-inventory-video-project-type.js +0 -38
- package/packages/block-platform/first-revenue-project-types.js +0 -46
- package/packages/block-platform/fixture-starters.js +0 -13
- package/packages/block-platform/launch-project-source.js +0 -10
- package/packages/block-platform/launch-project.js +0 -30
- package/packages/block-platform/motion-project-types.js +0 -55
- package/packages/block-platform/motion-starters.js +0 -14
- package/packages/block-platform/product-ad-variants-project-type.js +0 -30
- package/packages/block-platform/product-launch-updated.js +0 -90
- package/packages/block-platform/revenue-review-project-types.js +0 -36
- package/packages/block-platform/revenue-review-starters.js +0 -13
- package/packages/block-platform/script-writer.js +0 -29
- package/packages/block-platform/website-source-block.js +0 -14
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Data types: files, documents, tables, links, dates and colors
|
|
2
|
+
|
|
3
|
+
Ports can carry general files and structured data, not only media and text.
|
|
4
|
+
Each type has a checked value shape, a generated control and a result layout,
|
|
5
|
+
so a Block that declares them needs no custom view.
|
|
6
|
+
|
|
7
|
+
| Type | Value | Generated control | Default result layout |
|
|
8
|
+
| --- | --- | --- | --- |
|
|
9
|
+
| `file` | `{kind: "file", assetId, versionId, mimeType, url?, name?, bytes?}`; `mimeType` is `application/pdf`, `text/plain`, `text/csv`, `text/markdown`, `application/json` or `application/zip` | `file` (upload) | `download` |
|
|
10
|
+
| `document` | `{schemaVersion: 1, format: "markdown" \| "plain", text, title?}`, up to 1,000,000 characters | `richtext` | `document` |
|
|
11
|
+
| `table` | `{columns: [name], rows: [{name: text \| number \| boolean \| null}]}`, up to 500 columns and 100,000 rows | `grid` | `table` (with CSV download) |
|
|
12
|
+
| `url` | An absolute `http` or `https` address without credentials | `url` | a link |
|
|
13
|
+
| `date` | ISO 8601: `2026-10-09` or `2026-10-09T14:30` (seconds and an offset optional) | `date` (`time: true` for date and time) | a formatted date |
|
|
14
|
+
| `color` | `#rrggbb` or `#rrggbbaa` | `color` | a swatch |
|
|
15
|
+
|
|
16
|
+
Lists of these types (`file[]`, `url[]`, `date[]`, `color[]`) work like other
|
|
17
|
+
lists; the `list` control edits `text[]`, `number[]`, `integer[]`, `url[]`,
|
|
18
|
+
`date[]` and `color[]` item by item.
|
|
19
|
+
|
|
20
|
+
Output presentations in `manifest.ui` choose a layout for an output:
|
|
21
|
+
`{control: "table", port}`, `{control: "document", port}` (a `document` or
|
|
22
|
+
Markdown `text`), `{control: "chart", port, chart: "bar" | "line", x, y}` (a
|
|
23
|
+
`table` with optional column names, or a `number[]`), `{control: "code", port,
|
|
24
|
+
language}` (`text`, `json` or `object`), `{control: "player", port}` (`audio` or
|
|
25
|
+
`video`) and `{control: "download", port}` (`file`, `file[]` or `file-bundle`).
|
|
26
|
+
Each control is checked against its port's type when the manifest is
|
|
27
|
+
validated. Layouts show Block data as text: links in a document are displayed,
|
|
28
|
+
not followed, and downloads go through the host's export policy.
|
|
29
|
+
|
|
30
|
+
### Files
|
|
31
|
+
|
|
32
|
+
People upload files to a `file` input from the Block's controls. The host
|
|
33
|
+
checks the extension, the declared type, the size (50 MB) and the bytes (a PDF
|
|
34
|
+
or ZIP signature, valid UTF-8 text, parseable JSON) before the Block receives a
|
|
35
|
+
saved reference. Module Blocks read the bytes with
|
|
36
|
+
`stillmade.files.read(input.script)` and save new files with
|
|
37
|
+
`stillmade.files.write(bytes, {mediaType: "text/csv", name: "shots.csv"})`,
|
|
38
|
+
which returns a `file` value. Files a person uploaded to a Block, or a Block
|
|
39
|
+
saved, are indexed in project context as `files` (`file[]`, permission
|
|
40
|
+
`context.files.read`), apart from media so media lists stay media.
|
|
41
|
+
|
|
42
|
+
### Helpers
|
|
43
|
+
|
|
44
|
+
`@stillmade/block-sdk/data` (also exported from the main entry) has the checks
|
|
45
|
+
and builders: `isFileValue`, `isDocumentValue`, `isTableValue`, `isUrlValue`,
|
|
46
|
+
`isDateValue`, `isColorValue`, `createTable(columns, rows)`,
|
|
47
|
+
`createDocument(text, {format, title})`, `tableToCsv(table)`,
|
|
48
|
+
`fileFormatFor(name)`, `checkFileSignature(bytes, mimeType)`, and the
|
|
49
|
+
`DATA_VALUE_LIMITS`, `FILE_FORMATS`, `FILE_MEDIA_TYPES` and `DOCUMENT_FORMATS`
|
|
50
|
+
tables. `IMPORT_FORMATS` lists every upload the host stores (media and files),
|
|
51
|
+
and `inspectMediaImportFile(file, {kinds: ["file"]})` checks a chosen file.
|
|
52
|
+
|
|
53
|
+
### Conversions
|
|
54
|
+
|
|
55
|
+
Connections convert between these types with host-owned conversions, version 1:
|
|
56
|
+
|
|
57
|
+
| Conversion | From | To |
|
|
58
|
+
| --- | --- | --- |
|
|
59
|
+
| `text-to-url`, `url-to-text` | `text` | `url` (checked), and back |
|
|
60
|
+
| `text-to-table`, `table-to-text` | CSV `text` | `table`, and back to CSV |
|
|
61
|
+
| `object-to-table`, `table-to-object` | an `object` shaped as a table (for example from `csv-to-table`) | `table`, and back |
|
|
62
|
+
| `text-to-document`, `document-to-text` | `text` | a plain `document`, and back |
|
|
63
|
+
| `shots-to-shot-plan` | `shot[]` | the Shots workspace's version 1 `shot-plan` |
|
|
64
|
+
|
|
65
|
+
A shot list reaches the Shots workspace when the output declares the
|
|
66
|
+
workspace's meaning: `{"type": "shot[]", "semantic": "production_shot_plan"}`.
|
|
67
|
+
|
|
68
|
+
Shots 2.2.0 and Image Panels 2.4.0 take narration from an earlier Step. A
|
|
69
|
+
script whose output declares another meaning (or none), script-named `text`, or
|
|
70
|
+
a transcript reaches their `narrationScript` and `narrationTiming` inputs
|
|
71
|
+
through `script-as-narration`, `text-as-narration` and
|
|
72
|
+
`transcript-as-narration-timing` (version 1, words unchanged; listed in
|
|
73
|
+
`NARRATION_ADAPTERS`, not `ADAPTERS`). These are never
|
|
74
|
+
chosen by matching: StillMade pins one on the connection when such a Step is
|
|
75
|
+
added or replaced, or when the person picks "Use <Step>'s script". Declare
|
|
76
|
+
`"semantic": "narration_script"` on a narration output to connect without one.
|
|
77
|
+
|
|
78
|
+
### Example: PDF to shot list
|
|
79
|
+
|
|
80
|
+
`examples/module-pdf-shot-list` is a module Block that takes an uploaded PDF,
|
|
81
|
+
reads its text with pdf.js (bundled, its worker code imported directly so
|
|
82
|
+
nothing is fetched), plans the shots with one `text.generate` call that has a
|
|
83
|
+
JSON schema, and returns a `table` and a `shot[]` the Shots workspace accepts.
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
# Frame views: any interface code
|
|
2
|
+
|
|
3
|
+
# Frame views: any interface code
|
|
4
|
+
|
|
5
|
+
A frame view (`"runtime": "frame"` in the view) is an interface written with
|
|
6
|
+
ordinary web code: React, Svelte, Vue or Preact bundles, SVG, canvas and
|
|
7
|
+
WebGL, pointer capture and drag, timers, loops, recursion, classes and Web
|
|
8
|
+
Workers. Use it when the reviewed subset of standard views is too small for
|
|
9
|
+
the interface you want.
|
|
10
|
+
|
|
11
|
+
## Folder layout
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
my-block/
|
|
15
|
+
stillmade.block.json
|
|
16
|
+
src/run.js or another runtime (recipe, module, capability)
|
|
17
|
+
src/view.html markup, for example <div id="root"></div>
|
|
18
|
+
src/view.css styles; use StillMade's theme variables
|
|
19
|
+
src/view.js ONE classic script: bundle with --format=iife
|
|
20
|
+
src/view.config.json {"runtime": "frame"}
|
|
21
|
+
tests/fixtures.json
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
`src/view.config.json` may also set `"appearance"` and `"files"` (assets, see
|
|
25
|
+
below). Bundle npm dependencies into `src/view.js` as an IIFE, for example:
|
|
26
|
+
|
|
27
|
+
```sh
|
|
28
|
+
esbuild src/view.jsx --bundle --format=iife --minify --jsx=automatic \
|
|
29
|
+
--define:process.env.NODE_ENV='"production"' --outfile=src/view.js
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Limits: markup and each stylesheet up to 256 KiB, `view.js` up to 4 MiB,
|
|
33
|
+
and up to 32 asset files with 8 MiB in total.
|
|
34
|
+
|
|
35
|
+
## The `StillMade` object
|
|
36
|
+
|
|
37
|
+
Frame views get the same `StillMade` object as standard views: `input` and
|
|
38
|
+
`onInput`, `run`, `useOutput`, `getShared`, `onShared`, `updateShared`,
|
|
39
|
+
`bindShared`, `connectDocument`, `previewImage`, `previewMedia`, `render`
|
|
40
|
+
and the rest of the interface bridge. In addition:
|
|
41
|
+
|
|
42
|
+
| Member | What it does |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| `StillMade.asset(path)` | A `blob:` URL for one of the view's asset files, for `<img>`, `new FontFace()` or `<video>`. |
|
|
45
|
+
| `StillMade.assetBytes(path)` | A copy of an asset file's bytes as an `ArrayBuffer`. |
|
|
46
|
+
|
|
47
|
+
`StillMade.live` gives any view the camera and microphone as they happen, after the
|
|
48
|
+
person presses Start (see Live camera and microphone in
|
|
49
|
+
[Desktop capabilities](DESKTOP_CAPABILITIES.md)). A frame view can hand the frames to a
|
|
50
|
+
Worker it starts from a `blob:` URL.
|
|
51
|
+
|
|
52
|
+
Shared state works as in every view: keep each independently edited value in
|
|
53
|
+
its own field (for example `point0`, `point1`) so two people editing
|
|
54
|
+
different values never conflict.
|
|
55
|
+
|
|
56
|
+
## Adding files to an input
|
|
57
|
+
|
|
58
|
+
A one-page Block shows its input's files on its own screen as tiles and adds
|
|
59
|
+
more there. Never draw an upload box or an `<input type="file">` of your own:
|
|
60
|
+
the + tile asks StillMade, which opens its own file picker and saves the
|
|
61
|
+
files exactly as the Step's own tiles do (working copies, files kept on the
|
|
62
|
+
person's device, the limits and the error messages).
|
|
63
|
+
|
|
64
|
+
```html
|
|
65
|
+
<ul class="sm-gallery" data-size="small" id="photos">
|
|
66
|
+
<!-- one <li> per photo, drawn from onInput -->
|
|
67
|
+
<li><button type="button" class="sm-add" data-stillmade-add="listingPhotos"
|
|
68
|
+
aria-label="Add photos" title="Add photos"></button></li>
|
|
69
|
+
</ul>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`data-stillmade-add` names a declared `image`, `video`, `audio`, `asset` or
|
|
73
|
+
`file` input, or a list of one of them (`image[]`). It needs no code: a click
|
|
74
|
+
or key press on the tile opens StillMade's picker. A list gets every chosen
|
|
75
|
+
file added; a single input takes the first. The saved values reach the view
|
|
76
|
+
the way every input does, so draw the tiles from `onInput`:
|
|
77
|
+
|
|
78
|
+
```js
|
|
79
|
+
StillMade.onInput(async input => {
|
|
80
|
+
for (const photo of input.listingPhotos || []) {
|
|
81
|
+
const preview = await StillMade.previewImage(photo); // display copy
|
|
82
|
+
// ...add an <li><img src="preview.url"></li> before the + tile
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
From your own button, call `await StillMade.addFiles('listingPhotos')` inside
|
|
88
|
+
its click handler. It resolves to `{added}` (0 when the person closes the
|
|
89
|
+
picker) and rejects with a message for an undeclared input, an input that is
|
|
90
|
+
not a file input, an input an earlier Step fills, a person who can only view
|
|
91
|
+
the project, or a call that does not come from a click or key press in the
|
|
92
|
+
view. The view never receives a `File` or a `blob:` URL, only the saved
|
|
93
|
+
values. StillMade hides `[data-stillmade-add]` tiles from viewers and for
|
|
94
|
+
inputs an earlier Step fills. In the SDK preview, the tile opens your
|
|
95
|
+
computer's file chooser and the preview keeps the files like your own picks.
|
|
96
|
+
|
|
97
|
+
### Removing and reordering files
|
|
98
|
+
|
|
99
|
+
A list input's files are removed and put in order on the same screen, so a
|
|
100
|
+
person drops a bad photo or sets the tour's order without leaving the Block.
|
|
101
|
+
Put the buttons in each tile, with `data-index` (from 0) naming its place in
|
|
102
|
+
the list `onInput` gave you:
|
|
103
|
+
|
|
104
|
+
```html
|
|
105
|
+
<li>
|
|
106
|
+
<img src="..." alt="Photo 3">
|
|
107
|
+
<span class="sm-tile-tools">
|
|
108
|
+
<button type="button" data-stillmade-move="listingPhotos" data-index="2" data-to="1"
|
|
109
|
+
aria-label="Move earlier" title="Move earlier"><span class="sm-glyph" data-glyph="chevron-left" aria-hidden="true"></span></button>
|
|
110
|
+
<button type="button" data-stillmade-move="listingPhotos" data-index="2" data-to="3"
|
|
111
|
+
aria-label="Move later" title="Move later"><span class="sm-glyph" data-glyph="chevron-right" aria-hidden="true"></span></button>
|
|
112
|
+
<button type="button" data-stillmade-remove="listingPhotos" data-index="2"
|
|
113
|
+
aria-label="Remove" title="Remove"><span class="sm-glyph" data-glyph="close" aria-hidden="true"></span></button>
|
|
114
|
+
</span>
|
|
115
|
+
</li>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`data-stillmade-remove` removes the file at `data-index`; `data-stillmade-move`
|
|
119
|
+
moves it to the place `data-to`. A `data-to` past either end of the list does
|
|
120
|
+
nothing, so the first tile's Move earlier is harmless (disable it if you like).
|
|
121
|
+
From your own code, call `await StillMade.removeFile('listingPhotos', 2)` or
|
|
122
|
+
`await StillMade.moveFile('listingPhotos', 2, 1)` inside a click handler; each
|
|
123
|
+
resolves to `{files}`, how many the list now holds. StillMade changes the
|
|
124
|
+
Step's list as its own tile buttons do, keeping each saved file's upload record
|
|
125
|
+
with it, and the new list reaches the view through `onInput`: redraw the tiles
|
|
126
|
+
from it, never from your own copy.
|
|
127
|
+
|
|
128
|
+
Both work only on list inputs (`image[]`, `video[]`, `audio[]`, `asset[]`,
|
|
129
|
+
`file[]`); `addFiles` replaces a single input's file. They are refused, as
|
|
130
|
+
`addFiles` is, for an undeclared input, an input an earlier Step fills, a
|
|
131
|
+
viewer, Chat and a call that does not come from a click or key press in the
|
|
132
|
+
view, and also when the file at that place changed after the view was given it
|
|
133
|
+
(another person edited the list): the view gets the current list and the person
|
|
134
|
+
tries again. StillMade hides these buttons wherever it hides the + tile. The SDK
|
|
135
|
+
preview changes its example input the same way.
|
|
136
|
+
|
|
137
|
+
## Theming
|
|
138
|
+
|
|
139
|
+
The theme variables from StillMade's design system are always defined:
|
|
140
|
+
`var(--bg)`, `var(--bg-elev-1)`, `var(--fg)`, `var(--fg-muted)`,
|
|
141
|
+
`var(--accent)`, `var(--border-tok)`, `var(--divider)`, `var(--r-3)` and the
|
|
142
|
+
rest. Colors written with them follow Light, Dark and White automatically.
|
|
143
|
+
Frame views are not required to use them; the appearance check reports
|
|
144
|
+
hard-coded colors as advice instead of refusing the view.
|
|
145
|
+
|
|
146
|
+
A color the check takes is a theme variable, `transparent` or `currentColor`,
|
|
147
|
+
or a gradient of them (`linear-gradient(to top, var(--bg), transparent)`).
|
|
148
|
+
`opacity` is not a color and is always allowed. `color-mix()`, `rgba()`,
|
|
149
|
+
`#rrggbbaa` and other written colors are what it reports. For words over a
|
|
150
|
+
photo or video, use the kit's shade: `var(--scrim)` is the page's background,
|
|
151
|
+
partly see-through, in every theme, and `class="sm-scrim"` lays it over the
|
|
152
|
+
bottom of a positioned box (an `sm-stage`) under the words inside it:
|
|
153
|
+
|
|
154
|
+
```html
|
|
155
|
+
<figure class="sm-stage" data-fill>
|
|
156
|
+
<img src="..." alt="">
|
|
157
|
+
<figcaption class="sm-scrim">12 Elm Street · 3 bed</figcaption>
|
|
158
|
+
</figure>
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
`--scrim` and `sm-scrim` are the only shade a Block uses; StillMade's own
|
|
162
|
+
`--scrim-top` and `--scrim-bottom` (theme.css) are for its pages and the check
|
|
163
|
+
reports them.
|
|
164
|
+
|
|
165
|
+
## Layout
|
|
166
|
+
|
|
167
|
+
StillMade zooms a view to fill the space its Step gives it (up to 150%), and
|
|
168
|
+
Ctrl/Cmd +, - and 0 size the view while it has focus. It never centers a frame
|
|
169
|
+
view; a standard view narrower than its Step is centered by its margins.
|
|
170
|
+
|
|
171
|
+
An app that lays itself out (a full-size canvas or WebGL, its own scroll, pan
|
|
172
|
+
or zoom, its own Ctrl/Cmd +/- keys, as in a CAD or drawing tool) puts
|
|
173
|
+
`data-stillmade-layout="own"` on its outermost element:
|
|
174
|
+
|
|
175
|
+
```html
|
|
176
|
+
<div id="root" data-stillmade-layout="own"></div>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
StillMade then never centers or zooms it and leaves Ctrl/Cmd +, - and 0 to the
|
|
180
|
+
app. Without the attribute StillMade also stays out of the way when the view
|
|
181
|
+
looks like an app: no page padding, a clipped page, a root as tall as the frame,
|
|
182
|
+
fixed over half of it or scrolling over half of it, a canvas, SVG or
|
|
183
|
+
`touch-action: none` surface over 40% of it, or a canvas or SVG of 300x200 or
|
|
184
|
+
more with `touch-action: none` (as Three.js's controls set it). Mark the root
|
|
185
|
+
anyway, in `view.html` rather than from code: StillMade reads it before the view
|
|
186
|
+
starts, so the app never shows StillMade's size control or loses a key to it,
|
|
187
|
+
even while it is still loading.
|
|
188
|
+
|
|
189
|
+
A `<video controls>` plays in StillMade's player, the same one as everywhere in
|
|
190
|
+
StillMade: play, timeline, time, sound and full screen along the bottom, shown
|
|
191
|
+
while the pointer is on the video, with keys on the focused video (Space or K,
|
|
192
|
+
the arrows, M, F) and touch. Full screen goes through StillMade, right after a
|
|
193
|
+
click or key in the view; the frame itself has no `allow="fullscreen"`. A
|
|
194
|
+
`<video>` without `controls` is the Block's own and StillMade never touches it,
|
|
195
|
+
so a Block that drives playback (its own timeline, an editor or CAD viewer)
|
|
196
|
+
leaves `controls` out, and `data-stillmade-player="native"` keeps the browser's
|
|
197
|
+
controls. Result pictures from `StillMade.previewImage` in `sm-stage` or
|
|
198
|
+
`sm-gallery`, and any element marked `data-stillmade-expand`, get a full-screen
|
|
199
|
+
button in the bottom-right corner while the pointer is on them; pictures with
|
|
200
|
+
the same value (`data-stillmade-expand="shots"`) open as one set, and
|
|
201
|
+
`data-stillmade-expand="off"` removes the button. The keyboard reaches them
|
|
202
|
+
too: such a picture without a `tabindex` of its own joins the tab order,
|
|
203
|
+
keyboard focus on it shows the button, Enter or Space opens the viewer, and
|
|
204
|
+
closing the viewer gives the focus back to the picture.
|
|
205
|
+
|
|
206
|
+
## A job on one page: a check, then the run
|
|
207
|
+
|
|
208
|
+
A job the person fills in and gets a result from is one page: the inputs on the
|
|
209
|
+
left and the result's place on the right on a wide screen; on a phone they
|
|
210
|
+
stack in the page's order, the inputs, the button in normal flow (never a sticky
|
|
211
|
+
bar), then the result's place under it. When the expensive run needs a cheap
|
|
212
|
+
check first (the script and a voice sample before the video), keep it on the
|
|
213
|
+
same page: call `StillMade.run({make: 'check'})`, show what comes back, then
|
|
214
|
+
`StillMade.run({make: 'video', script})` with what the person checked. Each run
|
|
215
|
+
is priced and approved by StillMade on its own, so the view shows no price. The
|
|
216
|
+
module side and what the person sees are in MODULES.md, "A check, then the
|
|
217
|
+
expensive run, on one page".
|
|
218
|
+
|
|
219
|
+
## Assets
|
|
220
|
+
|
|
221
|
+
Images, fonts, JSON, audio and video the view needs ship as files named by
|
|
222
|
+
SHA-256, like module files:
|
|
223
|
+
|
|
224
|
+
```json
|
|
225
|
+
{"runtime": "frame", "files": {"schemaVersion": 1, "files": {
|
|
226
|
+
"fonts/inter.woff2": {"sha256": "…", "bytes": 48256, "mediaType": "font/woff2"}
|
|
227
|
+
}}}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
`stillmade-block pack` fills in the digests and sizes. StillMade checks every
|
|
231
|
+
file against its SHA-256 before the view starts.
|
|
232
|
+
|
|
233
|
+
## What the frame does not allow
|
|
234
|
+
|
|
235
|
+
The view runs in an opaque-origin frame with its own policy:
|
|
236
|
+
|
|
237
|
+
- no network (`fetch`, WebSocket and remote images, fonts or scripts fail);
|
|
238
|
+
- no code from strings (`eval`, `new Function`, inline event attributes) and
|
|
239
|
+
no extra script elements;
|
|
240
|
+
- no navigation, popups, downloads, forms that submit, or dialogs;
|
|
241
|
+
- no WebAssembly on the page (run heavy computation in the Block's runtime,
|
|
242
|
+
for example a module Block, and call it with `StillMade.run`);
|
|
243
|
+
- no storage or access to StillMade's page.
|
|
244
|
+
|
|
245
|
+
Workers created from `blob:` URLs are allowed and run off the page's thread.
|
|
246
|
+
|
|
247
|
+
## Run limits
|
|
248
|
+
|
|
249
|
+
StillMade compiles the view so every function and loop checks a time budget.
|
|
250
|
+
One task may run for 250 ms; past that it is stopped with an error, and a view
|
|
251
|
+
that keeps the page busy most of the time, stops answering, or navigates its
|
|
252
|
+
frame is closed with a message. A single built-in operation that blocks for a
|
|
253
|
+
second or more (a huge sort, or a regular expression that backtracks) also closes
|
|
254
|
+
the view where the browser reports it. Move long computation into a Worker or the
|
|
255
|
+
Block's runtime.
|
|
256
|
+
|
|
257
|
+
The host enforces every permission itself: a view's code can message the host
|
|
258
|
+
directly, so a read-only viewer cannot run the Block or save outputs from any
|
|
259
|
+
view.
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Generate media from JavaScript
|
|
2
|
+
|
|
3
|
+
A JavaScript Block can generate images and videos with any model in the shared
|
|
4
|
+
catalog (the same models the app's own Canvas and Image Panels use), speech in
|
|
5
|
+
any catalog voice, music and sound effects by returning a declared
|
|
6
|
+
`media.generate` action. Declare it in the manifest:
|
|
7
|
+
|
|
8
|
+
```json
|
|
9
|
+
"permissions": {"project": [], "actions": ["media.generate"], "network": [], "filesystem": [], "secrets": []},
|
|
10
|
+
"outputs": {"request": {"type": "json"}, "media": {"type": "asset[]"}}
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Return the action from your code. Each item is an `image`, `video`, `speech`,
|
|
14
|
+
`music` or `sfx` item with a prompt and optional `settings`. Image and video
|
|
15
|
+
items may also set `references` (images), `firstFrame`/`lastFrame` (video),
|
|
16
|
+
`negativePrompt` and `seed`. Audio items take only `settings`:
|
|
17
|
+
|
|
18
|
+
- `speech`: the prompt is the text to speak (up to 3,800 characters);
|
|
19
|
+
`settings: {voice, speed}` with a catalog voice id and a speed from 0.25 to 4.
|
|
20
|
+
- `music`: `settings: {durationSec}`, 5 to 240 whole seconds (default 30).
|
|
21
|
+
- `sfx`: `settings: {durationSec}`, 0.5 to 22 seconds in tenths (default 4).
|
|
22
|
+
|
|
23
|
+
Video items take `settings: {model, duration, resolution, aspectRatio, generateAudio}`.
|
|
24
|
+
With no `model`, an `aspectRatio` the default model (Vidu Q3 Turbo, which takes none)
|
|
25
|
+
cannot make picks the cheapest catalog model that makes it with the frames and
|
|
26
|
+
`duration` given, so `{aspectRatio: "9:16"}` alone asks for a vertical clip.
|
|
27
|
+
|
|
28
|
+
```js
|
|
29
|
+
return {request: {
|
|
30
|
+
schemaVersion: 1, kind: "stillmade.media-action", operation: "media.generate",
|
|
31
|
+
resultPort: "media",
|
|
32
|
+
request: {items: [
|
|
33
|
+
{key: "hero", operation: "image", prompt: input.prompt,
|
|
34
|
+
settings: {model: "nano-banana-pro", aspectRatio: "16:9", resolution: "2K"},
|
|
35
|
+
references: input.styleImages},
|
|
36
|
+
{key: "clip", operation: "video", prompt: "Slow push in on the harbor",
|
|
37
|
+
settings: {model: "kling-v3-turbo", duration: 5, aspectRatio: "16:9"}},
|
|
38
|
+
{key: "intro", operation: "speech", prompt: "Welcome back to the show.",
|
|
39
|
+
settings: {voice: "adam", speed: 1}},
|
|
40
|
+
{key: "bed", operation: "music", prompt: "Warm lo-fi piano", settings: {durationSec: 30}},
|
|
41
|
+
{key: "whoosh", operation: "sfx", prompt: "A fast whoosh", settings: {durationSec: 1.5}}
|
|
42
|
+
]}
|
|
43
|
+
}};
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
StillMade turns every item into one exact generation request and asks the server
|
|
47
|
+
for one maximum price for the whole batch, using StillMade's own prices. The user
|
|
48
|
+
sees that maximum and approves it once; credits are reserved before any provider
|
|
49
|
+
call, each call is settled from provider evidence, and unused credits are
|
|
50
|
+
returned when the batch closes. The approval is bound to this Block's exact
|
|
51
|
+
content digest, so changed code needs a new approval. A Block cannot name a
|
|
52
|
+
price, a provider, a key or another Block. References and frames must be images
|
|
53
|
+
saved in the user's own library. Up to 50 items per action.
|
|
54
|
+
|
|
55
|
+
When it finishes, the declared `resultPort` receives an array of
|
|
56
|
+
`{key, kind, assetId, versionId, url, duration?}` in item order (`kind` is `image`,
|
|
57
|
+
`video` or `audio`; `duration`, in seconds, is the length a video, music or sound
|
|
58
|
+
effect item asked for; speech has none, so decode it with `audio.decode` to time it); failed items are listed
|
|
59
|
+
separately and are not charged beyond what the provider actually received.
|