Skip to content
screenjson

Schema & data

Version-control screenplays as ScreenJSON

Commit ScreenJSON files to Git, diff drafts line-by-line, and keep every revision reviewable.

Last updated January 2026

Why this works

Because ScreenJSON is text, git diff just works. Because every element carries a UUID, changes to one scene don’t cascade into spurious diffs on unrelated scenes. Because text is language-keyed, you can even see translation changes as additions to a language map rather than replacements.

A reasonable repo layout

screenplays/
  my-script/
    manuscript.fdx            # source in your writing tool
    screenplay.json           # canonical ScreenJSON
    revisions/
      2026-01-10-blue.json
      2026-01-15-pink.json
    notes/                    # optional prose markdown

A pre-commit hook

Keep the canonical screenplay.json in sync with the source .fdx:

#!/usr/bin/env bash
# .git/hooks/pre-commit
set -e
for fdx in screenplays/**/manuscript.fdx; do
  dir="$(dirname "$fdx")"
  docker run --rm -v "$PWD/$dir:/data" screenjson/cli \
    convert -i /data/manuscript.fdx -o /data/screenplay.json
  git add "$dir/screenplay.json"
done

Pretty-printing for diffs

Commit the ScreenJSON pretty-printed — it diffs cleanly line-by-line:

screenjson convert -i manuscript.fdx | jq . > screenplay.json

Keeping UUIDs stable

Use a converter that honours existing UUIDs. Both screenjson-cli and screenjson-export will, by default, reuse an existing screenplay.json if one is present next to the source to keep UUIDs stable across regenerations.

Git attributes

Mark ScreenJSON files for text diffing:

# .gitattributes
*.json diff

Next