Persistent state
Why some variables survive a new game, where those values are stored, and how a player clears them.
Most story state is per playthrough. Start a new game and gold is back to its
default, the visit counters are back to zero, the generator has a new seed. A
persistent variable is the exception: it is the story's memory across
playthroughs on this browser.
The classic use is the second run acknowledging the first. A narrator who says "you have been here before". A route that only opens once some other ending has been reached. A cosmetic unlock. It works because a persistent variable is the only one a new game does not reset.
How it works
Declare a variable with scope persistent in the Variables panel. Everything
else about it is normal: it still has one of the seven types, it is still
written with a Set beat and read with conditions and tokens.
The difference shows at two moments.
Starting a new playthrough. The runtime seeds every declared variable to its default, then lays this browser's remembered persistent values over the top. A persistent variable that has never been remembered falls back to its default, which is why the default applies on the first ever play and never again.
Loading a save. A save is one playthrough frozen at a moment. The browser's remembered persistent values are laid over the loaded snapshot, so the store wins for persistent variables and the save keeps everything else. Without that rule, loading a slot taken before an unlock would silently revoke it, which is the whole feature failing quietly.
Persistent values are written back whenever the playthrough is saved, and again when the story reaches an ending. A reader who closes the tab mid-story does not lose an unlock.
Where the values live
In the reader's browser, in localStorage, under the key
narratomi:progress:<slug> for the story's share-link slug. The same record
holds one other thing: the ids of the endings this browser has reached, which is
what the endings gallery counts.
That record is deliberately not the save. Saves live under
narratomi:save:<slug>, are pinned to a bundle version, carry visit counters
and the generator position, and are thrown away on a new game. Progress is the
opposite of all four, which is why the two are separate keys.
There are no player accounts, so this is per browser and per share link. A different browser, a private window, or "clear site data" starts over. Say that in your story if an unlock matters, and do not promise readers something account-shaped. The player's own title screen says it too: "Remembered in this browser only."
Two consequences worth knowing. Previewing from the editor never persists anything, because a preview has no slug. And if the browser has storage disabled or full, writing silently does nothing: the playthrough continues, it just is not remembered.
Changing a persistent variable's type after publishing
Suppose a reader's browser remembers runsCompleted as the number 3, and you
republish with runsCompleted retyped to text. The stored 3 no longer fits
what the story declares, so it is ignored and the declared default wins for that
playthrough. The stored 3 is not destroyed. It stays in the browser's record
untouched, and if a later publish reverts the type, it starts being honored
again.
The fit test is by shape, not by declaration: same underlying kind, same array-ness, and for a list, every entry still a string.
How a player resets it
On the story's title screen, in the endings gallery, there is a Clear unlocks and endings button. It asks for confirmation ("Forget the endings you have found and everything this story remembers between playthroughs? Your saves are kept.") and then removes the whole progress record: persistent variables and found endings together. Saves are untouched. The button is disabled when there is nothing remembered yet.
The gallery only appears when the story has endings, so a story with none has no clear control on its title screen. Clearing site data in the browser has the same effect, plus it removes the saves.
There is no per-variable reset and no author-facing way to write into a reader's persistent state from outside a playthrough. If you need a "reset the meta progress" affordance inside the fiction, write it: a choice whose Set beats put your persistent variables back to their starting values is an ordinary scene.
What is never persistent
The runtime's own bookkeeping. Scene visit counters, choice-taken counters and
the random generator's position live in the
same snapshot as your variables, under reserved names beginning with @. The
persistent slice is built by walking the story's declared variables, and no
declared name can start with @, so per-playthrough bookkeeping stays per
playthrough by construction.