Skip to content

Quick Start

Get oriented and authoring in a few minutes. This page covers the need-to-know: how to run the engine, the handful of concepts that everything else builds on, and the ready-made templates you'll copy instead of writing UI from scratch. When you want the details, head to the Authoring Guide.


Run the engine

Prerequisites: Node.js 18+, and an editor (VS Code recommended; install the Ana extension for .ana syntax highlighting and macro completions).

bash
npm install
npm run dev        # dev server with hot reload at http://localhost:5173

Open the URL Vite prints. The repo ships with a small example game so you have something running immediately; you'll replace its passages with your own.

Want these docs offline? npm run docs:dev serves this site locally with hot reload.


The three things to learn

Almost everything in a passage is one of three things:

  • $ and _ variables: $player.gold is global and saved; _temp is scratch that resets every passage.
  • @ directives are structural markers. @zone(text) targets a screen region, @system(init) marks GameInit, and @hook / @into / @on wire up injection and events.
  • (macro:) calls are the verbs: (if:), (link:), (goto:), (set:), (add:). They follow a (name: args) shape, and blocks of content go in square brackets: (link: "Open")[ … ].

Get comfortable with those and the rest of the engine is just a larger vocabulary.


Where your game lives

Every .ana file under passages/ is discovered automatically, so organize them into folders however you like. A file holds one or more passages, each introduced by a :: Name header:

ana
:: TownSquare

@zone(text)
The square is quiet this afternoon.

@zone(options)
(link: "Enter the bar")[(goto: Bar)]

passages/_init.ana is special. It holds the GameInit passage (@system(init)), where your declarations and configuration live. It runs once when a new game starts and again every time a save loads (saved values are applied over it), so keep it to declarations, definitions, and config; put one-time story beats in your (start:) passage instead. The two lines every GameInit needs:

ana
:: GameInit @system(init)

(start: TownSquare)         // first passage after New Game
(layout: Layout_Standard)   // the built-in two-sidebar layout

(declare: $player, name, "", gold, 100)
(declare: $player.health, 100, 0, 100)   // bounded: (add:)/(sub:) auto-clamp

See the annotated gameinit_walkthrough.ana template (in templates/) for a fully commented GameInit covering player vars, world state, time, NPCs, items, quests, and config.


  • Zones are the named regions of the layout. @zone(text) and @zone(options) are the two you'll use most; sidebars, image, header, and overlays are also zones. Content after a @zone(...) line goes into that region.
  • Links are clickable buttons: (link: "Label")[body]. The body runs on click, so it can change state and then navigate.
  • Navigation tiers decide how much of the screen refreshes:
    • (goto: Passage) rebuilds the whole scene (a new location).
    • (update: Passage) refreshes the text and options zones only (same scene, new beat).
    • (action: Passage) makes a minimal, targeted update (toggle a detail without disturbing the rest).
ana
@zone(options)
(link: "Buy a round")[(pay: 5)(notify: "You spent 5 gold.")(action: Bar_Pour)]
(link: "Leave")[(goto: TownSquare)]

No back button by design. Ana has no undo or quick-save key; the only way to rewind is to deliberately load a save slot. Author your branches knowing players live with their choices.


Start from a template

The engine ships working, restyleable screens in templates/. Copy the ones you need into passages/ (UI screens conventionally live in passages/ui/) and customize them. They follow every engine convention, loop over engine data instead of hardcoding, and use theme variables so they match any theme. They're the fastest way to a real game.

TemplateWhat it gives you
title_screen.anaNew Game / Load Game title screen (renders automatically on boot via @system(title))
gameinit_walkthrough.anaA fully annotated GameInit to adapt as your _init.ana
game_menu.anaPause menu: save, settings, back to title
settings_screen.anaSettings modal with keybind remapping and clock/date format
header.anaHeader bar with location, clock, and shortcut buttons
char_creator.anaName + traits + skill-focus creator that hands off to your first passage
char_panel.anaCharacter sidebar: portrait, stats, traits, status effects
npc_panel.anaNPC sidebar: portrait and relationship tier
inventory_screen.anaModal inventory list with use/equip actions
equipment.anaEquipment screen built from your defined slots
quest_log.anaTwo-panel quest log (master/detail via (panel:))
achievements.anaAchievements grid that loops every defined achievement

See it live

With npm run dev running, save any file and changes hot-reload in the browser, with your game state preserved between edits.

Press ` (backtick) to open the dev debugger:

  • Vars: inspect and edit $ variables live.
  • Eval: run macros directly; try (set: $player.gold to 999).
  • Trace / Passages / Hooks: see where you've been, the total passages in game, and inspect injections.

Common mistakes

Nothing renders after New Game. GameInit needs (start: YourPassage), and the passage name must match the :: Name header exactly.

Variable changes don't persist. Only $ variables (declared with (declare:)) save. _temp variables reset every passage.

A link body doesn't navigate. A link body runs on click but only navigates if it contains (goto:), (update:), or (action:). Prose or (set:) alone will execute without moving anywhere.

A _temp is empty at click time. Macros in a link body fire on click, by which point the original passage's _temp vars are gone. Capture what you need into a $ variable first:

ana
// ✗ _id is gone by click time
(link: "Equip")[(add: $equip.weapon, _id)]

// ✓ promote _id at render time, use the global on click
(link: "Equip")[(set: $world.selected to _id)(action: _EquipWeapon)]

Images don't show. Put them in assets/images/; (img:) appends .jpg automatically when you omit the extension.


Where to go next

You want to…Read
Understand variables, bounds, and typesState & Variables
Lay out the screen / define zonesZones & Layout
Branch, loop, and link between passagesNavigation · Math, Loops & Expressions
Add inventory, NPCs, quests, statsRPG Systems
Style prose and theme the UIProse & Text · Theming & Modals
Run time, schedules, and reactive contentTime & Scheduling
Drop to JavaScript for custom logicExtending with JavaScript
Ship a modModding Guide
Look up a macro's exact syntaxMacro Reference