pixijs-core-concepts — Claude Code skill: PixiJS v8 rendering
Explains how PixiJS v8 puts frames on screen: backend selection, the render loop, RenderTexture work and context loss recovery.
npx skills add pixijs/pixijs-skills --skill pixijs-core-concepts -a claude-codeWhat pixijs-core-concepts does
This skill covers what happens under the hood when PixiJS v8 renders. The renderer is built from systems and pipes: lifecycle services for textures, buffers, state, filters and masks, plus instruction builders for sprites, graphics, mesh, particles, text and tiling. It also walks through how autoDetectRenderer picks between WebGLRenderer, WebGPURenderer and CanvasRenderer, and how app.ticker.add() drives per-frame work.
A section on common mistakes comes with code samples. The big one: Application.init() is async, so app.renderer, app.canvas and app.screen do not exist until the promise resolves. Another: call DOMAdapter.set(WebWorkerAdapter) before init(), otherwise the wrong adapter is baked into the renderer. And preference is a hint, not a demand — if the browser lacks WebGPU, PixiJS falls back to WebGL or Canvas, so branch on renderer.name for backend-specific code.
Two reference files go deeper: references/renderers.md on preference forms and per-renderer options, references/render-loop.md on priority order and manual rendering. Related topics live in separate skills — pixijs-application, pixijs-ticker, pixijs-environments, pixijs-custom-rendering. Rendering into a texture works by passing target to renderer.render(), or by building a RenderTarget with explicit color and depth attachments.
What it helps with
- figure out which backend PixiJS will pick and why
- trace the order of ticker callbacks against the draw call
- render the stage into a RenderTexture or a custom RenderTarget
- fix a crash from reading
app.rendererbeforeawait app.init() - plan recovery for WebGL context loss or WebGPU device loss
Example prompts for the agent
- explain how PixiJS v8 chooses between WebGPU and WebGL and what autoDetectRenderer does
- why is app.renderer undefined right after init and how do I fix it
- render app.stage into a RenderTexture and extract the texture from it
How to install pixijs-core-concepts
1Skills CLI (Vercel)
npx skills add pixijs/pixijs-skills --skill pixijs-core-concepts -a claude-code2Manually: put the files in place
~/.claude/skills/pixijs-core-concepts/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/pixijs-core-concepts/
1Skills CLI (Vercel)
npx skills add pixijs/pixijs-skills --skill pixijs-core-concepts -a codex2Manually: put the files in place
.agents/skills/pixijs-core-concepts/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add pixijs/pixijs-skills --skill pixijs-core-concepts -a cursor2Manually: put the files in place
.cursor/skills/pixijs-core-concepts/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install pixijs/pixijs-skills pixijs-core-concepts2Manually: put the files in place
.github/skills/pixijs-core-concepts/SKILL.md1Skills CLI (Vercel)
npx skills add pixijs/pixijs-skills --skill pixijs-core-concepts -a gemini-cli2Platform CLI
gemini skills install https://github.com/pixijs/pixijs-skills --path skills/pixijs-core-conceptsManually: put the files in place
.devin/skills/pixijs-core-concepts/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add pixijs/pixijs-skills --skill pixijs-core-concepts -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about pixijs-core-concepts
How do I install pixijs-core-concepts in Claude?
Run npx skills add pixijs/pixijs-skills --skill pixijs-core-concepts -a claude-code. The skill then lives at ~/.claude/skills/pixijs-core-concepts/SKILL.md.
What does pixijs-core-concepts do?
It documents how PixiJS v8 renders frames: the systems-and-pipes renderer, the render loop, backend selection, rendering into textures, and recovery from context or device loss.
Why doesn't preference: "webgpu" guarantee WebGPU?
It is a hint. Without browser support PixiJS falls back to WebGL or Canvas, so check app.renderer.name before using backend-specific features.
Source text
SKILL.md · MIT
---
name: pixijs-core-concepts
description: "Use this skill when understanding how PixiJS v8 renders frames: the systems-and-pipes renderer, the render loop, and how the library adapts to different environments. Covers WebGLRenderer/WebGPURenderer/CanvasRenderer selection, renderer.render() pipeline, environment detection, rendering into RenderTextures and RenderTargets (flipY, mipLevel, layer, bind/push/pop, copyDepthTexture), WebGL context loss and WebGPU device loss recovery, and pointers to per-topic deep dives. Triggers on: renderer, WebGL, WebGPU, Canvas, render loop, render pipeline, systems, environments, autoDetectRenderer, RenderTexture, RenderTarget, render to texture, flipY, mipLevel, layer, 3D texture, depth slice, renderTarget.bind, copyToTexture, copyDepthTexture, depth-only, WebGLLoader, WebGPULoader, CanvasLoader, RendererLoader, lazy-load renderer systems, code splitting, context lost, webglcontextlost, device lost, GPUDevice.lost."
license: MIT
---
Foundational model for how PixiJS v8 gets pixels on the screen: the renderer decides which GPU backend to use, the render loop drives per-frame work, and the environment layer adapts the library to browser, Web Worker, or SSR contexts. For the scene graph itself (Containers, transforms, destroy), see `pixijs-scene-core-concepts`.
## Quick Start
```ts
console.log(app.renderer.name); // 'webgl' | 'webgpu' | 'canvas'
app.ticker.add((ticker) => {
sprite.rotation += 0.01 * ticker.deltaTime;
});
const tex = app.renderer.extract.texture({ target: app.stage });
app.renderer.render({ container: app.stage });
```
`app.renderer` is the `WebGLRenderer`, `WebGPURenderer`, or `CanvasRenderer` chosen by `autoDetectRenderer`. The TickerPlugin drives `renderer.render()` automatically; call it manually only with `autoStart: false`. Backend selection happens in `Application.init({ preference })`; see `pixijs-application` for setup.
**Related skills:** `pixijs-application` (Application construction and lifecycle), `pixijs-ticker` (per-frame logic, priorities, FPS capping), `pixijs-environments` (Web Worker, SSR, strict CSP), `pixijs-custom-rendering` (writing a RenderPipe), `pixijs-scene-core-concepts` (scene graph basics).
## Topics
| Topic | Reference | When |
| ------------------- | ------------------------------------------------------ | --------------------------------------------------------- |
| Choosing a backend | [references/renderers.md](references/renderers.md) | Preference forms, per-renderer options, systems and pipes |
| Per-frame execution | [references/render-loop.md](references/render-loop.md) | Priority order, time units, manual rendering |
For deep dives into any single topic, open the corresponding reference file. Non-browser targets (`DOMAdapter`, `WebWorkerAdapter`, custom adapters, strict CSP) are covered in the `pixijs-environments` skill.
## Decision guide
- **Setting up an Application?** Start with `pixijs-application`. This skill explains what the renderer does under the hood.
- **Choosing between WebGL and WebGPU?** Use `['webgpu', 'webgl']` as your preference array. WebGPU is fastest where available; WebGL is the reliable fallback. See `references/renderers.md`.
- **Running in a Web Worker?** Set `DOMAdapter.set(WebWorkerAdapter)` before `app.init`. See the `pixijs-environments` skill for complete setup.
- **Need manual control over when rendering happens?** Set `autoStart: false` and call `app.renderer.render(app.stage)` from your own loop. See `references/render-loop.md`.
- **Integrating with a physics library?** Add your update at `UPDATE_PRIORITY.HIGH` so physics runs before the render at `LOW`. See `references/render-loop.md`.
- **Writing a custom renderable?** Implement a `RenderPipe`. See `pixijs-custom-rendering` skill.
- **Rendering into a texture or a custom render target?** Pass `target` to `renderer.render()`, or build a `RenderTarget` with explicit color and depth attachments. See `references/renderers.md`.
- **Running under strict CSP?** Import `'pixi.js/unsafe-eval'`. See the `pixijs-environments` skill.
## Quick concepts
### Renderer = systems + pipes
Each renderer is composed of `Systems` (lifecycle services: textures, buffers, state, filters, masks) and `RenderPipes` (per-renderable instruction builders: sprite, graphics, mesh, particle, text, tiling). Writing a custom renderable means implementing a `RenderPipe` and registering it via extensions. Backend-specific systems and pipes can be dynamic-imported through a renderer loader extension (`WebGLLoader`, `WebGPULoader`, `CanvasLoader`); see `references/renderers.md`.
### The render loop
`app.ticker.add(fn)` registers a callback that runs every frame. The `TickerPlugin` registers `app.render()` at `UPDATE_PRIORITY.LOW`, so ticker callbacks at `NORMAL` or `HIGH` run before the draw. Disable the plugin with `autoStart: false` for manual control.
### Environments
`DOMAdapter` abstracts every DOM call PixiJS makes (canvas creation, image loading, fetch, XML parsing). Swap with `DOMAdapter.set(WebWorkerAdapter)` for Workers or implement a custom `Adapter` for Node/SSR. Must be done before `Application.init`.
## Common Mistakes
### [HIGH] Accessing app.renderer before init() resolves
Wrong:
```ts
const app = new Application();
app.init({ width: 800, height: 600 });
console.log(app.renderer.name); // undefined — init() is async
```
Correct:
```ts
const app = new Application();
await app.init({ width: 800, height: 600 });
console.log(app.renderer.name); // 'webgl' | 'webgpu' | 'canvas'
```
`Application.init()` is async. `app.renderer`, `app.canvas`, and `app.screen` do not exist until after the promise resolves.
### [HIGH] Setting DOMAdapter after Application.init
Wrong:
```ts
const app = new Application();
await app.init({ width: 800, height: 600 });
DOMAdapter.set(WebWorkerAdapter); // too late — init already allocated resources
```
Correct:
```ts
DOMAdapter.set(WebWorkerAdapter);
const app = new Application();
await app.init({ width: 800, height: 600 });
```
The adapter abstracts DOM calls the renderer makes during construction (canvas creation, image loading, fetch). Swap it before `init()` or the wrong adapter is baked into the renderer.
### [MEDIUM] Treating `preference` as a guarantee
Wrong:
```ts
await app.init({ preference: "webgpu" });
// assume WebGPU is active
useWebGPUOnlyFeature(app.renderer);
```
Correct:
```ts
await app.init({ preference: "webgpu" });
if (app.renderer.name === "webgpu") {
useWebGPUOnlyFeature(app.renderer);
}
```
`preference` is a hint, not a demand. If the browser lacks WebGPU support, PixiJS falls back to WebGL (or Canvas). Always branch on `renderer.name` for backend-specific code.
## API Reference
- [autoDetectRenderer](https://pixijs.download/release/docs/rendering.autoDetectRenderer.html.md)
- [AbstractRenderer](https://pixijs.download/release/docs/rendering.AbstractRenderer.html.md)
- [WebGLRenderer](https://pixijs.download/release/docs/rendering.WebGLRenderer.html.md)
- [WebGPURenderer](https://pixijs.download/release/docs/rendering.WebGPURenderer.html.md)
- [CanvasRenderer](https://pixijs.download/release/docs/rendering.CanvasRenderer.html.md)
- [Application](https://pixijs.download/release/docs/app.Application.html.md)
- [DOMAdapter](https://pixijs.download/release/docs/environment.DOMAdapter.html.md)
© pixijs · MIT · pixijs/pixijs-skills