Wyrt Engine Logo

Wyrt Engine

The TypeScript MMO Framework

Build multiplayer games faster. Modular architecture. Real-time WebSockets.

Multiplayer in one line

Frostholm is a Glyft game with one network rule. Every player in it is another browser connected to Wyrt's wyrt_sync module: walking, jumping, riding the shared horse and sailing the shared boat.

Guests, rooms, no database

Players join a room by name. Each one moves on their own screen with no lag and Wyrt passes their state to everyone else, who see them glide between updates. Late joiners find the horse where it was left.

// In a Glyft game's config: everyone in the room sees each other
network: {
  server: 'wss://your-server.example/sync',  // Wyrt with wyrt_sync
  room: 'frostholm',
  name: 'Ada',
},

Pick only what you need

Combat, items, quests, crafting, skills, multiplayer rooms: each system is a module. Depend on what you need, ignore the rest.

TypeScript First

Full type safety, server to client.

Real-time Sync

WebSockets with room management.

Database Ready

MySQL/PostgreSQL with Prisma. Shared accounts, per-game data.

Auth Built-in

JWT, rate limiting, sessions out of the box.

Iterate without restarting

Game data lives in YAML. Edit items, quests, skills, and changes hot-reload instantly. No server restart needed.

And much more in
28 modules

How It Works

Your game is a module. Create a folder, declare dependencies, and start building. Wyrt handles multiplayer, persistence, and real-time sync.

1. Create Your Game Module

Your game is just a module. Declare dependencies and get instant access to combat, inventory, skills, and more.

// modules/my_game/index.ts
export default class MyGame implements IModule {
  name = 'my_game';
  dependencies = ['wyrt_combat', 'wyrt_skills', 'wyrt_items'];

  async initialize(context: ModuleContext) {
    // Create game-scoped managers
    this.combat = context.getModule('wyrt_combat')
      .createCombatManager('my_game');
    this.skills = context.getModule('wyrt_skills')
      .createSkillManager('my_game');
  }
}

2. Handle WebSocket Requests

Define request handlers with built-in auth and rate limiting. Auto-registered from the requests/ folder.

// modules/my_game/requests/attack.ts
export default {
  cost: 5,     // Rate limit cost
  auth: true,  // Requires JWT

  async exec(user, data, payload, context) {
    const combat = context.getModule('wyrt_combat')
      .getCombatManager('my_game');

    const result = combat.attack(user.id, payload.targetId);
    user.send({ type: 'attack_result', ...result });
  }
};

3. Define Content in YAML

Game data lives in YAML files. Edit and save, and changes hot-reload instantly without restarting the server.

# modules/my_game/data/items/weapons.yaml
Iron_Sword:
  name: "Iron Sword"
  type: weapon
  damage: [8, 12]
  requirements:
    level: 5

Steel_Axe:
  name: "Steel Axe"
  type: weapon
  damage: [12, 18]
  requirements:
    level: 10
    strength: 15