A Pixi.js Game You Can Play
The last article was the 3D object. This one is the 2D stage. Catch the fruit. Dodge the rotten ones. The GPU keeps the sprites at 60 fps; the score under it stays HTML. How I wire a branded minigame as a Next.js island — and why Pixi is still not a game engine.
Live stage — move to catch
Catch fruit. Dodge the wormy ones. Pointer or ← →.
I already wrote when I would pick Pixi.js over Three.js, and why a canvas on a business URL is a bill, not a decoration. Then I shipped the 3D object you can orbit. This page is the other surface: a 2D stage that must hold 60 fps while you play. The game above this paragraph is the pattern I would ship for a launch drop, a booth, or a loyalty loop — an island, lazy, disposable. The sentence you are reading is still in the document.
Move the basket. Catch apples, pears, slices. Dodge the rotten ones. Calm, arcade, storm. That is the commercial job: a few dozen sprites, a ticker, particles that die when they should. No sprite atlas download. No Phaser scene stack. Procedural graphics, a HUD in HTML, a loop that yields when you leave the viewport.
1. What you are actually looking at
Pixi.js is a 2D renderer. A display list, Graphics primitives, a ticker. The apples, pears and slices are not PNGs. They are polygons drawn on the GPU, batched, rotated in the loop. The orchard behind them is one Graphics object — sky, hills, trees — plus a few clouds that drift. Catch a fruit and a handful of sparks spawn, then die. That is the job Pixi is good at: many cheap 2D objects, every frame, without a DOM node per sprite.
There is no physics engine. Gravity is a number I add to vy. Collision is a box around the collector. Combo is a timer in the same tick. Phaser would give you scenes, arcade physics, audio. This product did not need that bill. It needed a hot stage inside a Next.js article. I cap devicePixelRatio. I drop star count when hardwareConcurrency is low. Storm is more sprites, not a heavier shader. That is the difference between a minigame that survives a recruiter’s laptop and one that cooks a mid-range Android in the subway.
2. The island, not the homepage
There is no WebGL on the server. This page is a static export. The article HTML is in the first paint. The stage is a client island: IntersectionObserver with a root margin, then a dynamic import of pixi.js, then Application.init. If you never scroll here, you never download the renderer. If you leave, the ticker skips the frame. On unmount I destroy the application, the canvas, and the GPU context. Navigate away in this app and the next article does not inherit a live WebGL session.
I did not put this on the homepage. An eager canvas hero fights LCP and then steals INP. Recruiters can wait one scroll. A customer on a launch URL can wait for the game they came to play. They cannot wait for a stage that blocked the heading. The score, the lives, the “play again” sit in HTML beside the canvas — not painted into a texture. Reduced motion slows the ticker and cuts the sparks; the stage still plays, because that is a choice, not an animation.
- Copy, score, and heading in server HTML. Canvas is not a crawler surface.
- Boot on intersection, not on route load.
- Destroy on unmount. Skip ticks off-screen. Honour prefers-reduced-motion.
3. Raw Pixi.js here. @pixi/react in a product app
I wired the renderer myself on this page so the island stays one chunk and the loop is obvious: init, tick, destroy. In a Next.js app where the stage must talk to a cart, a campaign flag, or a wallet, I would use @pixi/react. Same GPU, a display list that lives in the React tree, fewer footguns around unmount. The mistake is adopting the wrapper to spin a circle, or avoiding it when twenty sprites must stay in sync with Redux. Pick the wrapper when the product already thinks in components.
4. When I would ship this for a client
A branded minigame on a product drop. A booth that must run on a cheap laptop. A kids’ board, a loyalty catch, a reel of coins that CSS cannot hold. A Telegram mini app that is already a webview and should not grow a second engine. Not a marketing homepage that needed “to feel premium” — that brief is still CSS and GSAP. Not a jewellery SKU you orbit: that is Three.js. Not a platformer with levels and a physics world: start with Phaser or a real game engine. If WebGL fails to init, the page still has the rules in HTML. The canvas is the best path to the play, never the only one.
Conclusion: play on the GPU, keep the document
Teams hire Pixi.js when a customer stays because the stage is smooth, not because the heading is clever. They should still hire a document: title, rules, score, a fallback sentence. I ship that split as a senior web engineer — Next.js islands, a capped GPU budget, GSAP where the page is still a page. If your brief is a 2D stage that must hold 60 fps on a business URL, write via the form with the sprite count, whether it is a real game or a branded loop, and whether the same URL must rank. We will not start by dropping a canvas on the homepage “so the portfolio plays.”
Need this built, not just explained?
Web app development: Next.js, React, PostgreSQL. Direct contractor.
Ready to discuss your project?
I'm a senior web engineer specializing in React and Next.js - available for freelance projects worldwide.
Location
Kyiv, Ukraine
Upwork
View ProfileTelegram
Contact meViber
Contact me