Overview

ScriptPubSPUB for short — is a standard for formatting a single structured text work — a screenplay, a stage play, a story, poetry, any text with a repeating shape — as one self-contained, standards-correct HTML file: a .spub.html. The file describes how the work is structured, displayed, edited, and printed, using three primitives — sections, blocks, and marks — and it does so with the web platform’s own machinery, not a parallel one.

Built-in HTML and CSS store everything

SPUB deliberately invents as little as possible. Everything standard HTML and CSS can already express is expressed that way, natively:

  • Metadata is schema.org JSON-LD in the head — one <script type="application/ld+json"> island speaking a prepared CreativeWork/Book vocabulary, with <title>, <html lang>, and the canonical/icon links derived from it. See Metadata.
  • Styling lives in the document stylesheet — one real <style> element with real CSS: rules, @media conditions, @page. See The stylesheet.
  • Sections are semantic body-level elements<header>, <nav>, <main>, <footer>, <section>, with standard DPUB-ARIA roles. See Sections & divisions.
  • Block and mark identity is a CSS selector — a kind declares selector: "h3.scene" and is recognized by CSS selector matching, exactly as its stylesheet rule already targets it. See Kind inference.
  • Page breaks and keeps are real CSSbreak-before / break-after / break-inside in the sheet or on an element’s style attribute; there is no structured pagination directive.

Every fact has one machine-readable home. The metadata island is the only home of metadata, the sheet the only home of styling, the DOM the only home of sections. (Presentation may restate metadata — the <title> tag and a title page both show the title — but those are derived or authored display, never a second source machines read.) What remains — block types, marks, editor flow, foreign-syntax export spellings — is a minimal JSON island: the one <script type="application/json"> element holding only what HTML and CSS cannot express. A file whose config is trivial omits the island entirely.

The payoff is the zero-tooling property: a bare .spub.html is a proper, accessible web page. Open it from disk in any browser and it renders styled, themed light/dark, semantically sectioned, and screen-reader navigable — with no ScriptPub software anywhere.

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. The on-the-wire model counter is scriptpub: 6 — one constant version, independent of this 0.1 release status.

Scope — one work, one file

This specification defines exactly one thing: the formatting of a single text work as one .spub.html file — its head, its config island, its stylesheet, its body. That is the whole surface.

Everything around the file is the Script Pub App’s concern, documented with the app, not here: libraries of works, format presets, multi-file works and their assembly, conversion to and from foreign formats (Markdown, Fountain, FDX, EPUB, DOCX, …), export packaging, device targeting, and reading/writing user interfaces. The format keeps only the hooks those features need — for example the spub:preset island term that records which app-managed preset a work’s format was seeded from, and the per-kind foreign-syntax spellings the app’s converters read.

The canonical model

A .spub.html file parses into one canonical model:

{ config, content, sections?, css? }
  • config — the minimal FormatConfig plus the in-memory meta.
  • content — one flat, ordered stream of blocks.
  • sections — the resolved section spans over that stream.
  • css — the document’s own stylesheet text.

Design principles

  • The file is the format. One .spub.html holds the work, its metadata, its structure, and its design — self-contained, portable, diffable text.
  • Standard mechanisms only. Recognition is CSS selector matching; precedence is CSS specificity; theming is light-dark() and color-scheme; breaks are CSS fragmentation. The spec adds vocabulary, not machinery.
  • Every fact has one machine-readable home. Metadata in its island, styling in the sheet, sections in the DOM, the rest in the minimal config island. Presentation may restate a fact; machines read one place.
  • Structure is flat; nesting is bounded. The content is a flat stream. Sections are body-level spans, never nested. The only real nesting — grids — is exactly one level deep. See The document model.
  • Content and kind round-trip losslessly. Anything matching no selector is the default Text block, shown and saved verbatim. Attributes are a fixed, closed vocabulary.
  • The format is data. Block types, marks, and styling are editable configuration — nothing is hardcoded and no genre is built in.

How to read these docs

Start here Then
The file — the normative anatomy of a .spub.html, with a complete minimal example. Document model — the canonical { config, content, sections } shape, blocks, runs, the three shapes.
Configuration — the minimal FormatConfig and the in-memory Meta. Metadata — the JSON-LD island: the prepared schema.org vocabulary, the spub: context, the fallback tier.
Sections & divisions — semantic body-level elements, the standard vocabulary, matter. Blocks — block types, selectors, behavior, indexes, editor flow.
Marks & links — inline formatting and references. Kind inference — selector matching, specificity, foreign-syntax spellings.
Attributes — the fixed attribute vocabulary. Media — images, audio, video; figures; narration.
Mathematics — atomic TeX/MathML expressions. The stylesheet — the spub-base layer and the document’s own rules.
Conditions — @media + app-state adaptation. Settings — the --spub-* custom-property vocabulary.
Translations, drafts & revisions — metadata-linked documents. Glossary — every term, precisely.