Overview

ScriptPubSPub for short — is a standard for structured writing and for the libraries that hold it. It describes how a work (a screenplay, a stage play, a story, poetry — any text with a repeating shape) is stored, displayed, edited, and printed; and it describes how a set of works is organized, indexed, and shared as a library or curated as a collection. One standard covers the single poem and the whole shelf, and the two halves are built from the same three primitives: sections, blocks, and marks.

A standard, not a new format

ScriptPub deliberately invents no new file format. A work keeps living in a format you already have — HTML, Markdown, Fountain, Final Draft (FDX), plain text, or JSON — and SPub standardizes how its structure, format, and metadata are described within it: one canonical data model, plus a syntax adapter per file type. You can take an existing FDX, a folder of Markdown, your own HTML, or a Project Gutenberg .txt, describe it with a SPub format, and get a full editor and reader — while the file keeps being saved in its own syntax, as if SPub were never there.

The same posture holds for libraries: a library is just a folder of such files with an index.html — plain HTML a browser reads with no tooling, and any static server serves as a working website. Nothing in the standard needs a database, a build step, or an account. A library may also hold works in formats SPub does not itself define — EPUB, DOCX, PDF — which the tooling lists, reads, and can convert to SPub; the format registry is the full capability table of what every file type supports (round-tripping, read-only, or view-only).

Status — pre-release (0.1). ScriptPub is an early draft, still in active development and not yet released. Nothing here is frozen and there is no backward-compatibility guarantee yet: the standard is free to change shape until 1.0. This documentation is the source of truth for it; the implementation lives in the @script-pub/format package. (Internally the on-the-wire model carries scriptpub: 2 — or 3 when the document uses media — a model-version counter, independent of this 0.1 release status.)

Works and libraries, together

Every work carries its own format: a configuration that declares the work’s sections, its block types, mark types, their styling, the editor’s behavior, and how each block type is spelled in each syntax. The format plus the content parse into one canonical model:

{ config, content, sections }
  • config — the format (a FormatConfig).
  • content — one flat, ordered stream of blocks.
  • sections — the resolved section spans over that stream.

A library and a collection are the same kind of document — the config’s kind says so, and their body is a catalog: list blocks whose links point at works. So a library’s index edits in the same editor, renders in the same reader, and travels through the same syntaxes as any work; the shelf and the page never need different machinery. A work moves between libraries by copying a file; a library publishes by serving a folder; a collection curates across libraries by URL. They work together because they are one model.

File names

SPub files use the *.spub.* double extension — the inner name says SPub, the outer says the syntax:

Hamlet-by-William-Shakespeare.spub.html      a work (self-contained HTML)
Hamlet-by-William-Shakespeare.es.spub.html   its Spanish translation, beside it
notes.spub.json                              the same model as JSON
index.html                                   a library's catalog (the web-server default)
library.spub.json                            optional library-config companion

The recommended work name is Title-by-Author.spub.* (the naming template {title}-by-{author}). Content-derived syntaxes keep their own plain extensions (.md, .fountain, .fdx, .txt) — the point of those adapters is not renaming anyone’s files.

Design principles

  • The layout is the element. In content-derived syntaxes (plain text, Fountain, Markdown) a block’s kind is inferred from its spelling — its caps, prefixes, indentation, or Markdown construct — never from a stored annotation. So there is nothing extra to store and nothing to lose. See Kind inference.
  • Content and kind round-trip losslessly. Anything unrecognized becomes the default Text block, shown and saved verbatim. Attributes are tiered — some survive only in syntaxes that can store them — so a round-trip preserves content and kind, not necessarily every attribute. See Attributes.
  • Structure is flat; nesting is bounded. The content is a flat stream. Sections are points in it, not containers. The only real nesting — grids — is exactly one level deep. See The document model.
  • Styling is a curated CSS subset, never free CSS. A block or mark’s style is a { property: value } map limited to an enumerated catalog; values that could break out of a declaration are rejected.
  • The format is data. Block types, marks, sections, styling, and flow are all editable configuration — nothing is hardcoded. A built-in preset (screenplay / play / story / catalog) is just a default instance of the same shape a user can edit.
  • A library is data too. Its index is an ordinary document; its typed entries derive from the content; its store is anything path-keyed; and access is the store’s capability, never a claim inside a file. See Libraries.
  • Syntaxes are extensible. Adapters are additive: registering a new syntax id needs no format-version bump.

How to read these docs

Start here Then
Document model — the canonical { config, content, sections } shape, blocks, runs, the three shapes. Configuration — the FormatConfig object and its meta.
Blocks — block types, behavior, indexes, editor flow. Sections & divisions — the two kinds of structure.
Marks & links — inline formatting and references. Kind inferencematch / write per syntax.
Attributes — the fixed attribute vocabulary. Media — images, audio, video; assets, covers, narration.
The stylesheet — all visual truth as real CSS. Conditions — @media + app-state adaptation.
Syntaxes & file types — the six adapters and where config lives. Format presets — reusable formats.
Collections — curated catalogs of references to works. Libraries — a store of works + its generated index.
Multi-file works — one work split across files: work folder, spine, parts. Devices & export targets — device profiles, packages (EPUB), targets.
Translations, drafts & revisions — sibling documents. Glossary — every term, precisely.

Scope of this revision

Print and export targets are a separate concern from syntax adapters, and layer on top of the model without changing it — that layer is now specified: package formats (EPUB; PDF reserved) and per-library export targets. Sets of works are in scope: a document’s kind may declare it a collection (a curated catalog of references) or a library (a catalog owning a store of works) — both are ordinary documents under the same model. So is the multi-file work — a folder treated as ONE work: an index document whose body is the spine (the same catalog shape), plus config-less part files in any syntax, assembled into the same one flat document. A folder of Markdown managed as one work is exactly this.

Media is in scope — images (block and inline), audio, and video as void blocks and object runs; asset references resolved by the store, never bytes in the model; covers and index cards on the shelf; and narration alignment carrying everything an audiobook’s EPUB media overlay needs. Media is what moves the wire counter to 3; a media-free document stays version 2.