pixijs-application
pixijs/pixijs-skills
Create and configure PixiJS v8 Applications with renderers, stage, canvas, and plugins.
What is pixijs-application?
The Application class is PixiJS's main entry point, wrapping a renderer, root stage Container, canvas, and Ticker/Resize plugins. Use it to initialize a rendering context with async app.init(), manage the render lifecycle, and access core properties like app.stage, app.renderer, and app.canvas.
- Initialize Application with async app.init() and configure renderer, canvas, resolution, background, and DPI handling
- Access core properties: app.stage (root Container), app.renderer, app.canvas, app.screen (visible area), and app.domContainerRoot (DOM overlay host)
- Control the render loop with TickerPlugin: app.start(), app.stop(), app.ticker.add(), and automatic frame rendering
- Manage responsive canvas sizing with ResizePlugin: set resizeTo, call app.resize() or app.queueResize(), and track screen dimensions
- Opt-in CullerPlugin to skip rendering containers outside the visible area and improve performance
- Clean up with app.destroy() including releaseGlobalResources to drain global pools and prevent texture/batch stale state
How to install pixijs-application
npx skills add https://github.com/pixijs/pixijs-skills --skill pixijs-application- PixiJS v8 installed (npm install pixi.js)
- Basic understanding of display objects and the scene graph (see pixijs-scene-container skill)
- For non-browser setups, see pixijs-environments skill
How to use pixijs-application
- 1.Import Application from pixi.js
- 2.Create a new Application instance with new Application()
- 3.Call await app.init({...}) with desired options (width, height, background, preference, resizeTo, etc.)
- 4.Append app.canvas to the DOM: document.body.appendChild(app.canvas)
- 5.Add display objects to app.stage and use app.ticker.add() for animation callbacks
- 6.Call app.start()/app.stop() to control the render loop, or app.render() for manual rendering
- 7.On cleanup, call app.destroy({removeView: true, releaseGlobalResources: true}, {children: true, texture: true, textureSource: true})
Use cases
- Set up a basic 2D game or interactive canvas with automatic resize to window and high-DPI support
- Create a responsive web-based visualization that adapts to container size changes
- Build a multi-app scenario (e.g., multiple canvases on one page) with proper resource cleanup between instances
- Implement performance optimization by culling off-screen display objects in large scenes
- Control rendering manually with autoStart: false and requestAnimationFrame for custom frame timing
- Game developers building 2D games with PixiJS
- Web developers creating interactive graphics and visualizations
- Performance-conscious developers optimizing large scenes with culling
- Developers managing multiple Application instances or re-initializing apps in the same tab
pixijs-application FAQ
You must pass releaseGlobalResources: true to app.destroy() to drain global texture caches and batch pools. Omitting it is the usual cause of stale state when tearing down and re-creating an app in the same tab.
Set resizeTo: window in app.init(), combine with autoDensity: true and resolution: window.devicePixelRatio, and the ResizePlugin will automatically listen for resize events and update the canvas size.
Yes, pass autoStart: false to app.init(), then call app.render() yourself inside requestAnimationFrame or your own loop. Ticker callbacks will still fire if you call app.ticker.update() before rendering.
app.resize() immediately resizes the canvas; app.queueResize() defers the resize to the next frame to coalesce rapid calls; app.cancelResize() drops a pending queued resize.
Import CullerPlugin, call extensions.add(CullerPlugin) before creating the app, then set cullable: true on containers and sprites you want culled when outside the visible area.
Full instructions (SKILL.md)
Source of truth, from pixijs/pixijs-skills.
name: pixijs-application description: "Use this skill when creating and configuring a PixiJS v8 Application. Covers new Application() + async app.init() options (width, height, background, antialias, resolution, autoDensity, preference, resizeTo, autoStart, sharedTicker, canvas, useBackBuffer, powerPreference, eventFeatures, accessibilityOptions, gcActive, bezierSmoothness, webgl/webgpu/canvasOptions per-renderer overrides), app.stage/renderer/canvas/screen/domContainerRoot access, ResizePlugin, TickerPlugin, CullerPlugin (cullable, cullArea), custom ApplicationPlugin via ExtensionType.Application, start/stop lifecycle, and app.destroy() with releaseGlobalResources. Triggers on: Application, app.init, app.stage, app.renderer, app.canvas, app.screen, app.domContainerRoot, ApplicationOptions, ApplicationPlugin, ExtensionType.Application, resizeTo, sharedTicker, skipExtensionImports, preferWebGLVersion, preserveDrawingBuffer, cullable, CullerPlugin, app.start, app.stop, app.destroy, releaseGlobalResources." license: MIT
Application is the convenience wrapper that owns a renderer, a root stage Container, a canvas, and the Ticker/Resize plugins. In v8 the constructor takes no arguments; all configuration is passed to the async app.init() call which instantiates the renderer via autoDetectRenderer.
Quick Start
import { Application } from "pixi.js";
const app = new Application();
await app.init({
resizeTo: window,
background: "#1099bb",
antialias: true,
preference: "webgl",
autoDensity: true,
resolution: window.devicePixelRatio,
});
document.body.appendChild(app.canvas);
Related skills: pixijs-core-concepts (renderers, render pipeline), pixijs-ticker (render loop detail), pixijs-scene-container (working with app.stage), pixijs-environments (non-browser setups).
Core Patterns
Lifecycle: construct, init, render, destroy
import { Application } from "pixi.js";
const app = new Application();
await app.init({ width: 800, height: 600 });
document.body.appendChild(app.canvas);
// ... run scene, ticker drives app.render() automatically ...
app.destroy(
{ removeView: true, releaseGlobalResources: true },
{ children: true, texture: true, textureSource: true },
);
new Application()allocates the instance but creates nothing. Options passed here are ignored with a v8 deprecation warning.app.init(options)is async. It builds the renderer, wires up plugins, and must complete before you can useapp.canvas,app.renderer, orapp.screen.- The TickerPlugin calls
app.render()every frame once init resolves (unlessautoStart: false). app.destroy(rendererDestroyOptions, stageDestroyOptions)— the first argument forwards torenderer.destroy(). Passtrueor{ removeView: true }to remove the canvas from the DOM. AddreleaseGlobalResources: trueto drain global pools (batches, texture caches) when tearing down and re-creating an app in the same tab; omitting it is the usual cause of flickering and stale textures after a re-init (seepixijs-performance).
Key init options
await app.init({
width: 800,
height: 600,
background: 0x1099bb,
backgroundAlpha: 1,
antialias: true,
resolution: window.devicePixelRatio,
autoDensity: true,
preference: "webgpu",
autoStart: true,
sharedTicker: false,
resizeTo: window,
canvas: document.querySelector("#game-canvas") as HTMLCanvasElement,
});
For every option — view/canvas, background, renderer preference (including the array form), ticker, resize, culler, events, accessibility, WebGL/WebGPU context flags, Graphics bezier smoothness, GC, and per-renderer overrides (webgl / webgpu / canvasOptions) — see references/application-options.md.
Application properties
app.stage; // root Container; add all display objects here
app.renderer; // the WebGL/WebGPU/Canvas renderer instance
app.canvas; // the HTMLCanvasElement (insert it into the DOM yourself)
app.screen; // Rectangle describing the visible area in CSS pixels
app.domContainerRoot; // HTMLDivElement that holds DOMContainer overlays
app.stage is a plain Container. For scene graph detail (transforms, addChild, destroy) see pixijs-scene-container. For renderer-level operations (extract, generateTexture, custom systems) see pixijs-core-concepts and pixijs-custom-rendering. app.domContainerRoot is the <div> that the renderer uses to host DOMContainer overlays; append it next to app.canvas when you need DOM elements pinned to scene nodes (see pixijs-scene-dom-container).
ResizePlugin
Set resizeTo at init (or reassign app.resizeTo later) to have the plugin listen for the resize event and call renderer.resize() with the target element's client size. Combine with autoDensity: true and resolution: window.devicePixelRatio for high-DPI output.
await app.init({ resizeTo: window });
app.resizeTo = document.querySelector("#game-container") as HTMLElement;
app.resize(); // immediate resize to the target's current size
app.queueResize(); // defer the resize to the next animation frame
app.cancelResize(); // drop a pending queueResize
The plugin keeps the canvas matched to the target. app.screen and app.canvas.width/height update in response; read them after the resize to place UI.
app.resize()— immediate synchronous resize.app.queueResize()— coalesces rapid calls by deferring to the next frame; internally used by thewindow.resizelistener to avoid redundant work.app.cancelResize()— cancels a queued resize. Call this before tearing down your own layout code that triggeredqueueResize.
Ticker basics
The TickerPlugin creates app.ticker and registers app.render() on it at UPDATE_PRIORITY.LOW. Control the loop with app.start()/app.stop() and add callbacks with app.ticker.add / app.ticker.addOnce:
app.ticker.add((ticker) => {
sprite.rotation += 0.01 * ticker.deltaTime;
});
app.ticker.addOnce(() => {
console.log("runs once on the next frame, then removes itself");
});
app.stop(); // pause the render loop (e.g. tab hidden)
app.start(); // resume
The callback receives the Ticker instance; read ticker.deltaTime for a frame-rate-independent multiplier (~1.0 at 60fps), ticker.deltaMS for real milliseconds, or ticker.FPS for the current frame rate. See pixijs-ticker for priorities, FPS capping, onRender, shared vs private tickers, and the v8 callback signature change.
Manual render loop
await app.init({ autoStart: false, width: 800, height: 600 });
document.body.appendChild(app.canvas);
function frame() {
updateScene();
app.render();
requestAnimationFrame(frame);
}
frame();
autoStart: false prevents the TickerPlugin from starting the ticker automatically. Call app.render() yourself (or app.renderer.render({ container: app.stage }) for the same effect). If you still want registered ticker callbacks to fire, call app.ticker.update() inside your loop before app.render().
CullerPlugin (opt-in)
The CullerPlugin skips rendering containers that fall outside app.renderer.screen. It isn't registered by default; add it before creating your app:
import {
Application,
Container,
Sprite,
extensions,
CullerPlugin,
Rectangle,
} from "pixi.js";
extensions.add(CullerPlugin);
const app = new Application();
await app.init({ width: 800, height: 600 });
const world = new Container();
world.cullable = true; // this container is culled when its bounds leave the screen
world.cullableChildren = true; // default; set `false` to skip recursing into children
const tile = Sprite.from("tile.png");
tile.cullable = true;
world.addChild(tile);
app.stage.addChild(world);
Containers are not culled unless cullable is set. Override the default bounds check with container.cullArea = new Rectangle(x, y, w, h) when child bounds are expensive to compute. The plugin wraps app.render() so Culler.shared.cull(app.stage, app.renderer.screen) runs before every frame. See pixijs-performance for when culling pays off.
Custom Application plugins
Extend Application by registering a class with static init, static destroy, and static extension = ExtensionType.Application. Both methods are called with this bound to the Application instance, so this.renderer and this.stage are available.
import {
Application,
ExtensionType,
extensions,
type ApplicationOptions,
} from "pixi.js";
class FpsOverlay {
public static extension = ExtensionType.Application;
public static init(this: Application, options: Partial<ApplicationOptions>) {
// runs inside app.init() after the renderer is created
// attach props/methods to `this` to expose them on the app
}
public static destroy(this: Application) {
// runs inside app.destroy() — tear down anything you attached
}
}
extensions.add(FpsOverlay);
Plugins initialize in registration order and destroy in reverse. To add typed options for your plugin, extend PixiMixins.ApplicationOptions:
declare global {
namespace PixiMixins {
interface ApplicationOptions {
fpsOverlay?: { visible?: boolean };
}
}
}
await app.init({ fpsOverlay: { visible: true } });
The built-in ResizePlugin, TickerPlugin, and opt-in CullerPlugin all use this same contract. If you set skipExtensionImports: true, register the built-ins you need yourself (extensions.add(ResizePlugin, TickerPlugin)).
Common Mistakes
[CRITICAL] Passing options to the constructor
Wrong:
const app = new Application({ width: 800, height: 600 });
document.body.appendChild(app.canvas);
Correct:
const app = new Application();
await app.init({ width: 800, height: 600 });
document.body.appendChild(app.canvas);
In v8 the Application constructor takes no arguments. Options passed there are ignored and log a deprecation warning; the renderer is only created inside the async init() call.
[HIGH] Using app.view instead of app.canvas
Wrong:
document.body.appendChild(app.view);
Correct:
document.body.appendChild(app.canvas);
app.view was renamed to app.canvas in v8. The old getter still works but emits a deprecation warning.
[MEDIUM] Touching app.canvas or app.renderer before init resolves
Wrong:
const app = new Application();
document.body.appendChild(app.canvas);
app.init({ width: 800, height: 600 });
Correct:
const app = new Application();
await app.init({ width: 800, height: 600 });
document.body.appendChild(app.canvas);
app.renderer, app.canvas, and app.screen are only populated once the init() promise resolves. Accessing them earlier returns undefined.
API Reference
Related skills
More from pixijs/pixijs-skills and the wider catalog.

pixijs-assets
Load and manage PixiJS v8 resources with format detection, bundles, caching, and progress tracking.

pixijs-blend-modes
GPU-accelerated blend modes for PixiJS v8 display objects, from standard (add, multiply, screen) to advanced (color-burn, overlay, hard-light).

pixijs-color
Create, convert, and manipulate colors in PixiJS v8 with flexible input formats and chainable operations.

pixijs-core-concepts
Understand PixiJS v8 rendering: backend selection, render loop, and frame pipeline.

pixijs-create
Scaffold a new PixiJS v8 project or add PixiJS to an existing one with create-pixi CLI.

pixijs-custom-rendering
Write custom shaders, uniforms, filters, and low-level rendering code for PixiJS v8 with WebGL and WebGPU support.