1. Overview
ScreenJSON is a data serialisation format for screenplays. It describes, at the structural level, everything a working screenplay contains: a cover page, one or more scenes, sluglines, typed scene elements, a characters index, revisions, notes, bookmarks, layout rules, and optional derived data for analysis and retrieval.
A ScreenJSON file is a JSON document with a stable top-level shape.
The authoritative machine-readable definition is the
JSON Schema at
https://screenjson.com/schema.json.
This page is the human-readable counterpart. It walks through every part of the schema in the order you'd actually encounter it when reading or writing a document.
2. Design principles
Five commitments shape the schema.
Structural first, presentational second
A ScreenJSON document describes what a screenplay is, not
how it looks. Slug, action, cue, parenthetical, dialogue,
shot, and transition are typed nodes — not layout hints. Rendering
rules live in an optional layout block that viewers
can honour or ignore.
Language as a first-class concern
Every user-facing text field is a map keyed by BCP 47 language tag. A single document can carry the same line of dialogue in English, French, and Japanese side by side. Renderers pick a language at read time.
Stable identity
Every node that can be referenced from elsewhere carries a RFC 4122 UUID. Scenes, characters, authors, elements, notes, bookmarks, revisions — you can point to exactly one of them across the lifetime of a document, even after a rewrite.
Extensible without ambiguity
Every object includes an optional meta map — arbitrary
string-typed key/value pairs — so tools can round-trip their own
metadata. The core fields stay strictly typed and
additionalProperties: false; extension goes in
meta, and nowhere else.
Analysis is optional
The analysis block (embeddings, passages, summaries) is additive and discardable. A document without analysis is as valid as a document with it. Analysis sits alongside the canonical document rather than mutating it.
3. The document root
The top-level object has these required properties:
{
"id": "<uuid>",
"version": "1.0.0",
"title": { "en": "The Heist" },
"lang": "en",
"charset": "utf-8",
"dir": "ltr",
"authors": [ /* one or more */ ],
"document": { /* cover, scenes, layout, bookmarks */ }
} …and a long list of optional properties for richer documents:
generator— tool that produced the file (name,version).locale— BCP 47 locale (e.g.en-US), defaults toen-US.contributors— editors, directors, script doctors with their roles.characters— index of characters referenced by cues and dialogue.colors— reusable named colours for notes, revisions, UI.sources— source works this screenplay is based on.registrations— registration records (e.g. WGA).revisions— global revision history.encrypt— default encryption parameters.license— licensing / copyright descriptor.taggable/genre/themes— slug-keyed tag indexes for filtering.logline— one-sentence summary, language-keyed.analysis— optional derived data for retrieval and AI.
4. Shared types
ScreenJSON reuses a small set of scalar and small-object types everywhere. Understanding them once means the rest of the schema reads itself.
uuid
An RFC 4122 UUID string, formatted 8-4-4-4-12.
slug
A lowercase, kebab-cased identifier matching
^[a-z0-9]+(?:-[a-z0-9]+)*$, between 3 and 50 characters.
Used for every enumerable identifier that's not a UUID: tag names,
style ids, revision labels, colour ids.
datetime
An ISO 8601 date-time string (date-time format).
lang
A BCP 47 language tag. The schema regex accepts a 2–3 letter primary
subtag and any number of 2–8 character sub-subtags:
en, en-GB, fr-CA,
zh-Hant, sr-Latn-RS.
dir
Text direction: ltr or rtl.
charset
An IANA character set label, defaulting to utf-8.
text and name
The single most important pattern in the schema. Any place where a screenplay might need translation, ScreenJSON uses a map keyed by language tag:
{
"en": "Hello.",
"fr": "Salut.",
"ja": "こんにちは。"
} text allows up to 10,000 characters per language — long
dialogue or action runs. name is the short-form variant,
capped at 255 characters — titles, display names, cover labels.
meta
An arbitrary string-to-string map with key pattern
^[A-Za-z0-9_.:-]{1,64}$ and 2KB values. Every
object has one. It is the only place tools are permitted to stash
data not described elsewhere in the schema.
tags and roles
Unique arrays of slug. Scenes, characters, and elements carry tags; contributors carry roles.
5. Authors & contributors
Authors — the original writers of the content — are required at the
document level and at every element level. An author is a minimal
object: a UUID, a given name, a family name, and optional
meta.
{
"id": "a2c2a2f0-1c34-4b68-9f4d-ac8f21a0d8a4",
"given": "Jordan",
"family": "Lee"
}
Contributors are anyone who made artistic input other than
original authorship — editor, director, script doctor, showrunner.
They carry the same fields plus a roles array of slugs:
["editor"], ["script-doctor", "director"].
Why both?
Attribution in screenwriting is contested and legally significant. Separating "authors" from "contributors" makes the canonical credit list unambiguous while still giving you somewhere to record the people who shaped the work.
6. Characters
Characters are declared once, at the document level, and referenced everywhere else by UUID. A character has:
{
"id": "<uuid>",
"slug": "mara", // optional, for tooling
"name": "MARA", // canonical display name
"aliases": ["Mara Halpern", "M."],
"desc": { "en": "A thief, mid-30s." },
"traits": ["lead", "thief", "antihero"],
"meta": {}
} name is the canonical form that renderers show in
character cues (traditionally uppercase). aliases
captures alternate names and titles used inside the script so they
can be reconciled to the same canonical character. traits
is an editorial taxonomy — casting types, narrative roles,
demographics — strictly non-canonical and useful for search.
Why a character index?
Because the character of MARA should be the same character
every time she speaks, regardless of whether the script says
MARA, MARA (V.O.), or M., and
regardless of what language the dialogue is rendered in. A UUID
anchors her.
7. The document container
The document property is the screenplay itself. It has
three required halves: a cover page, a list of scenes, and — implicitly — a layout block for renderers.
{
"document": {
"cover": { "title": { "en": "…" }, "authors": ["<uuid>"] },
"layout": { "styles": [], "templates": [] },
"bookmarks": [],
"scenes": [ /* one or more */ ],
"meta": {}
}
} Cover
The cover page — title, authors, optional
sources, and free-form extra text.
It exists so that a ScreenJSON document can produce a
faithful title page without re-interpreting document-level metadata.
Bookmarks
Stable shortcuts into the document. Each bookmark references a
specific scene UUID and element UUID, so
even after a re-order or rewrite it still lands on the right line.
8. Scenes
A scene has this shape:
{
"id": "<uuid>",
"authors": ["<uuid>"],
"heading": { /* slugline */ },
"body": [ /* elements: action, cue, dialogue, … */ ],
"cast": ["<uuid>"],
"animals": [], "extra": [], "locations": [], "moods": [],
"props": [], "sfx": [], "sounds": [], "tags": [],
"vfx": [], "wardrobe": [],
"meta": {}
}
Every scene has at least one author, one slugline, and a body of
zero or more elements (an empty body is allowed for outlining).
The cast array is the set of character UUIDs that
appear in the scene — a projection that tools and UIs can use
without walking the body.
The ten production taxonomies — animals,
extra, locations, moods,
props, sfx, sounds,
tags, vfx, wardrobe —
are each a unique array of slugs. Populated by breakdown tools,
they make scheduling, budgeting, and discovery queryable.
9. Sluglines
The slugline — the scene heading — is one of the few places in screenwriting where formatting is the structure. ScreenJSON decomposes it:
{
"no": 14,
"context": "INT.",
"setting": "VAULT — SUB-LEVEL 3",
"time": "NIGHT",
"mods": ["FLASHBACK", "ESTABLISHING"],
"desc": { "en": "Low-ceilinged. Emergency lighting." },
"meta": {}
} context is constrained to the industry set — one of
INT, EXT, INT/EXT,
EXT/INT, I/E, or POV. The
time field is either one of the common enums —
DAY, NIGHT, DAWN,
DUSK, LATER,
MOMENTS LATER, CONTINUOUS,
MORNING, AFTERNOON,
EVENING, THE NEXT DAY — or any
custom uppercase string matching the shoulder-pattern
^[A-Z0-9][A-Z0-9 .’'/-]{1,39}$.
mods is for additional slugline modifiers —
INTERCUT, FLASHBACK,
ESTABLISHING, SAME, whatever your
production calls them.
10. Scene elements
Every element inside a scene body extends a common
element base — shared fields shown here once and then
assumed throughout:
{
"id": "<uuid>",
"scene": "<uuid>", // back-reference
"authors": ["<uuid>"],
"contributors": ["<uuid>"],
"access": ["<role-slug>"], // RBAC
"notes": [ /* note objects */ ],
"charset": "utf-8",
"dir": "ltr",
"class": "<slug>", // custom class for styling
"dom": "<string>", // optional dom hint
"encrypt": { /* encrypt params */ },
"locked": false,
"omit": false, // scheduled-for-deletion
"revisions": [ /* revision markers */ ],
"styles": ["<slug>"],
"meta": {}
} On top of that base, each element has its own narrow type:
action
Narrative description. text is a language-keyed map.
{ "type": "action", "text": { "en": "MARA lifts the lid." } } character (cue)
The cue above a block of dialogue. References a character UUID and
optionally carries a display override like
MARA (V.O.).
{ "type": "character", "character": "<uuid>", "display": "MARA (CONT'D)" } parenthetical
The bracketed actor direction between a cue and a line.
{ "type": "parenthetical", "text": { "en": "(whispering)" } } dialogue
The line itself. References a character UUID. origin
captures the dialogue's source — V.O., O.S.,
O.C., or FILTER. dual flags
side-by-side dual-dialogue.
{
"type": "dialogue",
"character": "<uuid>",
"origin": "V.O.",
"dual": false,
"text": { "en": "We have ninety seconds." }
} shot
Camera direction — CLOSE ON, ANGLE ON,
PUSH IN. Carries an optional fov
(0–360°) and perspective (2D or
3D) for visualisation tools.
transition
Scene transitions — CUT TO:, FADE TO BLACK., SMASH CUT TO:
general
A typed catch-all for any scene-body text that doesn't fit the others — chapter dividers, sub-headings, scripted on-screen text.
11. Revisions & notes
Revisions
A revision describes a discrete editorial pass. It has a UUID, an
optional parent UUID (the revision it was forked from), an integer
index, one or more authors, a sluggable
label (draft, blue,
final, production-draft), and a
created timestamp.
{
"id": "<uuid>",
"parent": "<uuid>",
"index": 3,
"authors": ["<uuid>"],
"label": "blue",
"created": "2026-01-14T10:12:00Z"
}
Revisions can live at the document level (revisions on
the root), or attached to individual elements
(element.revisions), making fine-grained revision
marking possible without inventing a sidecar format.
Notes
Notes are annotations. Every note has an author, a creation
timestamp, language-keyed text, an optional colour, and — most
importantly — a highlight array of character index
ranges into the rendered text of the element it's attached to:
{
"id": "<uuid>",
"created": "2026-01-14T10:20:00Z",
"contributor": "<uuid>",
"highlight": [[12, 27]], // start/end codepoints
"color": "amber",
"text": { "en": "Too on-the-nose." }
} 12. Layout, styles & templates
document.layout is an optional block that tells
renderers how to present the document. Everything in it is
informational — viewers may honour, partially honour, or ignore it.
Ribbons
Header and footer ribbons — optional repeating content at the top
and bottom of each page. cover controls whether the
ribbon appears on the cover, show toggles visibility,
start sets the page from which the ribbon first
appears, and omit is a list of pages to skip.
Status
The industry revision status block: color — one of
white, blue, pink,
yellow, green, goldenrod,
buff, salmon, cherry —
plus a round and updated timestamp.
Styles & templates
Reusable style fragments (short) and template fragments (longer).
Each has a slug id, a default flag, and a body of up
to 5,000 or 20,000 characters respectively.
Guides
References to external presentation standards — a URL, a title, an id, and notes. They let a document tell a renderer "follow this convention", without attempting to embed the convention itself.
13. Analysis: embeddings, passages, summaries
The analysis block holds derived data for retrieval and
AI workflows. Everything in it is optional and discardable — a
document without analysis is still canonical.
Embeddings
Embeddings are grouped by target UUID (keyed by the UUID of the scene, element, or character they describe) and each has:
{
"id": "<uuid>",
"model": "text-embedding-3-large",
"dimensions": 1536,
"values": [0.0234, -0.0417, …],
"source": "text", // name|text|desc|heading|composite
"lang": "en",
"tokens": 420,
"created": "2026-01-14T10:30:00Z"
} Passages
A passage is a retrieval-sized chunk of text derived from one or
more elements. It has a UUID, the scene UUID it belongs to, the
element UUIDs it covers, the passage text, the
tokens count, and an optional overlap for
sliding-window retrieval schemes.
Summaries
A summary has a scope of document or
scene, optionally a target UUID, a
generated flag, the model that produced it, and a
creation timestamp. Human-written and machine-generated summaries
share the same shape.
Settings
analysis.settings records how the analysis was
produced: model name, chunk size, overlap, tokeniser. Reproducibility is
a first-class concern.
14. Encryption
ScreenJSON supports confidentiality without sacrificing structural
introspection: only text runs are encrypted. UUIDs, timestamps,
scene counts, character lists, revision labels, and
meta stay in plain text, so indexers and schedulers
can still do their jobs.
{
"encrypt": {
"cipher": "aes-256-ctr",
"hash": "sha256",
"encoding": "hex"
}
}
The default cipher is AES-256-CTR with SHA-256 key derivation from
a shared secret of at least 10 characters. Binary output is encoded
as hex, base16, base32,
base64, or ascii85. Additional tool-specific
parameters live in encrypt.meta.
Encryption can be declared at the document root — applying to every element that doesn't override it — or on individual elements, so you can encrypt sensitive dialogue while leaving action visible.
15. Registration & license
A document can carry one or more registrations — a
registration authority name (e.g. WGA-West), a
registration id, and timestamps — and a single license
descriptor with an id and an optional reference URI.
16. Versioning
The top-level version field is the schema version the
document was authored against. It is a strict semantic version —
^\d+\.\d+\.\d+$ — not a free-form label. Tools SHOULD
warn when reading a document whose version they do not support,
and MUST NOT silently drop unknown-but-well-formed fields.
17. Conformance
A ScreenJSON document conforms to version N of this
specification if, and only if, it validates successfully against
the JSON Schema published under
https://screenjson.com/draft/<version>/schema
for version N.
The following guarantees hold for every conforming document:
- Exactly one
id,version,title,lang,charset,dir,authors, anddocumentat the root. - Every referenced UUID — author, character, scene, element, note, revision — exists exactly once in its canonical list.
- Every text map is keyed by a syntactically valid BCP 47 tag.
- No object contains properties beyond those permitted by the schema; extension data lives only in
meta.
The reference validator is screenjson validate --strict
in screenjson-cli. Any
validator implementing the current JSON Schema draft will produce
equivalent results.
Changelog
Breaking changes between drafts will always bump the major version. Additive, backwards-compatible changes will bump the minor version.