> ## Knowledge Base Index
> Fetch the complete knowledge base index at: https://documentation.celestory.io/sitemap.xml
> Use this file to discover available pages before exploring further.
> Pure-Markdown content can be obtained by appending a '.md' suffix to the content URLs listed in the sitemap (without the trailing slash).

# A variable is remembering

# 🧠 A variable is remembering

In chapter 1, your reader has a choice: tell the guard the truth, or lie to them. They lie. Three chapters later, the guard crosses their path again — and should remember it.

Without memory, your graph can't do anything with that lie. It would have to **duplicate the entire rest of the story**: one "they lied" version and one "they told the truth" version, doubled, all the way to the end. Add a second memorable choice and you're up to four copies, a third and it's eight. 😱

A variable is exactly what avoids that: **a place where your story writes something down, to read it again later.** A sticky note the project keeps in its pocket for the whole playthrough. 📝

🔺 There's no math involved. A Celestory variable isn't an unknown to solve for: it's a **label with a value written on it**. `HasLied = true`. `Points = 12`. `PlayerFirstName = Camille`. You write to it whenever you want, you read it back whenever you want.

---

${frame}[Video: A variable is remembering](https://celestory-docs-videos.netlify.app/en/construction-graphe/a-variable-means-remembering.html)

## 🪟 The Variables window

Two ways to open it:

- the **project menu** (the blue button top left) → **Variables**;
- the shortcut `Cmd+Shift+V` (`Ctrl+Shift+V` on Windows).

The window is titled **"Project variables."** That title isn't a vocabulary detail — remember it, we come back to it below.

It's laid out in two columns: on the left, your list of variables (with a **Search** field above it); on the right, the sheet for whichever one you've selected. As long as you have none, the right-hand column simply shows *"Add your first variable to add intelligence to your scenario."*

### ➕ Creating a variable

The **Add variable** button sits at the bottom of the left column. A small window asks for three things:

1. **Type of the variable (can not be changed)** — the dropdown in the table below. ⚠️ This is final: to change type, you have to delete and recreate.
1. **Of (can not be changed)** — this second dropdown appears **only** if you chose *List*: it asks what the list is made of.
1. **Name of the variable (can be changed)** — this one, yes, can be renamed at any time.

The confirm button refuses to activate and shows **"This variable already exists"** if the name is already taken. 👍

### 🎚️ The initial value

On the right-hand sheet, under the name, there's an **Initial value** field. This is the value the variable holds **at the very start of the playthrough**, before anything has touched it.

For seven types out of eight, Celestory creates this value on its own at creation time, with a neutral starting value: `0` for a Number, `false` for a Boolean, an empty (multi-line) text for a Text. All you have to do is fix it if it doesn't suit you.

🔺 Only the **Background image** type creates nothing automatically: its initial value stays empty until you fill it in yourself.

🔺 An empty initial value isn't an error, and produces no message: it produces emptiness, silently, everywhere you read the variable. Get in the habit of filling it in.

---

## 📋 The available variable types

Eight types, in the exact order of the dropdown:

| Type | What it remembers | Example use |
|---|---|---|
| **Text** | A string, on one line or several. | The player's first name, a typed answer, a long context for the AI. |
| **Boolean** | True or false, nothing else. Starting value: `false`. | "Lied to the guard," "found the key," "has seen the tutorial." |
| **Number** | A numeric value. Starting value: `0`. | Points, lives, money, attempt counter. |
| **Image** | An image file. | The portrait the player chose. |
| **List** | An ordered collection of a single type, asked for at creation: File, Text, Image, Number, Object, Boolean or Background image. | The inventory, the clues already found. |
| **Object** | A set of key/value pairs, editable field by field or as raw JSON. | A full character sheet, an API response. |
| **File** | A generic file, any format. | A document uploaded by the player. |
| **Background image** | An image combined with a color, a position and a repeat setting. | The current scenery, which changes as the story progresses. |

🔺 The **Boolean**, **File** and **List** types don't offer a **Clear** button: their value can't be reset to "nothing," only replaced.

---

## 🎬 The running example: the guard remembers the lie

Four steps, start to finish.

### 1️⃣ Create the variable

`Cmd+Shift+V` → **Add variable** → type **Boolean** → name `HasLied`. Its initial value shows as `false`: at launch, nobody has lied yet. ✅

### 2️⃣ Write it in chapter 1

In the graph, right after the "I lie" branch of your **Choice** block, add an **Assign** block. It has three inputs:

- `in` — the wire arriving from the choice;
- `variable` — **which** variable to write to;
- `value` — **what** to write into it.

On the `variable` input, open the picker and choose `HasLied`. 🔎 The `value` input **doesn't exist yet**: it appears automatically as soon as you've picked the variable, and it takes on the right type by itself (a checkbox, here, since `HasLied` is a Boolean). Check it: `true`.

🔺 Close the window: if nothing is wired to `variable` or `value`, the block collapses on the graph into a compact **`HasLied = true`** pill, with only `in` and `out`. The variable and the value can then only be set in the editing window (double-click).

Wire the `out` output into the rest of the scene. There you go, the lie is recorded. 🖊️

### 3️⃣ Read it back in chapter 4

Where the guard crosses paths again, drop a **Condition** block. It has one `condition` input expecting a Boolean. Two outputs: `true` and `false`.

To bring `HasLied` to it, two **strictly equivalent** ways:

- **The Variable block** — a small block that carries only the variable's name and a single output. Drop it, drag a wire from its output to the `condition` input.
- **Directly on the point** — open the Condition block's editing window and, on the `condition` field, use the **Select a variable** option. No wire, no extra block: the field points at the variable.

Either way, the read is **live**: Celestory fetches the value **at the moment the player passes through**, not the value it started with.

Wire `true` to "Well, well, the liar…" and `false` to "Good evening, honest traveler." 🎭

🔺 The Condition block has its own article: **☑️ Setting up true/false conditions**. It covers comparisons, combined tests and multiple branches. A variable with no condition is useless, and a condition with no variable is too: the two articles read one after the other.

### 4️⃣ Check that it works

Launch the player and open its **Variables** panel. You'll see the full list there, with the value **live**, changing before your eyes as the Assign block runs. You can even force a value by hand there to test the chapter 4 branch without replaying chapter 1. 🧪

---

## 🔎 ⚠️ Why you'll never find the "Variable" block in search

This is the most confusing trap in this chapter, and it deserves its own callout.

Open the add-block menu, type `variable`: **nothing**. The Variable block is deliberately excluded from the block list and its search. 🙈

It lives somewhere else: **right at the bottom of the add-block menu**, under a heading **"Variables,"** where Celestory lists **your** variables by name. Clicking `HasLied` drops a Variable block already wired to `HasLied`. The search field does filter this section — but by **variable name**, not block name: type `HasLied`, not `variable`.

🔺 **Direct consequence: as long as you haven't declared a single variable, the section doesn't exist and the block is perfectly unfindable.** This isn't a display bug: create the variable in the Variables window first, and the block will show up afterward.

🔺 Another route, handy once you know it: drag a wire out of an input and drop it into empty space. The autocomplete menu that opens offers, in addition to blocks, **all your variables of the right type** — and drops the block already wired. ⚡

---

## 🌍 ⚠️ Scope: there's only one bag, and it's shared

A critical, counter-intuitive point: **a Celestory variable is global to the entire project.**

Not to the module. Not to the graph. Not to the scene. There's only **one list**, flat, shared by the whole project — which is exactly what the window's title says, *"Project variables."* The `HasLied` you write in the "Prologue" module is exactly the same one you read in the "Epilogue" module. A variable created from anywhere is immediately visible everywhere.

This is extremely useful — it's what lets a story cross its modules without losing anything — but it has three consequences worth knowing:

- 🔺 **Names collide.** Two collaborators who each create a `Counter` in "their" part are, in reality, working on the same memory slot. Prefix them: `Ch1_Counter`, `Combat_Counter`.
- 🔺 **Deleting a variable hits the entire project.** Celestory scans **every** graph, deletes **every** Variable block that pointed to it, and clears every field that referenced it. It's clean, it's thorough, and it's irreversible with one click (undo remains your safety net).
- 🔺 **Renaming into a duplicate fails silently.** If you type a name already held by another variable, the rename is simply ignored: no message, the old name stays. Check that the new name actually shows up.

---

## 🎭 ⚠️ The "Context" trap in the sidebar

Expand a module in the left-hand sidebar: under each one sits an entry called **Context** (a speech-bubble icon).

The word strongly suggests "the variables **of this module**." **It's not the case.** This shortcut opens the exact same project Variables window, with no module filter whatsoever. Click "Context" under module A or under module B: you get the exact same list either way.

🔺 **"Context" is nothing more than a shortcut to the Variables window.** It's tucked under each module for convenient access, not because there's a context per module. There isn't one.

---

## 🗂️ Groups: folders, and nothing more

The Variables window offers an **Add group** button, and each group can contain subgroups. You can drag your variables into them, and fold or unfold the tree.

🔺 A group is **purely cosmetic**. It tidies up the display, full stop. It creates no partitioning whatsoever: a variable filed under the "Combat" folder stays readable and editable from any block in the project, exactly like the others. File things away for your own bearings, never to isolate them.

---

## ✍️ The four blocks that write to a variable

| Block | What it does | Types accepted |
|---|---|---|
| **Assign** | Writes a value into a variable, replacing the old one. | Number, Text, Boolean, Image, List, Background image, File, Object. |
| **Multi Assign** | The same thing, for several variables at once. A `count` input sets how many variable/value pairs the block displays. | The same. |
| **Increment** | **Adds** an amount to the current value (1 by default). | Number only. |
| **Decrement** | **Subtracts** an amount from the current value (1 by default). | Number only. |

🔺 Increment and Decrement are the right answer to "add a point": they read, compute and rewrite in a single block. Doing the same thing with an Assign would mean reading the variable, adding to it somewhere else, then reassigning it. 🎯

🔺 The **Variable** block, for its part, only **reads**. It has no input, only an output. It never modifies anything.

---

## 💬 Displaying a variable in a sentence

You don't need any complicated setup to write *"You have 12 points."* Just write, in the block's text field, `You have {{Points}} points.`: the double curly braces make a `Points` input appear on the block, which you wire to your variable.

This is a mechanism in its own right, with its own rules (no accents inside the braces, case matters, only ten blocks are concerned) — it's all in the article **🧩 Injecting a variable into text: double curly braces**. Don't leave this page without reading it if you want personalized text.

---

## 💾 What survives from one play session to the next

A natural question: if the player closes the tab and comes back tomorrow, is `HasLied` still `true`?

**Only if you planned for it.** There is a game-save mechanism, but it's **not automatic**: it relies on two blocks.

- The **Checkpoint** block records, the moment the player passes through it, **the entire state of the playthrough**: the position in the graph, the current module, the call stack… **and the value of every variable**. The whole thing is written into the player's browser, one save per project.
- The **Load checkpoint** block restores that state. It has a `no checkpoint found` output for the — common — case where the player is here for the first time.

🔺 **Without a Checkpoint block in your graph, nothing is kept.** On close, every variable goes back to its initial value.

🔺 A save is **a snapshot**, not a continuous recording: whatever happened after the last pass through a Checkpoint block is lost. Drop one at the end of every chapter.

🔺 It lives **in the player's browser**. Switch device, switch browser, or clear the site's data: the save is gone.

🔺 On the menu side, the **Start** button has a **Reset the variables** option. Turned on, it resets everything to the initial value when launching the module; turned off, it keeps the current state. That's exactly the difference between "New game" and "Continue." 🎮

---

## 🩹 Two details that catch people off guard

🔺 **The Variable block keeps its old name.** Its label is copied the moment you drop it, and isn't refreshed if you rename the variable afterward. The link stays correct — it really is the right variable being read — but the graph shows a stale name. Replace the block to refresh the display.

🔺 **An unwired variable doesn't complain.** Whether the initial value is empty, a `value` point is left dangling, or an input is waiting for a wire that never arrives, Celestory says nothing: it uses emptiness and moves on. The player's Variables panel is your only reliable witness. 🔦

---

→ Next step: your story can now remember — all that's left is to **see it for yourself**. Head to **Testing Your Project and Reading the Debugger**, to run a playthrough and watch your variables change live, value by value. That's where you find out whether the sticky note was really written. 🔍