FolioTier 1
characters
How speakers lower into Folio. A cast member is a stable handle (`say emma:`), like a Ren'Py `Character()` variable - rename-safe. A bare quoted name (`say "Storyteller":`, optionally `#color`) is a one-off custom speaker, like a Ren'Py string-speaker line. A bare string with no speaker is `narrate`.
Folio gives you three ways to attach a voice to a line of dialogue. A cast member is a name you define once in your project's cast - when you write say emma:, Folio resolves the display name, color, and portrait from that single definition, so renaming a character later touches one place rather than every line she speaks. A bare quoted name lets you put a speaker on screen without a cast entry, useful for one-off voices, environmental speakers, or anything whose identity matters for only a handful of lines.
Narrate drops the nameplate entirely. It is not a shorthand for a character named Narrator - it signals the structural absence of any speaker, and the engine presents it differently as a result.
The choice between a cast member and a quoted name is a question of reuse and ownership. If a speaker appears more than a handful of times, or if other parts of your script need to reference or react to their identity, define them as a cast member. A quoted name with a color is convenient for a background voice that surfaces once, but that color lives only inside that say line - there is no shared definition to update if your palette changes. Avoid using quoted names as a workaround for cast members you intend to reuse; the short-term convenience becomes maintenance debt once the character recurs.
Reference page - characters aren't a verb. This page collects the
rules that govern how say references a speaker and how the importer
flattens Ren'Py's character indirection.
Cast handle or quoted name
A cast member is referenced by a stable handle - say emma: "..." -
which is rename-safe: renaming the character never touches the line. A
quoted name (say "Storyteller": "...") is a one-off custom speaker
that is not in the cast.
say "Emma": "I missed you."
say "Storyteller": "And so the day began."
Two reasons for the flattening: (a) the node editor and migration report read cleaner when the speaker is the literal name a creator would say out loud, and (b) Folio's import target is the result of a project's character system, not its source - Vizno owns the future, not the round-trip back to Ren'Py.
Narrator
A line without a speaker is narrate, not a
say with an empty character. The split keeps the runtime,
node editor, and importer honest about whether a line is character
speech (namebox, character-coloured text, voice-line auto-attachment
once the voice verb ships) or narration (no namebox, full-width
prose).
narrate "The lights faded."
If a creator wants a named narrator - "the storyteller", "the dungeon
master" - they write it as a regular character: say "Storyteller": "...". The runtime treats them as a character; the render style
distinction stays clean.
Per-character styling
Per-character text styling (colours, fonts, side-of-screen positioning) is presentation work, not character-definition work. The presentation layer exposes one per-character hook today - the namebox can follow the speaker's own colour; a richer styling system may return later, but it isn't part of the v1 surface.
Importer translation
Ren'Py Character() definitions are flattened at import time:
| Ren'Py | Folio |
|---|---|
| define e = Character("Emma")e "Hello!" | say "Emma": "Hello!" |
| define e = Character("Emma", color="#ff8")e "Hello!" | say "Emma": "Hello!" (per-character colour is dropped; the presentation layer renders every character with the default style) |
| e "Hello," (what="...") | say "Emma": "Hello," (inline what= extensions normalize to plain text) |
| bare "Hello!" | narrate "Hello!" |
If two Ren'Py characters share a display name, the read-only migration report flags it inline on the affected scene - Folio's flat-namespace model can't carry the collision automatically, so the creator resolves it in the editor (typically by renaming one).