Collections

A collection is a curated set of works — a reading list, a ranking, a syllabus, an anthology’s table of contents. It lives in a library you can write to, and it never owns works, only references them: its body is a list of links pointing at works within its own library, by relative path.

A collection is an ordinary ScriptPub document whose config says so:

{ "scriptpub": 2, "kind": "collection", "meta": { "title": "Desert Island Picks" }, … }

kind is the one discriminator: "work" (the default — everything the format was before catalogs), "collection", or "library". A collection, a library’s index, and a multi-file work’s index (its spine) are the same document shape — a catalog document; the difference is authority and reach (a collection’s body is authored truth; a library’s is generated; a work index’s entries are its own parts).

A collection is a file in a library

A collection is a plain SPub file — Desert-Island-Picks.spub.html (.spub.html by default) — that sits inside the library folder, anywhere in it (a collections/ subfolder by convention, but the path is free). A library may hold many collections. They are recognized by their kind, never by name or location, and a library’s index lists works only — a collection file is not a work, so it never appears among them.

Because a collection lives beside the works it references and uses relative paths, it is portable for free: the folder moves to disk, a static host, another store, and every link still resolves — no server, no public URL, no absolute address anywhere. This is the same zero-tooling property a library has, inherited by the collections inside it.

Catalog documents are plain content

There is deliberately no new structure. A catalog document is ordinary blocks, read by ordinary rules:

  • An entry is a list block whose runs carry an href mark — the link text is the entry’s title, the href a relative path to a work in the same library. Ordered list = a ranking; unordered = a plain listing; list.depth nests sub-entries (a translation under its work).
  • Tiers / groups are ordinary divisions — heading blocks with behavior.outline + rank between the lists.
  • Everything else — prose, images, rules — is annotation content: preserved, rendered, and ignored by the catalog derivation. A paragraph after an entry annotates it for the reader; machine-readable annotation (a rating, a date) goes in the entry block’s data attr.

So the whole engine already works on collections: they parse through every syntax, render in any browser unstyled (a nested <ul> of working links), diff, edit, and export like any document.

The derived Catalog

Like the outline and the indexes, the typed view is computed, never storeddocCatalog in @script-pub/format:

CatalogEntry = {
  href: string,        // a relative path to a work in the collection's library
  title: string,       // the link text
  group: string[],     // enclosing division headings, outermost first
  depth: number,       // list nesting depth
  ordered: boolean,    // ranking vs listing
  blockIndex: number,  // the jump/edit coordinate
  lang?: string,       // the block's lang attr (translation links)
  meta?: { … },        // the block's data attr, stringified
}

An entry’s target resolves within the collection’s own library: the href is a store path relative to the library folder, read by whoever holds the store. A catalog document alone doesn’t fetch anything — resolution is the reader’s job, against the library the collection lives in.

References are within the library

A collection references only works in its own library, by relative store path — the same paths a library index uses, which is exactly what keeps a library folder portable across any store (disk, static host, browser database, object bucket).

There are no cross-library or web references in the collection model: to put a work from elsewhere in a collection, first copy it into the library the collection lives in, then reference it. A collection is a view onto one library’s works, not a bag of addresses across the web — which is what lets it move as a unit and resolve with no network, no serving, and no absolute URLs.

Collections subsume series

The earlier idea of a series (a work in exactly one ordered group) is retired: an ordered collection is a series, and being referenced by many collections is strictly more general than belonging to one.

The Catalog preset (scriptpub:preset/catalog) is the default format for collections and library indexes: group/subgroup headings, a default entry block, an annotation note, a link mark, and List/Shelf views.