Skip to content

Building and shipping

Writers work in a project folder; the thing you ship is a single compiled bundle. This page covers turning one into the other and getting it to your game.

Publish ▸ Publish Bundle (⇧⌘B) compiles the whole project to a .patterc: a single JSON file, with nothing else attached, and the only file a runtime needs. A toast confirms where it wrote.

Set the output path in Project Settings ▸ Publish. The default is a patter-dist/ folder next to the project; point it at your game’s assets folder so a build drops straight in.

Inside are the scenes, the compiled conditions and effects, the cast, the Game Data fields, the addresses your game uses to start scenes, the text (or none, in IDs-only mode), and a content hash. You don’t commit the bundle to your repo. You rebuild it, you don’t merge it.

From the terminal, patter export runs the same compile for CI, and patter validate re-checks the bundle’s hash to catch a stale build, as the CLI page describes.

The one build decision that affects integration is the localisation mode (Project Settings ▸ General):

Mode The bundle carries Your game Best when
Embedded Every language’s text Reads text straight from the runtime; can switch language live You want the simplest integration and built-in language switching
IDs-only Beat ids, no text Looks each id up in your localisation system You already have a localisation pipeline and want one source of text

Both are fully supported, and the runtime works the same way either way (see Localisation at runtime). A source-debug option adds the source text alongside the ids, handy while you’re developing.

To hand someone the script to read (a producer, an editor, a reviewer who wants it on paper), Publish ▸ Publish Readable Script… writes a screenplay-style document of the whole project in reading order. It has scene and block headings, dialogue (speaker, any performance direction, the line), prose narration, and the branching laid out plainly, with choices as a labelled list (with their conditions and once-only / repeatable flags) and jumps as “go to …”. A line with a speaker qualifier prints it in the cue, TAM (O.S.), as the editable script does. Pick PDF or Word (.docx) in the Save dialog.

It reads top to bottom. Branches sit indented under each choice; it doesn’t try to trace every path, because it’s the document of record rather than a playthrough (that’s the playable HTML).

You get the source language only. Cut lines and engine-only beats are omitted.

PDF uses standard built-in fonts, which are great for Latin and Western-European text. For a non-Latin script (Cyrillic, CJK, …) choose Word, which embeds full Unicode fonts.

From the terminal, patter export-script [path] -o script.pdf (or .docx) writes the same document, and the format follows the extension, as the CLI page describes.

When a stakeholder just wants to play the story (a producer, a publisher, a client) they don’t need your repo, the editor, or a game build. Publish ▸ Publish Playable HTML… writes a single self-contained .html file, with the Patterplay runtime, the whole compiled story, and a small reader UI all inlined. There’s no server, no network, and no build step. Double-click it and it plays in any browser, online or off. Email it, drop it in a shared folder, open it on a phone.

It’s the real runtime. Choices, conditions, sequences, and jumps behave exactly as they do in your game, because it’s the same engine the bundle ships with rather than an approximation. There’s a Restart, and Save/Load (kept in that browser).

Lines arrive on the scene’s own timing. With no recordings in the page, each line is held for an estimate of its reading time, then waits for the writer’s pause, so a cut-in arrives before the line it cuts into has finished. A Speed control (Half / Normal / Double / Instant) slows the timing down, speeds it up, or drops the waits, and that browser remembers the choice. A line with a speaker qualifier shows it after the name, TAM (O.S.).

The page reads in the project’s source language, which is the version a stakeholder is reviewing. (For translated text, send a localised build or the loc files instead.)

From the terminal, patter export-html [path] -o story.html produces the same file for a pipeline (use -o - to write it to stdout), as the CLI page describes.

This is for reading and playing, not editing, and there’s no way back into the project from it. To let someone edit and return changes, hand them a .patterpack instead (below).

Handing the project to someone without your VCS

Section titled “Handing the project to someone without your VCS”

Not every stakeholder is in your repo: a freelance writer, a reviewer, a translator. For them, patter pack produces a single .patterpack file (a zip, like a .docx) holding a full copy of the project. They edit it, send it back, and patter unpack --merge folds their changes back in, line by line. Both commands are on the CLI page.

You don’t need the terminal for any of it. The three moves are all in the File menu, and they are three different acts:

Move Menu What it does
Send Export as Patterpack… writes the file; your project is untouched
Receive Open Patterpack… unpacks into a new project folder and opens it
Take back Merge Returned Patterpack… folds their changes into the project you have open

Merge Returned Patterpack asks for two files, in this order: the pack that came back, then the pack you sent. It then shows you what it found before writing anything, so you can back out. Where you both changed the same line, your version is kept and a .patterconflict file is left beside the shard saying what disagreed. Those are ordinary files: resolve them the way you would a version-control conflict, and delete them when you’re done (patter validate fails while one is still lying about).

If the pack that came back, the pack you sent and your open project don’t all belong to the same project, Patterpad says so first and makes Cancel the default. It’s a warning rather than a refusal, since a project can legitimately be forked, but usually it means one of the two files was the wrong one. patter unpack --merge prints the same warning.

If your game keeps a game-scopes/ folder, the pack carries a snapshot of it, and unpacking puts it in game-scopes/ inside the new project folder. The person you sent it to gets the same checks on @story names, the same properties in the pickers, and previews that stand the other tools in, without needing the rest of your game.

The snapshot is read-only in spirit. Merging their pack back never writes it anywhere, even if they changed it: your folder stays the truth. The one edit that does come home is to World properties, which travels in the project file’s own copy of the game’s scopes. When the returned pack’s World properties differ from the pack you sent, the merge writes their change to your game.scopes.json (only the scopes they changed; the rest of the file stays as it is now), and says so: Patterpad in the merge summary, patter unpack --merge with a game scopes: line. Without that, your next save would bring the project’s copy back in line with the shared file and quietly drop their edit.

  1. Writers finish a pass; you run Production ▸ Production Information to check coverage and draft status (see Writing status).
  2. You Publish Bundle to your game’s assets folder.
  3. Your game loads the .patterc with its Patterplay runtime.
  4. In CI, patter validate gates the bundle, and patter coverage can fail the build if a flow can’t reach its end.

The bundle is engine-agnostic: the same .patterc plays identically on JavaScript, Unity, Unreal, and Godot, so you build once and ship everywhere.

Open source under the MIT licence, made by .