incanto
v0.59.0
Published
Vibe-coding-first web game engine SDK — JSON-driven scenes on three.js
Maintainers
Readme
incanto
Vibe-coding-first web game engine SDK. Every scene, character, event, and multiplayer rule is JSON an AI agent can read, diff, and rewrite — rendered by three.js.
Start with a whole game
bunx incanto new my-game # Beacon Isle — the flagship 3D template
bunx incanto new my-2d --template platformer-2d # the 2D flagship
cd my-game && bun install && bun run devOne command scaffolds a complete island action-adventure: a generated
golden-hour world (terrain, sea, groves, grass — bun run world re-rolls the
whole island deterministically), a quest NPC with dialogue and choices, enemies
that hunt you across the terrain via grid navigation, melee with a sword
riding the character's hand bone, bloom + color-grade, touch controls on
phones, win fireworks and a death/respawn loop — in ~2 files of game code, the
rest declared in JSON. bun run verify plays the entire quest headlessly
and replays recorded input bit-identically: the agent loop is author → verify →
fix, no browser needed.
bunx incanto new --list shows all five starters, grouped by dimension: three
3D (island adventure, third-person shooter, quest vignette) and two 2D
(platformer, survivors-like).
Or wire the engine yourself
bun add incanto threeimport { Engine, loadScene } from 'incanto';
import { Renderer2D, enablePhysics2D, registerNodes2D } from 'incanto/2d';
registerNodes2D();
const scene = loadScene(levelJson); // the whole game lives in *.scene.json
const engine = new Engine();
engine.setScene(scene);
engine.input.attachKeyboard(window);
new Renderer2D({ canvas, engine });
await enablePhysics2D(engine);
engine.start();| Entry | Contents |
|---|---|
| incanto | node tree, scene JSON load/serialize, signals, Engine loop, InputMap, Behavior, Timer |
| incanto/2d | sprites, spritesheet animation, Camera2D, labels/UI, Rapier 2D physics, character controller |
| incanto/3d | meshes, lights, Camera3D, Rapier 3D physics |
| incanto/net | multiplayer over a pluggable NetworkTransport — built-in offline Loopback + @agent8/gameserver adapter (optional peer); custom backends implement one interface |
schemas/scene.schema.json— generated JSON Schema for scene files (the agent contract)templates/agent8-server.js— the multiplayer server kernel for the agent8 platform
Debug mode
Off by default, with no URL toggle — a deployed build can never be switched on by a player. Gate it to your own dev server (every template already ships the line):
createGame3D({ ..., debug: import.meta.env.VITE_INCANTO_DEBUG === '1' });VITE_INCANTO_DEBUG=1 bun run dev # overlay ON; plain `bun run dev` and prod builds = offA ☰ debug menu appears top-left: Explorer (live scene tree; the selected node's bounds
light up orange in-game), Inspector (its props, editable while running), Logs
(engine.log tail with filters), Stats (fps · frame ms · nodes · tris · draw calls), and
Colliders (physics shapes as wireframe; one click cycles off → all → selected, and
selected draws only the collider of whatever the Explorer has picked — the way to find one shape
in a world full of them). In code: physics.debugDraw = true + physics.debugScope = node, or
(await import('incanto/debug')).attachDebugOverlay(engine) to boot the overlay by hand.
The agent8 asset library
bunx incanto editor --token <v8 access token> (or INCANTO_V8_TOKEN) adds a
📚 button to every field that takes a resource — model, texture, sprite
sheet, sound. Shelves, search, real previews (a GLB is rendered by the engine
itself), and one pick writes the URL, or the scene assets{} entry plus its
$ref for fields that take one. Without a token the panel asks for one and
keeps it in the browser; the editor server proxies the catalog because it is
per-account and not CORS-open to localhost.
Play ⇄ edit, in one window
The menu's last item, ✎ edit this scene, turns the running game into the scene editor in the page you are already in — same window, no reload, and the edit camera starts where the player's eye was. The editor's ▶ play offers the way back as a choice: preview here (simulate in the viewport, scripts stripped) or run as the game (this page becomes the real game again, with your edits). ✕ exit returns without playing.
It follows debug, so an overlay build already has it. editor: false opts out;
editor: { save } gives the editor a save button that writes your file; game.openEditor() is
the same switch as a function. The editor loads lazily (incanto/editor) the first time it is
asked for — a game that never opens it never downloads it.
Docs, agent skills, examples, and architecture: https://github.com/rareboe/Incanto
© 2026 Verse8. All rights reserved. Proprietary — see LICENSE. Bundled third-party OSS notices: THIRD-PARTY-NOTICES.md.
