Posts

Monogatari v2.8.0

Download Link: monogatari-v2.8.0.zip

v2.8.0 is the largest release since v2.6.0. Under the hood, the entire engine has been rewritten in TypeScript and broken apart into focused modules; on the surface, you get explicit asset management, save screenshots, native desktop storage, a big library of dialogue text effects, and a long list of fixes. Here’s everything that changed and how to take advantage of it.

πŸ’œ Support Monogatari

Monogatari is free, open source, and built in the open β€” releases like this one are powered by the people who chip in to keep it going. If the engine helps you bring your stories to life, please consider sponsoring its development:

πŸ“° Release Change Log

🌟 New Features

🧠 A Full TypeScript Rewrite

The core engine, every built-in action, and every component have been migrated to TypeScript. The @monogatari/core package now ships its own type definitions, so whether you’re writing custom actions and components or just scripting your game in an editor, you get full autocomplete and type-checking for the engine API, game settings, and the new typewriter effects.

🧩 The Engine, Split Into Modules

The old ~3,500-line monogatari.ts “god object” has been split into focused modules β€” assets, characters, i18n, input, lifecycle, persistence, and ui. The build now produces two clearly separated targets:

Nothing changes about how you write a game, but the engine is now far easier to maintain and to load from a bundler.

πŸ“¦ Preload & Unload Actions

Two new script actions give you explicit control over when assets live in memory. preload pre-caches music, sounds, voices, scenes, images, and character sprites before you need them; unload frees them when you don’t.

// Single assets
'preload music main_theme',
'preload scene classroom',
'preload character y happy',

// Wait until the asset is ready before continuing
'preload scene boss_room blocking',

// Free memory again
'unload scene classroom',
'unload music',            // a whole category
'unload all permanent',    // memory *and* the IndexedDB cache

You can also group assets into named blocks and load or free them in a single statement β€” great for per-chapter management:

monogatari.action('Preload').blocks({
    'Chapter1': {
        music: ['theme_song', 'battle_music'],
        scenes: ['school_gate', 'classroom'],
        characters: { 'y': ['happy', 'sad', 'normal'] },
    },
});

// ...later in your script
'preload block Chapter1 blocking',
// ...and at the end of the chapter
'unload block Chapter1',

Audio is decoded once and persisted in IndexedDB, so re-preloading across sessions is instant β€” unless you unload ... permanent, which clears the persistent cache too.

πŸ“Έ Save Screenshots

Save slots can now show a screenshot of the exact moment a save was made instead of a generic scene image. Turn it on with a single setting:

monogatari.settings({
    'Screenshots': true,
});

When enabled, the engine captures the game screen (via modern-screenshot) as you save and stores it in a dedicated IndexedDB database, kept separate from your save data so it never bloats the save object. Slots then render that screenshot as their thumbnail. ⚠️ Screenshots have a couple of requirements around CSP and cross-origin assets β€” see the upgrade notes below and the Saving documentation.

πŸ’Ύ File System Storage

For games packaged as desktop apps (Electron / Electrobun), there’s a new FileSystem storage adapter that writes saves straight to disk through a desktop bridge instead of the browser’s IndexedDB:

monogatari.settings({
    'Storage': {
        'Adapter': 'FileSystem',
        'Store': 'SaveData',
    },
});

If the same build is opened on the web (no desktop bridge present), it automatically falls back to IndexedDB, so it keeps working everywhere.

πŸ™ˆ Show & Hide Textbox

Two tiny but frequently requested actions to get the dialog UI out of the way β€” perfect for showing off a CG or a scene:

'show scene cg_sunset with fadeIn',
'hide textbox',
'wait 2000',
'show textbox',
'e ...beautiful, right?',

Visibility is part of the saved state, so it survives save/load and rollback. One thing to remember: once hidden, the box stays hidden for every following line until you show textbox again β€” so always bring it back before a line you want the player to read. Docs: show textbox Β· hide textbox.

✨ A Big Library of Text Effects

Dialogue now supports inline text effects with a simple {effect}…{/effect} markup. Open with {effect} and close with {/effect}:

'y I am {angry}absolutely furious{/angry}! {pause:500}{whisper}...but I will be okay{/whisper}.',
'narrator The {glitch}corrupted{/glitch} signal pointed somewhere {mysterious}strange{/mysterious}.',

There are 40+ effects across several families:

Effects nest, so you can combine them:

'{shake}{angry}STOP{/angry}{/shake} right there!',

…and they’re all driven by CSS custom properties, so you can re-tune them globally without touching the engine:

type-character[data-component] {
    --effect-shake-intensity: 4px;
    --effect-wave-amplitude: 0.5em;
    --effect-wave-speed: 0.6s;
    --effect-glitch-color-1: #ff00ff;
    --effect-glitch-color-2: #00ff00;
}

The full list and details live in the Dialogs and Type Writer docs.

⏩ Semi-Instant Skipping

If you keep InstantText off β€” so finishing a line rushes the typewriter while keeping its effects, rather than dumping the whole line at once β€” you can now also let players make that rush genuinely fast. Set the min value of the text-speed slider in your settings screen below 0:

<input type="range" min="-100" max="50" step="1" data-action="set-text-speed">

Players who drag the slider into the negative range get a near-instant fast-forward that still respects formatting and effects.

🚦 A Proper Action-Blocking API

Actions that need to pause the story until they finish β€” waiting on a choice, a notification permission, an async load β€” now declare a static blocking flag and a shouldProceed() check instead of toggling a global. The old block / executing sub action globals still work for now but are deprecated; if you maintain custom actions, see the upgrade notes below.

πŸ› Bug Fixes

πŸ“¦ Misc

How To Upgrade

If you’re on a v2.x.x version

For most games, upgrading is the usual drill: replace the files in your engine directory with the new ones from the download. A few things are worth double-checking:

If you’re on v1.4.1 (stable) or below

If you’re upgrading from a game built on v1.4.1, we recommend reading the Upgrade Guide first β€” the jump to v2 is a big one.