Recipes
A recipe answers exactly one question and is completable by editing at most two files. Every one has the same five headings — Goal, Files you will edit, Steps, Verify, See also — so you can skim straight to the part you need, and npm run docs:lint refuses a recipe that does not.
If you are looking for the rules a new recipe has to follow, that is the recipe template. Everything below is a recipe you can run.
Getting started
The path from nothing to a game you are editing.
- Scaffold a new game —
npm create aosengine, a playable game in its own directory with nothing to configure. - Create an engine around a canvas — boot
@aosengine/coreyourself, for a custom host rather than a template. - Debug with doctor — take
aosengine doctorfrom red to green, one check at a time. - Use the placeholder assets — render the CC0 arena and its spawn points before you have content of your own.
Game logic
Inside the guest: systems, input, the HUD, and the component that ships them.
- Write a game system — one more function per fixed step, allocating nothing.
- Read player input — named actions, so no key code ever appears in game code.
- Add a HUD element — a value on screen that only crosses the boundary on the frames it changed.
- Build the wasm guest — the shipping path:
jco componentize,jco transpile, and what each step is for. - Write a guest in Rust — the same WIT world from a Rust crate; the host cannot tell the difference.
First-person
Recipes that build on templates/fps.
- Add a weapon — a second fire mode with its own ammunition, rate and sound.
- Add an enemy — a heavier variant sharing the existing chase-and-attack behaviour.
- Change the level — your own splat environment, your own collider, your own spawns.
Third-person
Recipes that build on templates/third-person.
- Add an interactable — a lever the hero walks up to and presses
Eat, declared with a tag, with a HUD prompt when it is in reach. - Add NPC dialogue — a third person with a script of their own, in a JSON file and a prefab, without touching the dialogue system.
- Tune the follow camera — boom length, shoulder height, pitch range, an over-the-shoulder offset, and who owns the collision.
- Add a locomotion state — a crouch on
Ctrlthat halves walk speed, reported to the animator the way idle, walk and run are.
World and physics
- Load a splat environment — a gaussian-splat capture as the world, by id, drawn in the right order.
- Add a physics body — a crate that falls, lands and reports its collisions.
- Play a sound — positional audio that falls off with distance and tells you when it ended.
Characters and animation
- Load a character — a splat avatar in the scene, by id, with a graceful answer on a machine without WebGPU.
- Load a character from the Asset Manager — the same, sourced from AAM, without a URL ever being written down.
- Play an animation on a character — idle, walk and a one-shot wave, driven from the character state game logic already produces.
- Preview a rig without decoders — a freshly baked rig on screen as one gaussian per vertex, months before anyone has trained a decoder for it.
- Give an NPC a face — wire the guest's character commands to a real splat head, so dialogue expressions and look-at are drawn rather than recorded.
The rules, in one line each
- Two files maximum. A third file means two recipes, or a design problem.
- Never
packages/. A recipe that needs an engine change is a missing feature; file it instead of documenting it. - Assets by id. Recipes add manifest entries; they never hardcode a URL.
- No allocation in systems. Recipe code is copied verbatim, by humans and by language models. Preallocate.
- Runnable code only. Snippets are checked by
npm run docs:lint.
See also
- The recipe template — the five headings, and how to write one
- Concepts — the model a recipe assumes you have
- Build your first FPS — the long-form version
- Troubleshooting — when a recipe does not do what it says