- JavaScript 87.9%
- CSS 6.8%
- C++ 5.2%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| dist | ||
| docs | ||
| examples/static-site | ||
| scripts | ||
| src | ||
| .gitignore | ||
| .prettierignore | ||
| LICENSE | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
Sai
Ink stories that wake up inside static sites.
Sai is a small browser embedder for compiled Ink stories. It is not an Ink
engine; it uses inkjs for that. Sai owns the article-shaped part: loading a
story into an existing page, reading a visual manifest, rendering transcript,
visual-novel, or cinematic layouts, and staying pleasant to drop into Quartz,
Eleventy, Astro, Hugo, plain HTML, or whatever shrine of markup you dragged
home at midnight.
The name is the pitch: ink that becomes a living scene.
Why Sai Exists
Most Ink web players answer: "Can I play this story in a browser?"
Sai answers: "Can this story become part of a page?"
It is for interactive essays, lore posts, documentation rituals, cheap visual novels, pitch decks, character sermons, branching articles, and other story objects that want to live inside a site instead of becoming a separate web app.
Quick Start
Copy the built files from dist/ into your site's static assets:
sai.js
sai.css
ink.js
Add the assets to a page:
<link rel="stylesheet" href="/static/sai/sai.css" />
<script defer src="/static/sai/sai.js"></script>
Embed a story:
<div
class="sai-player"
data-ink-format="visual-novel"
data-ink-story="/stories/agora/story.ink.json"
data-visual-manifest="/stories/agora/visual-manifest.json"
data-scene-label="The Aquarium Agora"
></div>
Sai auto-initialises every .sai-player when the document loads. It also
listens for Quartz-style nav events after client-side page swaps.
Formats
Raven
<div class="sai-player" data-ink-story="/story.ink.json"></div>
The default format is a compact interactive-fiction transcript. It is the simplest Raven Collective-style shape: text, choices, variables when useful, and no stage machinery.
Visual Novel
<div
class="sai-player"
data-ink-format="visual-novel"
data-ink-story="/story.ink.json"
data-visual-manifest="/visual-manifest.json"
></div>
Visual-novel mode renders one scene image, a fixed dialogue bar, speaker avatar, speaker name, line text, and a right-side option rail. Ink tags drive the speaker and scene:
# speaker: Void
# scene: agora
# avatar: void
The world is full of systems that say one thing and reward another.
Cinematic
<div
class="sai-player"
data-ink-format="cinematic"
data-ink-story="/deck.ink.json"
data-visual-manifest="/deck.visual-manifest.json"
></div>
Cinematic mode is for slide/deck-like fragments: background plates, captions, references, and short blocks of text.
Data Attributes
data-ink-story: required URL for compiled Ink JSON.data-ink-format:raven,visual-novel, orcinematic.data-visual-manifest: optional visual manifest URL.data-scene-label: optional fallback scene label for visual-novel mode.data-ink-title: optional player title/status text.data-ink-runtime: optional URL forink.js.data-sai-runtime: alias fordata-ink-runtime.data-show-variables="true": show Ink variables in visual modes.
Legacy .aetheria-ink-player containers are still initialised so existing
GameCult pages can migrate without ritual screaming. New work should use
.sai-player.
JavaScript API
window.Sai.init(document.querySelector(".sai-player"));
window.Sai.initAll();
console.log(window.Sai.version);
By default, sai.js loads ink.js from the same directory as itself. Override
that with data-ink-runtime, data-sai-runtime, or window.Sai.runtimeSrc.
Visual Manifest
See docs/manifest.md.
Development
npm install
npm run build
npm run check
Compile the example story after dependencies are installed:
npm run compile:example
Open examples/static-site/index.html through a local static server. Browsers
are right to dislike fetch() from file://; do not take it personally.
Boundary
Sai owns:
- browser-side Ink loading through
inkjs - player DOM and mode rendering
- visual manifest interpretation
- default CSS and theme variables
- static-site auto-init
Sai does not own:
- authoring Ink
- compiling
.inkto.ink.json - Quartz page chrome
- GameCult-specific assets, lore, or characters
- a full VN/game engine loop
The brush is sharp. The painting is yours.