-
Notifications
You must be signed in to change notification settings - Fork 18
Settings Sync
Moonbase stores each user's preferences on the server and shares them across every Moonfin client, so your setup follows you between devices.
Direction: bidirectional, local wins on conflict.
- Each client keeps a local copy of your settings and pushes changes to the server.
- On startup a client fetches the server copy and merges it with its local copy.
- A snapshot of the last synced state is kept locally so the merge can tell what each side changed.
- Clients connected to the live events stream (
/Moonfin/Settings/Stream) pick up changes, theme updates, and admin messages without a restart.
Settings are stored per user in a profiled envelope. Version 2 splits values into a shared global profile plus optional per-device overrides.
{
"schemaVersion": 2,
"lastUpdated": 1740200000000,
"lastUpdatedBy": "desktop",
"syncEnabled": true,
"global": { "...": "base settings that every device inherits" },
"desktop": { "...": "overrides for desktop only" },
"mobile": { "...": "overrides for mobile only" },
"tv": { "...": "overrides for TV only" }
}| Field | Type | Description |
|---|---|---|
schemaVersion |
int |
2 for the profiled format. Older flat (v1) files are migrated automatically on load |
lastUpdated |
long | When the envelope was last saved, in epoch milliseconds |
lastUpdatedBy |
string | The client id that last wrote it |
syncEnabled |
bool | Whether server sync is on for this user |
global |
profile | Base values that all devices inherit |
desktop, mobile, tv
|
profile | Sparse overrides that apply only on that device type |
Valid profile names are global, desktop, mobile, and tv. Device profiles only store the values you actually changed for that device, so anything you leave alone keeps flowing from global.
When a client asks for the resolved value of a setting, the server returns the first value that is set, in this order:
- The device profile (
desktop,mobile, ortv), unless you asked forglobal - The
globalprofile - The admin default settings
If none of those set a value, the field stays empty and the client falls back to its own built-in default.
On startup a client pings /Moonfin/Ping to confirm the plugin is installed and sync is on, then fetches /Moonfin/Settings. What happens next depends on what already exists:
- Local and server both exist, with a snapshot: a three-way merge. For each setting, if only one side changed, that change is kept. If both sides changed the same setting, the local value wins.
- Local and server both exist, no snapshot: first sync on this client. Local wins, then the merged result is pushed back to the server.
- Server only (fresh install or new browser): the server settings are restored locally. This is how your settings carry over to a new client.
- Local only: the local settings are pushed to the server.
After merging, the result is saved as the new snapshot for next time. Every settings change also saves locally right away and, when the server is reachable, pushes to the server.
- Opening Moonfin on a new device with no local settings pulls everything from the server.
- Changing a setting on one client pushes it to the server, and the next client to load merges it in (with local winning if both changed the same value).
- Push Defaults to Existing Users updates the stored global values and emits a live update so connected clients re-resolve immediately.
- Admin broadcasts are delivered over the same live stream.
- The three-way merge handles most cases, but when two clients change the same setting, local wins.
- Live updates only reach clients currently connected to the events stream. Others catch up on their next startup.
- Sensitive values like
mdblistApiKeyare stored on the server per user.
Every value below can be set on global and optionally overridden per device profile. Names are the JSON property names.
| Setting | Type | Description |
|---|---|---|
seerrEnabled |
bool | Enable Seerr integration |
seerrApiKey |
string | Seerr API key |
seerrBlockNsfw |
bool | Hide adult results from Seerr |
seerrRows |
object | Which Seerr discovery rows show and their order |
mdblistEnabled |
bool | Enable MDBList ratings |
mdblistApiKey |
string | MDBList API key |
mdblistRatingSources |
list | Which rating sources to pull from MDBList |
mdblistShowRatingNames |
bool | Show the rating source names |
mdblistShowRatingBadges |
bool | Show rating badges |
tmdbApiKey |
string | TMDB API key |
tmdbEpisodeRatingsEnabled |
bool | Enable per-episode ratings from TMDB |
The jellyseerr* names (jellyseerrEnabled, jellyseerrApiKey, jellyseerrBlockNsfw, jellyseerrRows) are legacy aliases backed by the same values as their seerr* equivalents.
| Field | Type | Description |
|---|---|---|
trendingMovies |
bool | Show the trending movies row |
trendingTv |
bool | Show the trending TV row |
popularMovies |
bool | Show the popular movies row |
popularTv |
bool | Show the popular TV row |
upcomingMovies |
bool | Show the upcoming movies row |
upcomingTv |
bool | Show the upcoming TV row |
rowOrder |
list | The order of the Seerr rows |
| Setting | Type | Description |
|---|---|---|
navbarPosition |
string | Navbar placement (top or side) |
navbarColor |
string | Navbar color |
navbarOpacity |
int | Navbar opacity |
navbarAlwaysExpanded |
bool | Keep the navbar expanded |
focusColor |
string | Accent color for focused items |
visualTheme |
string | Selected built-in theme |
customThemeId |
string | Selected custom theme id |
watchedIndicator |
string | Style of the watched indicator |
cardFocusExpansion |
bool | Expand cards when focused |
posterSize |
string | Poster size |
seasonalSurprise |
string | Seasonal particle effect |
backdropEnabled |
bool | Show backdrops |
browsingBlur |
string | Blur behind browsing screens |
| Setting | Type | Description |
|---|---|---|
detailScreenStyle |
string | Detail screen layout variant |
detailExpandedTabs |
bool | Show the detail screen tabs expanded |
useDetailedSubHeadings |
bool | Use detailed sub-headings |
detailsScreenBlur |
string | Detail screen backdrop blur |
detailsBackdropBlur |
int | Detail backdrop blur amount |
detailsBackdropOpacity |
int | Detail backdrop opacity |
| Setting | Type | Description |
|---|---|---|
showShuffleButton |
bool | Show the shuffle button |
showGenresButton |
bool | Show the genres button |
showFavoritesButton |
bool | Show the favorites button |
showCastButton |
bool | Show the cast button |
showSyncPlayButton |
bool | Show the SyncPlay button |
showLibrariesInToolbar |
bool | Show libraries in the toolbar |
shuffleContentType |
string | What shuffle pulls from (movies, tv, both) |
| Setting | Type | Description |
|---|---|---|
desktopMediaBarProvider |
string | Which provider backs the desktop media bar |
mediaBarMode |
string | Media bar mode |
mediaBarSourceType |
string | Source type (library or collection) |
mediaBarLibraryIds |
list | Library ids feeding the media bar |
mediaBarCollectionIds |
list | Collection ids feeding the media bar |
mediaBarExcludedGenres |
list | Genres to exclude |
mediaBarItemCount |
int | Number of items |
mediaBarOpacity |
int | Overlay opacity |
mediaBarOverlayColor |
string | Overlay color |
mediaBarAutoAdvance |
bool | Auto-advance slides |
mediaBarIntervalMs |
int | Auto-advance interval in milliseconds |
mediaBarTrailerPreview |
bool | Play trailer previews |
mediaBarTrailerAudio |
bool | Enable trailer audio |
episodePreviewEnabled |
bool | Enable episode previews |
previewAudioEnabled |
bool | Enable preview audio |
| Setting | Type | Description |
|---|---|---|
homeSections |
list | The full home layout, including dynamic plugin sections. Newer clients prefer this |
homeRowOrder |
list | The legacy ordered list of built-in rows |
homeRowsStyle |
string | Home rows rendering style |
homeRowsImageType |
string | Home rows image type (poster, thumb, banner) |
homeRowsImageTypeOverride |
bool | Override the home rows image type |
homeImageTypeContinueWatching |
string | Image type for the Continue Watching row |
homeImageUseSeriesImage |
bool | Use the series image instead of the episode image |
fullScreenRows |
bool | Full-screen home rows |
mergeContinueWatchingNextUp |
bool | Merge Continue Watching with Next Up |
displayFavoritesRows |
bool | Show favorites rows |
displayCollectionsRows |
bool | Show collections rows |
displayGenresRows |
bool | Show genres rows |
displaySeerrRows |
bool | Show Seerr rows |
displayPlaylistsRows |
bool | Show playlists rows |
displayAudioRows |
bool | Show audio rows |
favoritesRowSortBy |
string | Sort order for favorites rows |
collectionsRowSortBy |
string | Sort order for collections rows |
genresRowSortBy |
string | Sort order for genres rows |
genresRowItemFilter |
string | Item filter for genres rows |
| Field | Type | Description |
|---|---|---|
kind |
string | Section kind, built-in or a dynamic plugin section |
type |
string | The row key for built-in sections |
enabled |
bool | Whether the section shows |
order |
int | Position of the section on the home screen |
serverId |
string | Owning server for multi-server setups |
pluginSource |
string | Source plugin for dynamic sections |
pluginSection |
string | The plugin's section identifier |
pluginAdditionalData |
string | Extra data the plugin section needs |
pluginDisplayText |
string | Display label for the plugin section |
| Setting | Type | Description |
|---|---|---|
displaySinceYouWatchedRows |
bool | Show Since You Watched rows |
sinceYouWatchedSource |
string | Source for those rows |
sinceYouWatchedSourceType |
string | Source type |
sinceYouWatchedSourceItem |
string | Specific source item |
sinceYouWatchedNumRows |
int | How many rows to show |
sinceYouWatchedIncludeWatched |
bool | Include already-watched items |
displayRewatchRow |
bool | Show the rewatch row |
rewatchSortBy |
string | Sort order for the rewatch row |
rewatchIncludeMovies |
bool | Include movies |
rewatchIncludeShows |
bool | Include shows |
rewatchIncludeCollections |
bool | Include collections |
| Setting | Type | Description |
|---|---|---|
enableMultiServerLibraries |
bool | Aggregate libraries across servers |
enableFolderView |
bool | Enable folder view |
confirmExit |
bool | Ask before exiting |
blockedRatings |
list | Content ratings to hide |
themeMusicEnabled |
bool | Enable theme music |
themeMusicOnHomeRows |
bool | Play theme music on home rows |
themeMusicVolume |
int | Theme music volume |
themeMusicLoop |
bool | Loop theme music |
hiddenContinueWatchingItems |
string | Items hidden from Continue Watching |
hiddenNextUpSeries |
string | Series hidden from Next Up |
Note: not every client uses every setting yet. The server stores the full set. Each client reads and writes the ones it supports and preserves the rest untouched.