Skip to main content

Moonspell

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:

JobLibrary
3D scene and frame loopthree.js (its WebGPU renderer) through React Three Fiber
GPU surface on the phonesreact-native-webgpu (Dawn, Google's WebGPU implementation)
GPU surface in the browserthe browser's WebGPU (navigator.gpu)
HUD and 2D games@shopify/react-native-skia and React Native views
Particles and compute shadersTypeGPU, on the same GPU device as three.js
Touch and animationreact-native-gesture-handler, Reanimated
Soundreact-native-audio-api (a Web Audio API), expo-audio
Physicscannon-es
Running in a browserreact-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.

The stack​

+------------------------------------------------------------------+
| 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 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.
  • 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.
  • Eleven example games. Each is one file you can copy over the game and change. See Examples.
  • A backend scaffold. A Cloudflare Worker with Durable Objects for leaderboards, rooms, synced saves and an AI opponent. See Backend.
  • 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.

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.

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 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.

There are two ways to build a game:

PathWhat you needWhere your game ends up
Engine only, plain ExpoA 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
Publish to Moonspell, local developer modeThe 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

Where to go next​

If you want toRead
Run a game in your browser nowQuickstart
Build on your computer and publish to the Moonspell appPublish to the Moonspell app
Build a small game from scratchYour first game
Understand how React Native produces a frameHow it works
Know what is in a game repoProject structure
Look up an engine pieceEngine overview
Make a racer, puzzle, shooter or kingdom gameGame modules
Start from a finished gameExamples
Put scores, rooms and saves onlineBackend
Let Claude Code or another agent build itBuild with AI
Ship to the web, iOS or AndroidWeb, iOS, Android
See how the hosted product worksArchitecture
ContributeContributing