What's inside a .sboardx

Rename it to .zip or run unzip and you get this:

project.json                 format version, name, frame + resolution, fps
sequence.json                panel order, scenes, camera keyframes
panels/<id>/panel.json       code, shot, duration, note, dialogue
panels/<id>/layers.json      layer stack (bottom to top), image layers, blur
panels/<id>/art/<layer>.svg  the art: one SVG per layer
audio/clips.json + audio/*   clips, tracks, embedded audio files
images/*                     embedded images for image layers

Every entry is stored uncompressed, so a reader is a few dozen lines in any language and nothing is hidden behind a proprietary codec.

Open it anywhere

  • In a browser. The web reader plays a storyboard back with layers, camera moves and audio. It's a single HTML file; nothing is uploaded.
  • In a vector editor. Each layer's SVG opens in Illustrator, Inkscape, Figma or Affinity as ordinary filled paths.
  • In Toon Boom Storyboard Pro. The import/export scripts bring boards into Storyboard Pro as true vector layers, with timing, dialogue, audio tracks and scene cameras, and take edited boards back to Upshot. See the Toon Boom plugin guide.
  • From a script. Python's zipfile and json are all you need; see below.

The SVG art

Each layer is one SVG in world units: the frame is 540 units tall, centred on the origin, and the viewBox is the frame, so a panel of any resolution uses the same coordinates. Strokes are closed, filled outlines (M C Z paths), never centrelines, so they render identically everywhere. Layer opacity, blend mode and blur are baked into the group's CSS, so a browser shows the layer correctly on its own. A handful of sboardx: attributes let Upshot re-import its own files bit-exactly; every other reader ignores them.

The JSON manifest

Entry Holds
project.json Format version, name, episode, frame size, render resolution, fps
sequence.json Panel order; scenes with their camera keyframes (t, zoom, centre, rotation)
panel.json Code, shot type, duration in seconds, notes, dialogue
layers.json Per layer: name, opacity, blend, visibility, lock, blur, optional image placement
audio/clips.json Clips with start, duration, trim, gain, file; tracks with mute state

The full schema, every key and default, is in SPEC.md.

Scripting example

List every panel with its dialogue:

import json, sys, zipfile

z = zipfile.ZipFile(sys.argv[1])
seq = json.loads(z.read("sequence.json"))
for scene in seq["scenes"]:
    print(scene["name"])
    for pid in scene["panels"]:
        p = json.loads(z.read(f"panels/{pid}/panel.json"))
        print(f"  {p['code']:<8} {p['dur']:>5.2f}s  {p.get('dialogue', '')}")

More in the repo's examples: extract all layer SVGs, validate an archive.

Versioning and extending the format

The current version is 1.0. Readers ignore keys they don't know, so new optional keys don't change the version; app-specific data lives under vendor keys (x-upshot) and never leaks into the public schema. Proposals are pull requests against the spec on GitHub.

No lock-in, by design

The format, the reader and the Toon Boom scripts are Apache-2.0 at github.com/Upshot-Storyboard/sboardx. An exported storyboard is readable, editable and convertible with free tools today, and will stay that way whether or not Upshot is installed.