Electron Setup
Installing mods, folder structure, and hot reload
This guide covers how to manage mods in the desktop version of Subway Builder.
Installing Mods#
- Download the mod (usually a
.zipfile) - Extract it to your mods folder
- Restart Subway Builder
- Enable the mod in Settings > Mods
Hot Reload#
During development, you can reload all mods without restarting the game:
// Reload all mods (clears mod state and re-executes mod scripts)
await window.SubwayBuilderAPI.reloadMods();This clears:
- All registered callbacks (except mapReady - map is already loaded)
- UI components
- Custom layers, sources, and styles
- Custom train types (keeps built-in heavy-metro and light-metro)
- Custom cities (keeps built-in cities)
The mod loader will then re-execute all enabled mod scripts.
Mod Storage#
Mods can persist settings and data using the storage API. Data is stored per-mod in the user's app data directory.
Save and Load Settings#
// Save a setting
await window.SubwayBuilderAPI.storage.set('myModEnabled', true);
await window.SubwayBuilderAPI.storage.set('favoriteColor', '#ff0000');
await window.SubwayBuilderAPI.storage.set('userPrefs', {
volume: 0.8,
notifications: true
});
// Load a setting (with optional default value)
const enabled = await window.SubwayBuilderAPI.storage.get('myModEnabled', false);
const color = await window.SubwayBuilderAPI.storage.get('favoriteColor', '#000000');
const prefs = await window.SubwayBuilderAPI.storage.get('userPrefs', {});Delete and List Keys#
// Delete a stored value
await window.SubwayBuilderAPI.storage.delete('myModEnabled');
// Get all stored keys for this mod
const keys = await window.SubwayBuilderAPI.storage.keys();
console.log('Stored keys:', keys); // ['favoriteColor', 'userPrefs']Note: Storage is only available in Electron (desktop app). In browser, storage operations are no-ops. Storage is scoped per-mod based on mod ID from the manifest.
Multi-Language Support#
Want your mod to support multiple languages? Use i18n.create():
const t = SubwayBuilderAPI.utils.i18n.create({
en: { greeting: 'Hello', status: 'Active' },
es: { greeting: 'Hola', status: 'Activo' },
fr: { greeting: 'Bonjour', status: 'Actif' }
});
t('greeting'); // Returns "Hola" if game is set to SpanishThe returned t() function automatically picks the right language based on the player's game setting, falling back to English if a translation is missing.
Debugging Tips#
- Check API availability
``javascript if (!window.SubwayBuilderAPI) { console.error('API not loaded yet'); return; } ``
- List all registered cities
``javascript console.table(window.SubwayBuilderAPI.utils.getCities()); ``
- Get current map instance
``javascript const map = window.SubwayBuilderAPI.utils.getMap(); console.log('Map loaded:', !!map); ``
- Check game constants
``javascript const rules = window.SubwayBuilderAPI.utils.getConstants(); console.log('Starting money:', rules.STARTING_MONEY); ``
Tips#
- Check API availability: Always check
window.SubwayBuilderAPIexists before using - Use hooks for timing: Register content in
onGameInitto ensure proper loading - Test incrementally: Add one feature at a time and verify it works
- Check console: Modding API logs all operations with
[Modding API]prefix - Cities need data: Custom cities require data files in
public/data/{CODE}/