Monogatari v2.8.0

June 17, 2026 Β· 8 min read

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.

πŸ“° 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:

  • lib/monogatari.module.js β€” an ES module, the main entry of the npm package, ideal for bundlers (Parcel, Vite, webpack, etc.).
  • dist/engine/core/monogatari.js β€” a self-contained browser bundle, the one used by the classic drop-in game template.

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:

  • Movement β€” shake (plus shake-hard, shake-slow, shake-little, shake-horizontal, shake-vertical), wave / wave-slow / wave-fast
  • Reveal β€” fade, blur, scale, scale-bounce, slide-up, slide-down, redacted, invisible-ink, handwriting, flicker
  • Glitch β€” glitch, glitch-hard, glitch-slow
  • Style β€” bold, italic, big, small, impact, rainbow, glow
  • Emotion presets that bundle several of the above into one keyword β€” angry, scared, happy, sad, mysterious, excited, whisper, shout, dizzy, dreamy, robotic, static

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#

  • Fixed audio volume being reset to 0 on fade-in instead of fading from the configured level.
  • Fixed word-wrap making text “jump” mid-typewriter β€” unrevealed characters now use opacity instead of visibility.
  • Text speed now updates live from the settings slider (previously it only took effect after a refresh), and the slider shows the correct value on reload.
  • Fixed Message actions soft-locking the screen and blocking progress.
  • Fixed AutoPlaySpeed flipping to the opposite value every time the player changed it and refreshed the game.
  • Fixed the selector parameter not being passed to init() in actions and components.
  • Fixed the page not centering correctly when aspect-ratio enforcement was active.
  • Fixed dialog-log and text-box scrolling behavior.
  • Made visual actions (show/hide image, character, layer, canvas, video, etc.) record state and history consistently, for more reliable rollback.
  • Fixed a recursive-call bug in the engine core.
  • Re-exported tsParticles for legacy compatibility.

πŸ“¦ Misc#

  • Added the modern-screenshot dependency that powers the screenshots feature.
  • New service-worker caching strategy: network-first for navigations (so fresh CSP and markup reach players immediately), stale-while-revalidate for your JS/CSS (instant load, updated on the next visit), and cache-first for everything under assets/. Opaque cross-origin responses are no longer cached β€” this is what keeps screenshots from coming out black.
  • Documentation has moved into the main repository and now lives at monogatari.io/v2.
  • The development toolchain now runs on Bun, with a custom dev server (WebSocket live-reload), a build-web.ts web build, and Electrobun scripts for desktop distribution. None of this is required to ship a game β€” the downloadable template is still a static site you can serve any way you like.
  • Removed the old Parcel / Yarn toolchain, cleaned up leftover debug logs, added missing debug-mode error messages, and updated the CI lint/test tasks.
  • The npm package has been updated to 2.8.0 and now ships TypeScript types.

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:

  • Custom dialog markup: if you use inline text effects, make sure your closing tags are {/effect} (for example, {shake}boom{/shake}).
  • Custom actions: if you wrote actions that called engine.global('block', …) or relied on _executing_sub_action, migrate them to the new pattern β€” a static blocking property plus a shouldProceed() that throws while the action is blocking. The old globals are still honored, but deprecated.
  • Turning on screenshots: besides Screenshots: true, you’ll need to:
    • add blob: to the script-src directive of your Content-Security-Policy (the template’s script-src-elem already allows blob:; modern-screenshot also needs it in script-src),
    • serve any cross-origin assets (for example, from a CDN) with CORS headers (Access-Control-Allow-Origin), otherwise the browser taints the canvas and your thumbnails come out black, and
    • replace your service-worker.js with the new one, which skips caching opaque responses.

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.

Tags: #monogatari #visual #novel #engine #typescript #release