TypeScript + React template for Subway Builder mods using rolldown-vite. Please use pnpm!
pnpm install| Command | Description |
|---|---|
pnpm build |
Build the mod to dist/ |
pnpm dev |
Watch mode + launch game with logging |
pnpm dev:link |
Symlink dist/ to game's mods folder |
pnpm dev:unlink |
Remove the symlink |
pnpm typecheck |
Run TypeScript type checking |
-
Build and link your mod:
pnpm build pnpm dev:link
-
Enable the mod in Subway Builder: Settings > Mods
-
Start development with hot reload:
pnpm dev
This runs the vite watcher and game simultaneously. Logs are saved to
debug/latest.log. -
After making changes, reload mods in-game or restart. You can use CTRL + SHIFT + R or CMD + SHIFT + R to hot reload in-game.
├── src/
│ ├── main.ts # Entry point
│ ├── ui/
│ │ └── ExamplePanel.tsx # Example React component
│ └── types/
│ ├── react.ts # React shim (pulls from game API)
│ └── subway-builder.d.ts # Game API types
├── scripts/
│ ├── run.ts # Game launcher with logging
│ └── link.ts # Symlink management
├── manifest.json # Mod metadata
├── vite.config.ts # Build config
└── tsconfig.json
Edit manifest.json to set your mod's ID, name, and description:
{
"id": "com.yourname.yourmod",
"name": "Your Mod Name",
"description": "What it does",
"version": "1.0.0",
"author": { "name": "Your Name" },
"main": "index.js"
}React is provided by the game at runtime. Import hooks normally:
import { useState, useEffect } from "react";For game UI components, pull them from the API:
const { Button, Card } = window.SubwayBuilderAPI.utils.components as Record<
string,
React.ComponentType<any>
>;Access the full API via window.SubwayBuilderAPI:
const api = window.SubwayBuilderAPI;
// Hooks
api.hooks.onMapReady((map) => { ... });
api.hooks.onDayChange((day) => { ... });
// UI - Floating panels (icon names from Lucide)
api.ui.addFloatingPanel({
id: 'my-panel',
title: 'My Panel',
icon: 'Settings',
render: MyComponent,
});
// UI - Buttons and notifications
api.ui.addButton('escape-menu', { id: 'btn', label: 'Click', onClick: () => {} });
api.ui.showNotification('Hello', 'info');
// Game state
api.gameState.getStations();
api.gameState.getBudget();
// Actions
api.actions.setMoney(1000000);
api.actions.setPause(true);See src/types/subway-builder.d.ts for the full API reference.
- macOS:
~/Library/Application Support/metro-maker4/mods/ - Windows:
%APPDATA%\metro-maker4\mods\ - Linux:
~/.config/metro-maker4/mods/