Installation
Quick Start
Section titled “Quick Start”Scaffold a new game project with the CLI:
npx @doodle-engine/cli create my-gameThe scaffolder will prompt you:
- Project name: directory name for your game
- Use default renderer?: whether to include the batteries-included
GameRendereror start with a custom setup
Then install and run:
cd my-gamenpm install # or: yarn install / pnpm installnpm run dev # or: yarn dev / pnpm devYour game is now running at http://localhost:3000.
Manual Setup
Section titled “Manual Setup”If you prefer to set up manually, install the packages:
npm install @doodle-engine/core @doodle-engine/reactnpm install -D @doodle-engine/cli viteYou’ll need:
- Node.js 24+
- npm, yarn, or pnpm
- TypeScript 5.7+
package.json
Section titled “package.json”{ "scripts": { "dev": "doodle dev", "build": "doodle build", "validate": "doodle validate", "preview": "vite preview" }, "dependencies": { "@doodle-engine/core": "latest", "@doodle-engine/react": "latest", "react": "^19.0.0", "react-dom": "^19.0.0" }, "devDependencies": { "@doodle-engine/cli": "latest", "vite": "^6.0.0" }}Entry Point
Section titled “Entry Point”Create src/main.tsx:
import { createRoot } from 'react-dom/client';import App from './App';import './index.css';
createRoot(document.getElementById('root')!).render(<App />);Create src/App.tsx using GameShell:
import { useEffect, useState } from 'react';import type { ContentRegistry, GameConfig, AssetManifest,} from '@doodle-engine/core';import { GameShell } from '@doodle-engine/react';
export default function App() { const [content, setContent] = useState<{ registry: ContentRegistry; config: GameConfig; } | null>(null); const [manifest, setManifest] = useState<AssetManifest | null>(null);
useEffect(() => { Promise.all([ fetch('/api/content').then((res) => res.json()), fetch('/api/manifest').then((res) => res.json()), ]).then(([contentData, manifestData]) => { setContent({ registry: contentData.registry, config: contentData.config, }); setManifest(manifestData); }); }, []);
if (!content || !manifest) return ( <div className="app-bootstrap"> <div className="spinner" /> </div> );
return ( <GameShell registry={content.registry} config={content.config} manifest={manifest} title="My Game" /> );}GameShell now requires a manifest prop. The manifest is served by npm run dev at /api/manifest and generated by npm run build at dist/api/manifest. It tells the engine what assets to load and when.
In production, npm run build generates a service worker (dist/sw.js) that precaches all game assets. Assets load progressively before each screen renders, so portraits, music, and backgrounds are ready before the player sees them.
Content Directory
Section titled “Content Directory”Create a content/ directory with at minimum:
content/game.yaml: game configurationcontent/locations/: location YAML filescontent/locales/en.yaml: English strings
See Project Structure for the full layout.