Open-source project
pixijs/pixijs avatar
pixijs/pixijs

PixiJS: the async app.init, the @types/web switch, and a dev default branch

GitHub describes it as The HTML5 Creation Engine: Create beautiful digital content with the fastest, most flexible 2D WebGL renderer.. The repository metadata lists TypeScript as its primary language. The metadata lists the MIT license. This article stays within the project description and details documented in the GitHub repository README.

48,229 stars5,075 forksTypeScriptMIT

At a glance

What is it?
PixiJS is an MIT-licensed 2D WebGL and WebGPU renderer written in TypeScript, published as the npm package pixi.js. The repository's own files show where the friction sits: an install that names no version, a WebGPU type swap that changes with your TypeScript release, and a feature list that stops at the drawing layer.
Who is it for?
Adopt PixiJS when the work is 2D on the web and you are willing to own the scene, the physics and the input handling, because none of those arrive with the package. Skip it if you want a game framework that hands you those layers, and do not justify the choice with the speed claim in the README, since no script in the manifest measures a frame.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 26, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Two install commands, and neither one names a version

The setup section gives two routes and they differ in what you are left holding. One runs the create generator and produces a project:

bash
npm create pixi.js@latest

The other attaches the library to a codebase you already have:

bash
npm install pixi.js

The generated project comes from the CLI behind the first command, at pixijs.io/create-pixi/, and the README frames it as getting set up in one command. Neither line pins anything. The scaffold asks the registry for latest by definition, and the plain install resolves whatever range your project already declares, so the lockfile is the only thing that records which copy of the library you actually received. That matters more than it sounds for a renderer, where a change to filters or blend modes changes pixels rather than throwing an error.

Note the naming before you search for the package. The repository is pixijs/pixijs, the package on the registry is pixi.js, and the import statement in the usage example reads from pixi.js. Licence is MIT in both the package.json field and the licence section, funding points at an OpenCollective page, and there is no commercial tier between the code and your build.

app.init is awaited, and app.canvas is yours to append

The renderer does not exist until init resolves, which is why the usage example wraps itself in an async IIFE and awaits before touching anything:

typescript
import { Application, Assets, Sprite } from 'pixi.js';

(async () =>
{
    // Create a new application
    const app = new Application();

    // Initialize the application
    await app.init({ background: '#1099bb', resizeTo: window });

Those two options are the whole configuration in the example. background sets the clear colour, resizeTo: window ties the surface to the window, and no other key appears anywhere in it, so the defaults you inherit are the ones you did not write. Only after the await does the canvas become available, and the library hands you the DOM node instead of inserting it:

typescript
    // Append the application canvas to the document body
    document.body.appendChild(app.canvas);

    // Load the bunny texture
    const texture = await Assets.load('https://pixijs.com/assets/bunny.png');

    // Create a bunny Sprite
    const bunny = new Sprite(texture);

    // Center the sprite's anchor point
    bunny.anchor.set(0.5);

Assets.load is a promise over a network request to a file on pixijs.com, so the first sprite costs a round trip and a failed one leaves you with a rejected promise and nothing to draw. anchor.set(0.5) moves the origin to the sprite's middle so scaling and rotation pivot where you expect. One gap worth knowing before you paste it: the snippet stops mid function, with the closing of the async IIFE not shown, so treat it as a shape to finish rather than a module that runs as printed.

TypeScript 6 and 7 need @types/web because dom leaves out GPUTextureUsage

Supporting WebGPU means the type declarations depend on the WebGPU types, and where those come from depends on your compiler. On TypeScript 5 no WebGPU types are built in, so PixiJS adds @webgpu/types for you and asks for no extra setup. On TypeScript 6 and 7 the WebGPU types are built into the dom library, but some releases leave parts out, GPUTextureUsage named as one, so the full set comes from @types/web and goes in place of dom:

bash
npm install --save-dev @types/web
json
{
  "compilerOptions": {
    "lib": ["esnext"],
    "types": ["@types/web"]
  }
}

Read that compilerOptions block rather than skimming it. lib narrows to esnext and the types array lists @types/web, so dom is gone rather than merged, and any earlier @webgpu/types entry has to be removed because it conflicts with the built-in declarations. Skip that removal and you have two definitions of the same WebGPU interfaces in one program, and the compiler reports duplicate identifiers without telling you which package to drop. Because the same renderer source is expected to compile under both setups, this is the first thing to check when a WebGPU path type-checks on a colleague's machine and not on yours.

TypeScript under 6.0 reads lib/index.legacy.d.ts, a different declaration surface

The manifest points types at lib/index.d.ts and then adds a typesVersions map that sends any compiler below 6.0 to lib/index.legacy.d.ts instead. One published version, two declaration surfaces, selected by whoever is consuming it. For an adopter on an older compiler that is a real difference: a member you read in the current declarations can be absent from the file your build actually loads, and the repository does not say which members the legacy file drops, so you end up inferring the surface from editor squiggles rather than from a compatibility note.

The same manifest splits the module formats, with main at lib/index.js and module at lib/index.mjs, so your bundler picks CommonJS or ESM from those fields and the interop cost lands in your build rather than in the library. The files array is broader than the runtime: it lists lib, dist, transcoders and skills, so a published install carries transcoding assets and a skills directory whether you use them or not. Check the size of that tarball before adding pixi.js to a bundle that ships on every page load.

vert, frag and wgsl compile as source, so a shader edit is a build step

The build treats shaders as source files rather than as data. The watch task in package.json watches ./src/* for the extensions ts, js, vert, frag, wgsl and d.ts, which is the clearest signal in the repository that GLSL-style vert and frag files and WGSL files live beside the TypeScript and are compiled in the same pass. Two consequences follow for anyone working on the library itself.

A dev loop that reloads only TypeScript leaves your previous shader bytes in place, and the symptom is a scene still rendering the old effect while the code you just edited looks correct. And because main and module point into lib/, editing src changes nothing until node ./scripts/build.mts writes the lib output, so a contributor expecting a live-reload dev server has to run the watch task rather than point a bundler straight at src.

Documentation is built on a separate path again. The build:docs task runs typedoc against .configs/typedoc.json and then a script that converts the generated HTML to Markdown, and the API docs link in the README header points at a generated site under pixijs.download rather than at files you can read in the repository. Reading the source in types/ and the examples is closer to ground truth than the published reference when the two disagree.

Two renderers are named, and neither selection nor fallback is documented

The feature list opens with WebGL and WebGPU renderers, then claims unmatched performance and calls the library the fastest and most lightweight 2D library available for the web. No number sits behind either sentence, and nothing in the manifest measures anything: the scripts defined there are build, build:lib, build:docs, build:status, dist, clean and the watch tasks, none of which profile a frame. That claim cannot carry the decision. If the renderer path is the reason you are considering this library, you have to measure it against what you would otherwise use.

The same silence has a sharper edge. Naming two renderers is not the same as documenting how one is picked, and the README does not say whether a device without WebGPU falls back to WebGL, what happens when no context can be created, or which browser versions are supported at all. For anyone shipping to a mixed device fleet that gap is the difference between a graceful downgrade and an empty canvas on the machines you did not test. There is no renderer selection flag or configuration key anywhere in this material to point at, so if that fallback matters, you have to find it in the guides or the examples and confirm it yourself.

Everything above Sprite is yours: no scene, no physics, no audio

What ships is a renderer and an asset pipeline, and the examples directory shows how thin the layer above it is. The files are named after building blocks: container_tinting.ts, container_inverse-mask.ts, container_transform_pivot_basic.ts, container_cache-as-texture_optimization.ts, events_dragging.ts, events_custom-hitarea.ts. Every one is a piece you assemble yourself. Nothing in what the project documents provides a scene manager, a physics body, an audio channel or a timeline, and the capability list stops at the asset loader, mouse and multi-touch, text rendering, primitives and SVG drawing, dynamic textures, masking, filters and blend modes.

That is where the Phaser question gets settled. Phaser is a game framework that brings scenes, physics and audio with it; PixiJS is the drawing layer with those same three left for you to write. The honest comparison is about which of those you want to own, not about which renders faster.

Two example filenames hint at the costs. container_cache-as-texture_optimization.ts means baking a container into a texture, trading memory and bake time for fewer draw calls, which is a decision you make per object and can reverse as the scene grows. dom-container_html-text-area.ts exists because a canvas cannot host a real HTML text area, so text input, caret movement and IME composition have to come from a DOM element layered on top, and you manage the two together.

dev is the default branch, and three releases landed in four weeks

The default branch is dev, and package.json reads 8.21.0, matching the newest tag v8.21.0 released on 2026-09-17. Below it sit v8.20.1 on 2026-08-26 and v8.20.0 on 2026-08-20, and the last push to the repository was on 2026-09-25. A minor-version cadence measured in weeks lands directly on anyone who installed without pinning, since the two commands name no version, and pixel-level changes in masking, filters or blend modes can arrive without a major bump ever appearing. Commit a lockfile on the first install and move versions deliberately.

The rest is ordinary open source. MIT covers both the package and the documentation, with no copyleft obligation reaching your own code, and the contributing route is a read of .github/CONTRIBUTING.md before opening a pull request. The root declares examples and playground as workspaces, so a clone installs two extra packages you did not ask for, and the dist task copies the built output into .s3_uploads, a path the clean script also deletes along with .pr_uploads. Release artifacts pass through a dot-directory on the maintainer machine, which is worth knowing before you script anything around this repository.

Editorial conclusion

Adopt PixiJS when the work is 2D on the web and you are willing to own the scene, the physics and the input handling, because none of those arrive with the package. Skip it if you want a game framework that hands you those layers, and do not justify the choice with the speed claim in the README, since no script in the manifest measures a frame. Verify two things first: that your compiler version matches the types path, because TypeScript below 6.0 silently reads lib/index.legacy.d.ts, and that your target devices resolve the renderer you expect, because the repository documents no fallback from WebGPU.

Frequently asked questions

What is PixiJS used for?

PixiJS is a 2D rendering library for the web, written in TypeScript and released under the MIT License. It draws through WebGL and WebGPU renderers and includes an asset loader, text rendering, masking, filters and blend modes, and the project describes its target as rich, interactive graphics and cross-platform applications.

How do I install PixiJS?

Run npm create pixi.js@latest to scaffold a new project through the PixiJS Create CLI, or npm install pixi.js to add the library to an existing one. The package name on the registry is pixi.js even though the repository is pixijs/pixijs, and neither command pins a version.

Does PixiJS use WebGPU?

Yes. The capability list names both WebGL and WebGPU renderers, and the type declarations depend on the WebGPU types. On TypeScript 6 and 7 that means installing @types/web and using it in place of the dom library, while TypeScript 5 needs no extra setup because PixiJS adds @webgpu/types for you.

Is PixiJS better than Phaser?

PixiJS is the rendering layer: WebGL and WebGPU drawing, an asset loader, masks, filters and blend modes, with no scene system, physics or audio documented. Phaser is a full game framework, so the choice turns on whether you want to build those layers yourself.

Is PixiJS a game engine or a framework?

It presents itself as a 2D library and an HTML5 creation engine, not a game engine. What is documented is a renderer, an asset loader and input events, and nothing in the project supplies a scene, physics or audio layer.

Is PixiJS free?

Yes. The content is released under the MIT License and the license field in package.json reads MIT, with support requested through an OpenCollective page. The repository is not archived, and the last push was on 2026-09-25.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
  4. Release notes
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pixijs-pixijs.svg)](https://hysenlabs.com/projects/pixijs-pixijs)