Mod Storage
New in v1.0.0Persist settings and data across game sessions (Electron only)
<Callout type="info"> Storage is only available in the desktop (Electron) version. In browser, storage operations are no-ops that return safely without error. </Callout>
The Storage API lets your mod save settings and data that persist across game sessions. Data is stored per-mod in the user's app data directory.
<Callout type="warning"> Common gotcha: `storage.get()` returns a Promise, not the value directly. If you forget await, you'll silently get [object Promise] instead of your data.
// Wrong β val is a Promise object, not your data
const val = api.storage.get('key');
// Correct
const val = await api.storage.get('key');</Callout>
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', {});
console.log('Mod enabled:', enabled);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']API Reference#
storage.get(key, defaultValue?)#
Retrieves a stored value.
| Parameter | Type | Description |
|---|---|---|
key | string | The key to retrieve |
defaultValue | any | Value to return if key doesn't exist |
Returns: Promise<any> - The stored value or default
storage.set(key, value)#
Stores a value.
| Parameter | Type | Description |
|---|---|---|
key | string | The key to store under |
value | any | The value to store (must be JSON-serializable) |
Returns: Promise<void>
storage.delete(key)#
Deletes a stored value.
| Parameter | Type | Description |
|---|---|---|
key | string | The key to delete |
Returns: Promise<void>
storage.keys()#
Lists all stored keys for this mod.
Returns: Promise<string[]> - Array of key names
Data Types#
Storage supports any JSON-serializable data:
// Primitives
await storage.set('count', 42);
await storage.set('name', 'My Mod');
await storage.set('enabled', true);
// Objects
await storage.set('config', {
theme: 'dark',
notifications: true,
favorites: ['NYC', 'CHI', 'LA']
});
// Arrays
await storage.set('history', [
{ date: '2024-01-01', action: 'installed' },
{ date: '2024-01-02', action: 'configured' }
]);<Callout type="warning">Functions, DOM elements, and circular references cannot be stored.</Callout>
Mod Isolation#
Each mod's storage is isolated based on the mod ID from your manifest.json:
{
"id": "my-awesome-mod",
"name": "My Awesome Mod"
}Keys are automatically namespaced, so storage.set('config', ...) in your mod won't conflict with another mod using the same key name.
Complete Example#
const api = window.SubwayBuilderAPI;
// Mod settings panel with persistent preferences
const DEFAULT_SETTINGS = {
showNotifications: true,
autoSave: true,
theme: 'auto'
};
// Load saved settings on init
api.hooks.onGameInit(async () => {
const settings = await api.storage.get('settings', DEFAULT_SETTINGS);
applySettings(settings);
});
// Settings UI
api.ui.registerComponent('settings-menu', {
id: 'my-mod-settings',
component: api.utils.components.createElement(
'div',
{ className: 'space-y-4' },
api.utils.components.createElement(api.utils.components.Switch, {
id: 'notifications',
defaultChecked: true,
onCheckedChange: async (checked) => {
const settings = await api.storage.get('settings', DEFAULT_SETTINGS);
settings.showNotifications = checked;
await api.storage.set('settings', settings);
}
}),
api.utils.components.createElement(
api.utils.components.Label,
{ htmlFor: 'notifications' },
'Show Notifications'
)
)
});
function applySettings(settings) {
// Apply your mod's settings
console.log('Applied settings:', settings);
}Browser Compatibility#
When running in the browser (not Electron), storage operations are safe no-ops:
// In browser, these work but don't persist:
await api.storage.set('key', 'value'); // Does nothing
await api.storage.get('key', 'default'); // Returns 'default'
await api.storage.keys(); // Returns []This lets you write code that works in both environments without conditionals.