For PixiJS v8 · WebGL & WebGPU

Your browser console,
inside the canvas.

pixi-console captures console.log, warnings and uncaught errors and draws them on top of your scene. It's built for debugging on phones, tablets and TVs where you can't open devtools.

npm install pixi-console

Tap the > prompt (or press ` to open the console) and type help.

Captures everything

It captures log, info, debug, warn and error, plus uncaught errors, unhandled promise rejections and console.clear(). Harmless ResizeObserver loop notices are left out. Your devtools keep working as usual.

Reads like devtools

It supports printf-style %s %d %o substitutions. Objects, Maps, Sets, typed arrays and sparse arrays print like in devtools, circular references included. Errors show their stack, cause chain and extra properties like code. Repeated messages collapse into one line.

Virtualized & fast

Only the visible lines exist as display objects, drawn with BitmapText from a single glyph atlas. Layout happens at most once per frame, and the console is its own render group, so a flood of logs doesn't make PixiJS rebuild your stage. Hidden, it skips layout entirely.

Touch friendly

Scroll with the wheel or by dragging. Taps and the wheel over the log don't reach objects under it, and the wheel scrolls the log instead of the page. The toolbar filters by level, clears and closes, with compact labels on narrow screens. It opens itself when an error happens.

Fits any screen

autoResize follows your renderer across window resizes and orientation changes. Put the console anywhere with a layout function. Filters, timestamps, maxEntries, the toolbar and the prompt can change at any time.

Tiny & typed

Zero runtime dependencies besides pixi.js. Ships ESM, CommonJS and a <script> build with full TypeScript types.

Command line

Turn on prompt to run commands on the device itself. help and clear are built in, addCommand() adds your own, and createJsEvaluator() runs JavaScript in development builds. ↑ ↓ recall earlier lines, Tab completes command names, and execute() runs a line from your code. It's a real text field over the canvas, so phone keyboards, IME and paste just work.

Quick start

import { Application } from "pixi.js";
import { PixiConsole } from "pixi-console";

const app = new Application();
await app.init({ resizeTo: window });
document.body.appendChild(app.canvas);

const devConsole = new PixiConsole({
    autoResize: { renderer: app.renderer },
});
app.stage.addChild(devConsole);

console.log("Hello from the canvas!");

Or with a script tag

<script src="https://cdn.jsdelivr.net/npm/pixi.js@8/dist/pixi.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/pixi-console@5"></script>
<script type="module">
    const app = new PIXI.Application();
    await app.init({ resizeTo: window });
    document.body.appendChild(app.canvas);

    const devConsole = new PixiConsole.PixiConsole({
        visible: true,
        autoResize: { renderer: app.renderer },
    });
    app.stage.addChild(devConsole);
</script>

Command line

import { createJsEvaluator, PixiConsole } from "pixi-console";

const devConsole = new PixiConsole({
    prompt: true,
    autoResize: { renderer: app.renderer },
    commands: {
        spawn: {
            usage: "<count>",
            description: "Spawn enemies",
            run: ([count = "1"]) => game.spawn(Number(count)),
        },
    },
    // JavaScript too, in development builds only
    evaluator: import.meta.env.DEV
        ? createJsEvaluator({ scope: { app } })
        : null,
});
app.stage.addChild(devConsole);

devConsole.addCommand("fps", () => app.ticker.FPS.toFixed(1));
await devConsole.execute("spawn 3"); // run a line from code

Change it at runtime

devConsole.filter = ["warn", "error"];
devConsole.timestamps = true;
devConsole.maxEntries = 100; // drops the oldest entries now
devConsole.toolbar = false;
devConsole.prompt = true;
devConsole.history = savedLines; // for ↑ and ↓

// In a tap handler, so phones open the keyboard
button.addEventListener("click", () => devConsole.focusPrompt());

Every option, method and type is documented in the API reference. Coming from v4? Read the migration guide.