# Moonspell

> The Moonspell engine is a React Native (Expo) project set up as a game runtime, one TypeScript codebase that plays in the browser, on iOS and on Android, with a WebGPU 3D renderer on every platform.

The Moonspell engine is a React Native project set up to run games. You write one game in TypeScript and React, and the same code plays in a browser, on iOS and on Android. The 3D scene is drawn with WebGPU on every platform: three.js and React Three Fiber on top, react-native-webgpu on the phones, the browser's own WebGPU on the web.

If you know React, you already know how a Moonspell game is written. A game is a component. The scene is JSX. The HUD is React Native views. The game loop is a `useFrame` callback.

## What the engine is

The engine is an Expo app (Expo SDK 58, React Native 0.88) whose root component is a game. It comes as a template folder, `templates/crescent-game/`, that you copy and make your own. There is no npm package to install and no editor to learn: the engine is source code in `src/engine/`, and your game is source code in `src/game/`.

Inside, it wires a set of well-known libraries so they share one frame:

| Job | Library |
| --- | --- |
| 3D scene and frame loop | three.js (its WebGPU renderer) through React Three Fiber |
| GPU surface on the phones | react-native-webgpu (Dawn, Google's WebGPU implementation) |
| GPU surface in the browser | the browser's WebGPU (`navigator.gpu`) |
| HUD and 2D games | `@shopify/react-native-skia` and React Native views |
| Particles and compute shaders | TypeGPU, on the same GPU device as three.js |
| Touch and animation | react-native-gesture-handler, Reanimated |
| Sound | react-native-audio-api (a Web Audio API), expo-audio |
| Physics | cannon-es |
| Running in a browser | react-native-web |

The engine's own code is the glue and the game parts: a canvas that hosts the 3D scene, multi-touch controls that also answer to a keyboard, a HUD kit, an audio mixer, a 2D layer, saves, leaderboards and rooms. How these fit in one frame is on [How it works](https://docs.moonspell.app/start/how-it-works.md).

## The stack

```text
+------------------------------------------------------------------+
|  Your game: src/game/index.tsx                                   |
|  a React component, or one config for a genre module             |
+------------------------------------------------------------------+
|  Genre modules: racing, puzzle, shooter, kingdom                 |
+------------------------------------------------------------------+
|  Engine (src/engine): EngineCanvas, controls, HUD, audio mixer,  |
|  physics, 2D layer, character, combat, bots, saves, net, turns   |
+----------------+---------+---------+--------------+--------------+
| three.js + R3F |  Skia   | TypeGPU | Reanimated + | audio-api,   |
| (WebGPU)       |         |         | gestures     | cannon-es    |
+----------------+---------+---------+--------------+--------------+
|  React Native 0.88 + Expo SDK 58      (react-native-web in a     |
|  Hermes on the phones                  browser)                  |
+----------------------------------+-------------------------------+
|  iOS, Android                    |  Browser                      |
|  react-native-webgpu (Dawn)      |  navigator.gpu                |
+----------------------------------+-------------------------------+
```

## Why React Native for games

- **One language and one component model.** Game logic, the scene, the HUD and the menus are all TypeScript and React. A menu is a view, a spaceship is a `<mesh>`, and both re-render from the same state.
- **A real native runtime on the phones.** The game runs on Hermes inside a native app, draws through a native WebGPU implementation, and reads multi-touch through a native gesture system. It is not a web page in a wrapper.
- **The web from the same source.** Expo builds the same project for the browser with react-native-web. You get a static site you can host anywhere, with no second codebase.
- **The ecosystem.** npm, three.js and its addons, Expo's modules, and the tooling you already use for React: TypeScript, Metro, Node's test runner.

The cost is that a game cannot add native code of its own in the Moonspell app, and a phone build is a normal Expo development build. [The game contract](https://docs.moonspell.app/start/game-contract.md) lists the rules that follow from that.

## What you get on top

- **Engine pieces.** A WebGPU canvas with sky, sun and post-processing; touch controls; a HUD kit with icons, fonts and rolling counters; an audio mixer; physics; GPU particles; a 2D layer; a character controller and cameras; a combat kit; bots; saves and progression; leaderboards, presence and rooms; a turns kit with a computer opponent; a story kit. See the [engine overview](https://docs.moonspell.app/engine/overview.md).
- **Four genre modules.** A whole game from one config: an arcade racer, a grid puzzle (block, merge, match, sort), an arena shooter, and a story-led kingdom builder. See [Game modules](https://docs.moonspell.app/modules/overview.md).
- **Eleven example games.** Each is one file you can copy over the game and change. See [Examples](https://docs.moonspell.app/examples.md).
- **A backend scaffold.** A Cloudflare Worker with Durable Objects for leaderboards, rooms, synced saves and an AI opponent. See [Backend](https://docs.moonspell.app/backend/overview.md).
- **A repo shaped for coding agents.** Every game carries `CLAUDE.md`, `AGENTS.md`, 24 skills and agent-facing docs. These docs are also published as `llms.txt`, as Markdown per page, and through a docs MCP server. See [Build with AI](https://docs.moonspell.app/ai/overview.md).

## A taste

This is a complete game. It is the Moon Blocks example (`examples/moon-blocks/index.tsx`): a block puzzle with a title screen, a HUD, a pause menu, results, sounds and a leaderboard, all from the puzzle module.

```tsx
import { definePuzzleGame } from '@/engine/modules/puzzle';

export default definePuzzleGame({
  id: 'moon-blocks',
  title: 'Moon Blocks',
  description: 'Drag blocks onto the board and clear lines under the moon.',
  pack: 'block',
  mode: 'endless',
  board: { rows: 8, cols: 8 },
  block: { pieces: 'classic', tray: 3 },
  theme: {
    background: '#0B0D24',
    board: '#161A3D',
    cell: '#20264F',
    accent: '#7EE0FF',
    palette: ['#FF6B8B', '#FFB35C', '#FFE066', '#5BE38E', '#5CC8FF', '#9D7BFF'],
    tileStyle: 'glossy',
  },
});
```

When no module fits, you write the game yourself from the engine pieces. [Your first game](https://docs.moonspell.app/start/first-game.md) builds a small 3D one in about 170 lines.

## The engine and the Moonspell app

This is the engine behind the Moonspell app, where players describe a game in a chat and a coding agent builds it. The engine, the template, the examples, the skills, the server and these docs are open source under the MIT License. The source of the phone app and of the `crescent` CLI is private; the CLI is handed out in built form to developers who publish to the app. See [What is open and what is private](https://docs.moonspell.app/start/open-source.md).

There are two ways to build a game:

| Path | What you need | Where your game ends up |
| --- | --- | --- |
| **Engine only, plain Expo** | A clone of this repository. No account, nothing from Moonspell. | An Expo app you own: a static web build, or your own iOS and Android builds. [Quickstart](https://docs.moonspell.app/start/quickstart.md) |
| **Publish to Moonspell, local developer mode** | The starter and the built `crescent` CLI from moonspell.app, and a Moonspell account. | The Moonspell app on iPhone and Android and the web, public at once, with a share link. [Publish to the Moonspell app](https://docs.moonspell.app/start/publish-to-moonspell.md) |

## Where to go next

| If you want to | Read |
| --- | --- |
| Run a game in your browser now | [Quickstart](https://docs.moonspell.app/start/quickstart.md) |
| Build on your computer and publish to the Moonspell app | [Publish to the Moonspell app](https://docs.moonspell.app/start/publish-to-moonspell.md) |
| Build a small game from scratch | [Your first game](https://docs.moonspell.app/start/first-game.md) |
| Understand how React Native produces a frame | [How it works](https://docs.moonspell.app/start/how-it-works.md) |
| Know what is in a game repo | [Project structure](https://docs.moonspell.app/start/project-structure.md) |
| Look up an engine piece | [Engine overview](https://docs.moonspell.app/engine/overview.md) |
| Make a racer, puzzle, shooter or kingdom game | [Game modules](https://docs.moonspell.app/modules/overview.md) |
| Start from a finished game | [Examples](https://docs.moonspell.app/examples.md) |
| Put scores, rooms and saves online | [Backend](https://docs.moonspell.app/backend/overview.md) |
| Let Claude Code or another agent build it | [Build with AI](https://docs.moonspell.app/ai/overview.md) |
| Ship to the web, iOS or Android | [Web](https://docs.moonspell.app/platforms/web.md), [iOS](https://docs.moonspell.app/platforms/ios.md), [Android](https://docs.moonspell.app/platforms/android.md) |
| See how the hosted product works | [Architecture](https://docs.moonspell.app/moonspell/architecture.md) |
| Contribute | [Contributing](https://docs.moonspell.app/contributing.md) |
