The pack file
A dynamic pack is one .sshowdynamic file. It’s a zip file with a new name, with the manifest dynamic.json at the top level. An icon is optional.
Shaders aren’t separate files: they go in dynamic.json as text. The editor takes only dynamic.json and the icon from the package. Don’t zip the folder itself; select the files inside it and zip those.
One pack holds up to 32 dynamics. Each one is either a paint or an effect: paints show in a Fill or Stroke, and effects in Effects. The Basic, Retro, and Backgrounds packs use the same format. For how they look to the people who use them, see Dynamics.
Manifest (dynamic.json)
Its fields are almost the same as a plugin’s manifest. Instead of main, it has dynamics, which holds the dynamics. Unknown fields are ignored.
| Field | Required | Rule |
|---|---|---|
| id | Required | Lowercase reverse-domain format (com.example.waves). The rules are the same as a plugin’s, and plugins and dynamic packs share one set of ids. Up to 100 characters when publishing. Ids starting with app.sshow. are SSHOW’s. |
| name | Required | The pack name shown on the Extensions screen in Studio. In the picker of dynamics, it’s the title of the pack’s group. Up to 100 characters when publishing. |
| name_localized | Optional | The name in another language, written as { "ko": "…" } for Korean. The editor and Studio show it when they’re in that language. |
| version | Required | Three numbers joined by periods, x.y.z (1.0.0). |
| api | Required | The dynamic pack API version. It’s 1 now. |
| dynamics | Required | The array of dynamics, 1 to 32 of them. Dynamic fields |
| description | Optional | The description shown on the Extensions screen and in the detail dialog. Up to 2000 characters when publishing. |
| description_localized | Optional | The description in another language, written the same way as name_localized. |
| author | Optional | The author. In the published list, the author is the submitting account, not this value. |
| icon | Optional | The name of the icon file in the package: png, svg, jpg, jpeg, or webp. Without one, the Extensions screen shows a wind icon. |
Dynamic fields
| Field | Required | Rule |
|---|---|---|
| name | Required | The name that points to the dynamic inside the pack, and the one documents remember it by. Lower camel case starting with a lowercase letter (meshGradient), up to 32 characters, unique in the pack. |
| label | Required | The name shown in the picker and in the Dynamic panel. Up to 48 characters. |
| label_localized | Optional | The label in another language, written the same way as name_localized. |
| slot | Required | “paint” is a pattern painted in a Fill or Stroke. “effect” changes an object’s pixels and shows in Effects. |
| animated | Optional | true if it moves over time. It’s false when left out, and then it doesn’t get uTime. |
| params | Required | The array of parameters, up to 24. With none, use an empty array. Parameters |
| glsl | Required | GLSL text that holds one function. Shaders |
| padding | Optional | Only for an effect. How far the effect spreads outside the object, in px, written like { "plus": 4, "scale": { "size": 2 } }. plus is always added, and scale multiplies a number parameter’s value. It can reach up to 256 px with every parameter at its max. |
Shaders
Write only one function in glsl. The editor adds the uniform declarations and the main function, so don’t write main, #version, #extension, or #include. These three are refused even inside a comment.
The vec4 you return is a color with premultiplied alpha. The src an effect gets is the same, so when you change a color, divide by alpha first and multiply again after.
A paint is drawn as a picture of up to 1024 px on each side, then stretched to the object’s size. On a large object, thin lines and small dots get thicker by as much.
Shaders compile on the device’s GPU when the pack goes in. If any one dynamic doesn’t compile, the whole pack stays out.
| Name | Meaning |
|---|---|
| vec4 dynamicPaint(vec2 uv) | The function for slot “paint”. uv is the position inside the painted box, from 0 to 1 both across and down. |
| vec4 dynamicEffect(vec2 uv, vec4 src) | The function for slot “effect”. src is the original pixel at that position. Read pixels at other positions with texture(uTexture, uv). |
| uTime | Time in seconds, passed only when animated is true. |
| uInputSize | The size of the input picture. xy is the width and height in px, and zw is their inverse, for moving by one pixel. |
| uOutputFrame | The area being drawn. zw is the width and height in px, and a paint’s position in px is uv * uOutputFrame.zw. |
| uTexture | Effects only. The picture of the object. |
| uViewportScale | Effects only. The current zoom. Multiply values set in document px (such as a dot size) by it to get screen px. |
| u + parameter key | Each parameter is one uniform: capitalize the key’s first letter and put u in front (size → uSize). Numbers and booleans are float (off 0, on 1), and colors are vec3. |
Parameters
Parameters show as fields under Parameters in the Dynamic panel. Values people change are saved in the document and reach the shader as uniforms.
The editor gives every paint and effect its own opacity, so don’t make opacity a parameter.
| Field | Rule |
|---|---|
| key | Lower camel case starting with a lowercase letter, up to 32 characters, unique in the dynamic. time, texture, opacity, viewportScale, inputSize, inputPixel, inputClamp, outputFrame, globalFrame, and outputTexture are names the editor uses, so they can’t be keys. |
| label · label_localized | The field’s name. Up to 48 characters. |
| type | One of number, color, and boolean. |
| default | For a number, a value between min and max; for a color, #rrggbb; for a boolean, true or false. |
| min · max · step | Required for a number. step must be greater than 0. Saved values are held to this range before they reach the shader. |
| unit | A unit for a number, up to 8 characters. For an angle, use °. |
Try it
There are two ways to check a pack in the editor after you change it. You can drop the file anywhere, and the Windows desktop app can also watch a folder.
Drop the file
Web · DesktopDrag the .sshowdynamic file onto the editor canvas. Nothing announces it: choose Dynamic in a Fill, Stroke, or Effects, and its dynamics show under the pack’s name. If a pack with the same id is already there, the new file replaces it. A dropped pack lives only in the editor you have open now, so it’s gone when you reload.
Watch a folder
Desktop app (Windows)Open settings.json the same way as for a plugin’s folder watching. Set "dynamics.devPath" to the absolute path of the folder that holds dynamic.json, save, and restart the app. Add the key if it isn’t there. From then on, each time you save a file in the folder, the pack goes into every open editor again. It can be on together with "plugins.devPath".
A refused pack stays out without a word
If a declaration breaks a rule or a shader doesn’t compile, the pack stays out with no message. If the pack doesn’t show in the picker, choose the file in the developer console. It points out what breaks the rules, and sends nothing until you click “Send for review”. The console can’t check whether shaders compile, so undo your changes bit by bit to find the cause.
Publish
A published pack goes into Dynamics on the Extensions screen in Studio, where anyone can install it. Publishing works the same way and follows the same rules as publishing a plugin, and a person reviews every version.
-
Choose the package
Open the developer console and click “Choose a file” in the “Send for review” panel. When you choose the .sshowdynamic file, the console reads it at once and shows its name and version. If it breaks a rule, it says what to fix.
-
Send it for review
Check the consent box and click “Send for review”. The pack appears in the “Your extensions” list, marked “Dynamic pack”, as “In review”.
-
Check the result
A reviewer tries the pack in the editor, and for a new version compares its pictures side by side with the published version’s. The result comes by notification and email. An approved version is published right away.
Rules for new versions
| Change | What happens |
|---|---|
| Remove a dynamic | Refused, because documents that use it would break. |
| Change a dynamic’s slot | Refused. |
| Remove a parameter, or change its type | Refused. |
| Narrow a number parameter’s range | Refused, because saved values would be cut. Only lower min and raise max. |
| Add a dynamic or a parameter | Allowed. |
| Change a default, a label, or a shader | Allowed. Documents that already use it change their look too, though, so add a dynamic whose look changes under a new name. |
When something goes wrong
-
Why doesn’t a pack I dropped show in the picker?
It was refused because it breaks a rule or a shader doesn’t compile. Choose the file in the developer console, and it points out what breaks the rules. Effects are in Effects, not in a Fill. -
Why does a pack I fixed and dropped again stay the same?
When a pack with the same id is already there, the new file replaces it only if it keeps the rules for new versions. If you removed or changed a dynamic or a parameter, reload the editor and drop the file again. -
Why do I get “The package doesn’t meet the rules. Fix this and try again:”?
The reason follows it, in English, starting with the name of the manifest field or dynamic entry. Fix that field and choose the file again. For a new version, also check the rules for new versions. -
Why can’t others see a paint?
A dropped pack is only in your editor. Use it in a cloud project, and the Dynamic panel shows “This pack isn’t published, so others won’t see this dynamic”. Publish the pack, and others get it too. To show it before publishing, share a .sshow file from Save a Copy in the editor’s Menu: the pack goes inside the file, so it draws as is. A file from Download .sshow on a Studio card doesn’t carry the pack. -
Where do I see shader errors?
The editor doesn’t show shader errors. First check that a very small function goes in, then grow it a little at a time, dropping the file each time.
Updated 10/30/2026 · The videos on this page were recorded in the current editor.