
The TypeScript MMO Framework
Build multiplayer games faster. Modular architecture. Real-time WebSockets.
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.
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',
},Combat, items, quests, crafting, skills, multiplayer rooms: each system is a module. Depend on what you need, ignore the rest.
Full type safety, server to client.
WebSockets with room management.
MySQL/PostgreSQL with Prisma. Shared accounts, per-game data.
JWT, rate limiting, sessions out of the box.
Game data lives in YAML. Edit items, quests, skills, and changes hot-reload instantly. No server restart needed.
And much more in
28 modules
Your game is a module. Create a folder, declare dependencies, and start building. Wyrt handles multiplayer, persistence, and real-time sync.
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');
}
}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 });
}
};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: 15Tested, documented, and ready to use. Mix and match for your game.