Screenplays
are data.
ScreenJSON is an open schema and toolchain for treating the screenplay as a first-class, structured document. Convert from Final Draft, Fountain, FadeIn, and PDF. Store in any NoSQL database. Query it, transform it, render it, feed it to an LLM, ship it to a viewer.
ACT I — THE PROBLEM
The screenplay is the last major creative format still locked inside proprietary formats.
A novel is UTF-8. A song is MIDI or stems. A video is MP4 plus sidecar tracks. A screenplay?
An .fdx file, a proprietary XML variant, or — more often than anyone wants to admit — a flat PDF that has to be re-parsed every time anything touches it.
That works fine for writing a screenplay. It breaks the moment you want to do anything else: batch-process 5,000 library titles for streaming catalogue search, build an AI tool that understands dialogue per character, version two drafts side by side, or translate a whole film for an international production.
ScreenJSON fixes this by treating the screenplay as what it already is — a structured, hierarchical, typed document — and giving it a proper schema, a proper toolchain, and a proper viewer. Open at the schema layer, licensable at the industrial layer.
ACT II — THE TOOLS
Seven tools. Open framework.
Use any one on its own, or stack them: open reference implementation at the bottom, industrial batch pipeline at the top.
screenjson-export
Go · Docker
A free, open-source CLI that converts Final Draft FDX into ScreenJSON. The reference implementation.
screenjson-cli
Go · Docker
The full command-line tool: convert, export, validate, encrypt, and serve a REST API across every format.
screenjson-ui
TypeScript · Svelte
An embeddable JavaScript viewer that renders ScreenJSON as a studio-quality screenplay in the browser.
Desktop Viewer
Desktop
Windows, macOS, and Linux AppImage releases.
iOS Viewer
iOS
Native iPhone and iPad reader.
Android Viewer
Android
Native Android screenplay reader.
greenlight
Go · Svelte · Docker
A batch microservice with a job queue: ingest from S3, run pipelines of tasks, deliver at scale.
INTERCUT
The same scene, two formats.
A single scene from The Heist, on the left as Final Draft's FDX XML, on the right as ScreenJSON. Same information, one of them structured.
<Paragraph Type="Scene Heading">
<Text>INT. VAULT - NIGHT</Text>
</Paragraph>
<Paragraph Type="Action">
<Text>A single bulb flickers.</Text>
</Paragraph>
<Paragraph Type="Character">
<Text>MARA</Text>
</Paragraph>
<Paragraph Type="Dialogue">
<Text>We have ninety seconds.</Text>
</Paragraph> {
"id": "7a1c0b4e-…",
"heading": {
"context": "INT.",
"setting": "VAULT",
"time": "NIGHT"
},
"body": [
{ "type": "action",
"text": { "en": "A single bulb flickers." } },
{ "type": "character", "character": "8d2f-mara" },
{ "type": "dialogue", "character": "8d2f-mara",
"text": { "en": "We have ninety seconds." } }
]
} Stable UUIDs
Every scene, element, character — addressable forever.
Language maps
Every text field keyed by BCP 47 — en, fr, ja.
Typed elements
Action, cue, dialogue, parenthetical, shot, transition — not layout.
Queryable
jq a catalogue, index it, embed it, retrieve it.
THE SCHEMA
Every part of a screenplay, exactly where you'd expect it.
ScreenJSON models every element a working screenplay actually contains: structured sluglines with context and time-of-day, typed scene bodies with action, dialogue, cues, parentheticals, shots and transitions, a characters index, a revisions log, notes anchored to character ranges, bookmarks, embeddings, passages and summaries for retrieval — and a layout block so renderers can reproduce studio-standard formatting.
Every textual field is keyed by BCP 47 language tag, so localisation is a first-class concern, not an afterthought.
Every structural node carries a UUID, so you can point to the exact line of dialogue in an otherwise-identical revision.
{
"id": "9fea5fc5-f8f9-4c59-85d2-9ec5dcd452c1",
"version": "1.0.0",
"title": { "en": "The Heist" },
"lang": "en",
"authors": [{ "id": "…", "given": "Jordan", "family": "Lee" }],
"characters": [
{ "id": "…", "name": "MARA", "traits": ["lead", "thief"] }
],
"document": {
"cover": { "title": { "en": "The Heist" }, "authors": ["…"] },
"scenes": [{
"id": "…",
"authors": ["…"],
"heading": { "context": "INT.", "setting": "VAULT", "time": "NIGHT" },
"body": [
{ "type": "action", "text": { "en": "A single bulb flickers." } },
{ "type": "character", "character": "…" },
{ "type": "dialogue", "character": "…",
"text": { "en": "We have ninety seconds." } }
]
}]
}
} ACT III — WHO USES IT
Writers, producers, studios, developers.
Writers & writers' rooms
Keep every draft in source control. Diff revisions line-by-line. Collaborate across time zones without merging .fdx binaries by email.
Producers & line producers
Extract props, wardrobe, cast lists, and scene breakdowns automatically. Feed scheduling tools real data instead of rekeying sluglines.
Studios & archives
Convert 10,000-title back catalogues into something you can actually search. Greenlight ingests, Elasticsearch indexes, your catalogue team exhales.
Developers & platform teams
Embed the viewer, hit the REST API, ship a feature. Everything speaks JSON, every node has a UUID, every field validates against the schema.
AI & data teams
Training data that already has structure. Per-character dialogue, per-scene tags, optional pre-computed embeddings. Stop parsing PDFs.
Localisation teams
Every text node is a language map. Translate once per language, ship one file, render in any locale the viewer supports.
FADE IN:
Paste a URL. Upload an FDX. See what your screenplay looks like as structured data.
APPENDIX
Start where you are.
Guides
Long-form, per-audience. Pick the one that describes you and start reading.
How-tos
Short, focused recipes. One task, one page, real commands you can copy.
Specification
The full schema, annotated. Every object, every field, every constraint.
NewAI
Embeddings, vector DBs, RAG, MCP — the playbook for treating screenplays as retrieval data.