Make a game for PocketVibe
Describe a game to your AI coding tool, play it in your browser, then on your own handheld, and send it to the store. Games are three.js web pages; the starter project and our brief teach your AI the handheld, so the game runs at 60 fps there too.
From an idea to the store
-
1
Start the project
You need Node.js 22 or newer and an AI coding tool such as Claude Code, Codex or Cursor.
npm create pocketvibe@latest my-game cd my-game npm install -
2
Give your AI the brief, then your idea
The brief holds the handheld's measured limits, the rules that keep a game smooth there, and how to try it and publish it. Start your AI tool in the project's folder and tell it:
Read https://pocketvibe.cobanov.dev/agents.md and follow it. Then make me a PocketVibe game: a snowboard race down a mountain, dodging trees.The project's own
AGENTS.mdhas the same rules in more detail, with code; your AI reads it too. -
3
Play it in your browser
npm run devshows the game at the handheld's size. Arrows are the d-pad; X is A, Z is B, S is X, A is Y, Q and W are L and R, Enter is Start and Shift is Select. P shows the performance overlay, which turns red when the game is too heavy for the handheld. The links under the screen try the other screen shapes. -
4
Play it on your handheld
With the handheld on the same network as your computer, run this in the game's folder:
npx pocketvibe serveIt prints an address like
http://192.168.1.20:8740. In PocketVibe on the handheld, open Settings > Stores > Add a store and type it. Your game is then in the Store tab as "(dev)": A downloads it. Each change you make is built again, and the Store offers it as an update. Works on ROCKNIX and Android. -
5
Send it to the store
Fill in
pocketvibe.json(a uniqueid, the title, version1.0.0, a description, the genre and the controls) and add a 480×270cover.png. Store games are open source: put yours in a public GitHub repository (gh repo create my-game --public --source . --push), then:npx pocketvibe publishIt opens a pull request to the store's repository, like F-Droid: the game is built from its source and checked there, we play it, and once it is merged it is on every PocketVibe handheld.
-
6
Update it
Raise
versioninpocketvibe.json, commit, push and publish again. Players get the update in the Store.
What the handheld can draw
Games are written for the weakest handheld PocketVibe runs on: an Allwinner H700 with four Cortex-A53 cores, a Mali-G31 MP2 GPU and 1 GB of memory, behind a 720×480 screen. Code that is instant on a laptop can run at 5 fps there. We measured these limits on an Anbernic RG34XX SP, raising one cost at a time until the frame rate fell. A game has 16.7 ms per frame for 60 fps.
| What | For 60 fps | Past it |
|---|---|---|
| Triangles inside the view | 10,000 | 15,000: 48 fps · 20,000: 39 fps · 30,000: 28 fps |
| Draw calls | 100 | about 30 µs each |
| Materials | Lambert, Basic, Toon | Phong 54 fps · Standard 37 fps · Physical 29 fps |
| Lights | 1 hemisphere + 1 directional | each point light about 3 ms · 4 of them: 37 fps |
| Shadows | none | the cheapest shadow map: 36 fps |
| Transparent layers over the screen | 1 | 2: 52 fps · 4: 41 fps |
| Particles | 1,000 small | 5,000 small: 39 fps |
| Post-processing | none | FXAA 45 fps · bloom 40 fps |
| Your own JavaScript | 8 ms a frame | the CPU is about ten times slower than a laptop's |
| Memory for assets | 150 MB | the system struggles past about 300 MB |
The first use of anything costs a long frame, so a game prepares everything while it loads:
| First use of | Costs | |
|---|---|---|
| A material (shader compile) | 40 to 120 ms | 300 ms with shadows |
| A PNG texture | 30 ms | 512×512; 100 ms at 1024×1024 |
| A 50,000-triangle geometry | 130 ms | uploaded on first draw |
How games stay inside it
- Triangles outside the view cost almost nothing: a short camera
farwith fog to hide the cut, and low-poly models. - Repeated things (coins, trees, enemies, bullets) drawn as one
InstancedMeshper kind. - Static scenery merged into one mesh per material, then
.toNonIndexed(): this engine spends CPU time every frame on large indexed meshes. - The HUD in HTML, updated only when a value changes; no
backdrop-filter. - 2D games made with three.js too: a plain 2D canvas is slow here.
- Every material compiled and every texture uploaded while the game loads.
- When a scene still does not fit, drawn at half resolution: 20,000 triangles went from 27 to 60 fps.
The performance guide explains each limit with code, and the full results have every measurement.
Screens and buttons
- Screen shapes. Designed for 720×480, a game can also fit 4:3, 16:9 and square screens; it then says
"responsive": truein its listing. Otherwise it shows at 720×480 with black bars. - Two screens. On a two-screen handheld such as the Anbernic RG DS, a game can put a map or a menu on the second screen (
"screens": 2). Without it, the second screen shows the game's controls. - Buttons. D-pad, A, B, X, Y, L, R, Start and Select. A confirms or jumps, B goes back, Start pauses. Holding Start and Select leaves the game, so games never use that pair.
- Saves.
hh.save()andhh.load(); each game keeps its own. - Offline. Games load nothing from the internet.
What we check before a game goes into the store
- It is a finished game, not a test or a demo: a title screen, a goal, a way to win or lose, and a way to play again.
- It plays smoothly on the handheld, close to 60 fps in its busiest moment.
- Everything works with the buttons alone, and the hints on screen name them.
- It works offline.
- Its listing is complete, with a cover that shows the game.
- It is suitable for everyone, and you have the right to use every image, sound and model in it.
- Its repository is public and open source, and the zip is under 50 MB.
Everything happens in the open, on the game's pull request: what the check found, what we ask to change, and why. Questions and ideas are welcome on GitHub.