Modding Guide¶
Multiverse Echoes supports three modding systems: theme overrides, export templates, and extension slots. All are available through the client's JavaScript API.
Theme Overrides¶
Override any CSS design token to create custom visual themes.
import { useThemeStore } from 'multiverse-echoes-client/stores';
// Register a custom theme
useThemeStore.getState().registerOverride({
id: 'synthwave',
name: 'Synthwave',
variables: {
'--canvas': '#1a0a2e',
'--surface': '#2d1b4e',
'--accent': '#ff6ec7',
'--accent-hover': '#ff8fd4',
'--text-primary': '#e0d4ff',
},
});
// Apply it
useThemeStore.getState().applyOverride('synthwave');
// Remove it
useThemeStore.getState().unregisterOverride('synthwave');
Registered themes appear in Settings > Appearance alongside the built-in dark and light modes.
Export Templates¶
Add custom formats for Echo story exports.
import { registerExportTemplate, unregisterExportTemplate } from 'multiverse-echoes-client/lib/exportTemplates';
registerExportTemplate({
id: 'screenplay',
name: 'Screenplay',
description: 'Formatted as a film screenplay',
render(echo, feed) {
let output = `FADE IN:\n\nINT. ${echo.name}'s WORLD - DAY\n\n`;
for (const item of feed) {
if (item.item_type === 'diary_entry') {
output += `${echo.name.toUpperCase()}\n(${item.title})\n${item.body}\n\n`;
}
}
output += 'FADE OUT.\n';
return output;
},
});
Extension Slots¶
Inject custom UI components into predefined slots in the application.
Available Slots¶
| Slot Name | Location |
|---|---|
dashboard-panel |
Bottom of the Dashboard main area |
echo-detail-panel |
Bottom of the Echo Detail page |
shard-view-panel |
Bottom of the Shard View page |
settings-tab |
Additional tab in Settings |
sidebar-footer |
Bottom of the sidebar |
Registering an Extension¶
import { registerExtension, unregisterExtension } from 'multiverse-echoes-client/lib/extensions';
registerExtension({
id: 'weather-widget',
slot: 'dashboard-panel',
render() {
const div = document.createElement('div');
div.textContent = 'Custom weather widget for the Shard';
div.style.padding = '1rem';
return div;
},
});
React Extensions¶
For React-based extensions, return a React element from the render function:
registerExtension({
id: 'analytics',
slot: 'echo-detail-panel',
render() {
return <AnalyticsDashboard />;
},
});
Best Practices¶
- Use unique IDs — prefix with your mod name to avoid conflicts (e.g.
mymod-theme) - Clean up — call
unregister*when your mod is disabled - Respect design tokens — override tokens, don't use hardcoded colours
- Test both themes — verify your overrides look good in both dark and light mode
- Keep it accessible — maintain contrast ratios (4.5:1 AA minimum for text)
Further Reading¶
- Full modding API documentation: MODDING.md
- Design system tokens:
client/src/styles/tokens.css - Extension slot component:
client/src/lib/extensions.ts