Skip to content

Streams and the URN spine

A workspace is several streams of the same work: a spine text, a padapāṭha, a translation, a commentary. They share relative URNs (1:1, 1:1:1) so the viewer can weave them into one reading or a grid.

The word primary is easy to overuse. In current Vyasa it has one meaning in Toml: a boolean on stream.toml.

IdentityWhere it appearsWhat it is
URN spine flagprimary = true in exactly one content/<folder>/stream.tomlWhich stream owns sequence ids (the catalog tree). Other streams may only attach blocks to those ids.
Packed / runtime idFolder name under content/What the .vyview, viewer, CSS, and grid layout actually store.
content/samhita/stream.toml
language = "sa"
script = "Deva"
kind = "source"
primary = true

Every stream folder must declare language, script, and kind (syntax-checked opaque strings; see Workspace configuration). The viewer uses these packed facts; it does not guess script. Do not set kind = "primary" — that collides with the pack-time alias.

There is no [streams] table in vyasac.toml. Packed id is the folder, so you do not need a path map. Leftover [streams] is a load error.

Examples:

  • Ṛgveda: folder samhita → packed id samhita
  • Aṣṭādhyāyī: folder sutra → packed id sutra
  • Bhagavad-gītā fixture: folder mula → packed id mula
  • A work with folder content/primary → packed id is primary (the folder)

Nested content/transliteration/iast packs as stream transliteration (depth-1 folder only).

Spine alias (primary) — pack time only

  • primary = true in stream.toml
  • View templates: `stream { ref="primary" }
  • Localization: extend = "primary"

The packer rewrites those refs to the packed folder name before they reach the .vyview.

Packed folder name — everything after pack

  • streams.name rows, manifest.primary_stream, streams_config, streams_meta, stream_separators
  • Grid JSON: layout.rows[].block
  • CSS classes: .vyasa-block-{stream}
  • [build.default] streams allow-list

The viewer must not map primary → samhita in TypeScript.

[build.<profile>] streams is an optional packed-name filter. Omit it unless this profile should exclude some folders.

# Ṛgveda: only needed if you are leaving streams out of this pack
[build.default]
streams = ["samhita", "padapatha", "sayana"]

Pack errors (nothing is silently dropped) when the list contains:

  • the alias primary while the packed folder is not named primary
  • an unknown id

You cannot list both primary and samhita as two spellings of the same stream.

In a view template you may still write the spine alias:

`stream { ref="primary" }

In grid layout JSON and in stylesheets, use the packed id:

{ "rows": [[{ "block": "samhita" }]] }
.vyasa-block-samhita { /* spine column */ }

A class scrape that looks for class="primary" will not find class="samhita".

Optional per-stream string inserted between SegmentBreak (|) splits when weaving that stream:

content/mula/stream.toml
language = "sa"
script = "Deva"
kind = "source"
primary = true
segment_separator = " "

The packed publication stores this under the packed stream name.

Pack order must not imply a spine: a translation folder must not become the catalog tree because it was listed first. primary = true is that authority. Runtime surfaces need a stable, filesystem-visible id so publishers can write CSS and grid specs without a secret alias. Collapsing both into the word primary made Ṛgveda packs look like a stream named primary while every layout expected samhita.