Skip to content

Project Setup

This guide walks you through setting up a complete Web Engine Dev project from scratch using Vite and TypeScript.

Create a New Project

1. Scaffold with Vite

bash
pnpm create vite my-game -- --template vanilla-ts
cd my-game

2. Install Engine Packages

Choose one of two approaches:

bash
pnpm add @web-engine-dev/engine
bash
pnpm add @web-engine-dev/ecs @web-engine-dev/math @web-engine-dev/renderer @web-engine-dev/time

3. Configure TypeScript

Replace the contents of tsconfig.json:

json
{
  "compilerOptions": {
    "target": "ES2022",
    "lib": ["ES2022", "DOM", "DOM.Iterable"],
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "noUncheckedIndexedAccess": true,
    "isolatedModules": true,
    "verbatimModuleSyntax": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "noImplicitReturns": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src"]
}

4. Set Up the HTML Entry Point

Replace index.html:

html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>My Game</title>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      html, body { width: 100%; height: 100%; overflow: hidden; }
      canvas {
        display: block;
        width: 100%;
        height: 100%;
      }
    </style>
  </head>
  <body>
    <canvas id="game-canvas"></canvas>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>

5. Create the Entry Point

Replace src/main.ts:

typescript
import { createEngine, Game3DPreset, RenderPlugin } from '@web-engine-dev/engine';
import { createDevice } from '@web-engine-dev/renderer';

async function main() {
  // Get the canvas element
  const canvas = document.getElementById('game-canvas') as HTMLCanvasElement;

  // Create a GPU device (WebGPU runtime)
  const { device, backend } = await createDevice({
    canvas,
    preferredBackend: 'auto',
    powerPreference: 'high-performance',
  });

  console.log(`Rendering with ${backend}`);

  // Create the engine with 3D game defaults
  const engine = createEngine(Game3DPreset);

  // Add rendering plugin (registers render systems and resources)
  engine.addPlugin(RenderPlugin);

  // Initialize and start
  await engine.init();
  await engine.start();
}

main().catch(console.error);

6. Run the Dev Server

bash
pnpm dev

Open the URL shown in the terminal (usually http://localhost:5173). You should see a blank canvas with the GPU backend initialized.

Project Structure

A recommended structure for a game project:

my-game/
├── public/              # Static assets (textures, models, audio)
│   ├── textures/
│   ├── models/
│   └── audio/
├── src/
│   ├── main.ts          # Entry point
│   ├── components.ts    # Game-specific ECS component definitions
│   ├── systems.ts       # Game systems (movement, AI, etc.)
│   ├── resources.ts     # Game resources (config, state)
│   └── scenes/          # Scene setup functions
│       └── main-scene.ts
├── index.html
├── tsconfig.json
├── vite.config.ts
└── package.json

Vite Configuration

For most projects, the default Vite config works fine. For advanced setups:

typescript
// vite.config.ts
import { defineConfig } from 'vite';

export default defineConfig({
  build: {
    target: 'es2022',
  },
  optimizeDeps: {
    // Pre-bundle engine packages for faster dev startup
    include: ['@web-engine-dev/engine'],
  },
});

Engine Presets

The engine provides presets optimized for different game types:

PresetTarget FPSFixed TimestepBest For
MinimalPresetUncappedNoBare bones, custom setups
Game2DPreset601/60s2D games with physics
Game3DPreset601/60s3D games
HighPerformancePresetUncapped1/120sFast-paced games
TurnBasedPreset30NoTurn-based games
HeadlessPresetN/ANoServer-side, testing

Use presets as the base and override specific fields:

typescript
import { createEngine, Game3DPreset } from '@web-engine-dev/engine';

const engine = createEngine({
  ...Game3DPreset,
  targetFps: 120,
  maxDeltaTime: 0.1,
});

Plugin System

Plugins configure the engine with systems, resources, and integrations:

typescript
import {
  createEngine,
  Game3DPreset,
  RenderPlugin,
  InputPlugin,
  AudioPlugin,
  Physics3DPlugin,
  AnimationPlugin,
} from '@web-engine-dev/engine';

const engine = createEngine(Game3DPreset);

// Add plugins individually
engine.addPlugin(RenderPlugin);
engine.addPlugin(InputPlugin);
engine.addPlugin(AudioPlugin);
engine.addPlugin(Physics3DPlugin);
engine.addPlugin(AnimationPlugin);

Or use plugin groups for common setups:

typescript
import { createEngine, Game3DPreset, Game3DPlugins } from '@web-engine-dev/engine';

const engine = createEngine(Game3DPreset);

// Game3DPlugins includes: Input, Audio, Physics3D, Render, Particle, Animation, Scripting
engine.addPlugin(Game3DPlugins);

Available plugin groups:

  • Game2DPlugins -- Input, Audio, Physics2D, Sprite, Particle, Animation, Scripting
  • Game3DPlugins -- Input, Audio, Physics3D, Render, Particle, Animation, Scripting
  • FullPlugins -- All available plugins

Next Steps

  • First Game -- Build a playable game using this project setup
  • Quick Start -- Learn the ECS API fundamentals
  • Rendering -- Understand the rendering pipeline

Proprietary software. All rights reserved.