App Shell & Branding¶
Customize the visible identity of your Mozaiks app using declarative config files — no runtime code changes needed.
Key Files¶
| File | Controls |
|---|---|
app/brand/theme_config.json | Colors, fonts, spacing, dark/light mode |
app/brand/assets/ | Logos and icons |
app/brand/fonts/ | Custom local fonts |
app/config/shell.json | Header, navigation, shortcuts, chrome modes, notifications |
app/app.json | App name, startup route, auth intent |
theme_config.json¶
app/brand/theme_config.json drives all visual tokens for the shell, pages, and chat surfaces. It is served by /api/theme-config and read by themeProvider.js. It has seven top-level sections.
theme¶
High-level presets. Most apps only need to touch these.
{
"theme": {
"primary": "cyan",
"variant": "modern",
"radius": "medium",
"font": "rajdhani",
"font_heading": "orbitron",
"appearance": "dark",
"density": "comfortable",
"branding": {
"app_name": "My App",
"logo_url": "/assets/my_logo.svg",
"favicon_url": "/favicon.ico"
}
}
}
| Field | Options |
|---|---|
primary | Named color — e.g. cyan, violet, emerald, amber |
variant | modern, flat, glass |
radius | none, small, medium, large, full |
font / font_heading | Font key matching an entry in fonts |
appearance | dark, light, system |
density | compact, comfortable, spacious |
identity¶
App name and tagline shown in the UI and metadata.
assets¶
Asset filenames served from app/brand/assets/.
{
"assets": {
"logo": "my_logo.svg",
"wordmark": "my_wordmark.png",
"favicon": "/favicon.ico",
"chatbackgroundImage": "chat_bg.png"
}
}
logoandwordmarkare referenced byshell.json → header.logochatbackgroundImageis the subtle texture behind the chat feed (optional)
fonts¶
Define body, heading, and logo fonts. Use googleFont for web fonts or localFont: true with a src path for self-hosted fonts.
{
"fonts": {
"body": {
"family": "Inter",
"fallbacks": "ui-sans-serif, system-ui, sans-serif",
"googleFont": "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap",
"tailwindClass": "font-sans"
},
"heading": {
"family": "Sora",
"fallbacks": "Inter, ui-sans-serif, sans-serif",
"googleFont": "https://fonts.googleapis.com/css2?family=Sora:wght@600;700&display=swap",
"tailwindClass": "font-heading"
}
}
}
For a local font, use:
Only commit fonts whose license allows redistribution, such as the SIL Open Font License or Apache 2.0, and keep the license text beside the font as app/brand/fonts/<Family>-OFL.txt (or <Family>-LICENSE.txt), where <Family> is the font file name up to its first -. A desktop or personal-use font license does not cover shipping the font file inside your app. The default Mozaiks brand keeps its mozaik.png wordmark image and ships Bungee Inline for logo-styled text, plus Share Tech and Oxanium, each with its OFL text. An active app's brand config supplies its own fonts and colors.
colors¶
Full color palette. Each entry has main, light, and dark hex values.
{
"colors": {
"primary": { "main": "#06b6d4", "light": "#67e8f9", "dark": "#0e7490", "name": "cyan" },
"secondary": { "main": "#8b5cf6", "light": "#a78bfa", "dark": "#6d28d9", "name": "violet" },
"accent": { "main": "#f59e0b", "light": "#fbbf24", "dark": "#d97706", "name": "amber" },
"background": { "base": "#0b1220", "surface": "#0f1724", "elevated": "#131d33" },
"text": { "primary": "#e6eef8", "secondary": "#94a3b8", "muted": "#64748b" }
}
}
Also include success, warning, error, border, and text.onAccent as needed.
shadows¶
Color-matched glow shadows used by elevated surfaces and focused elements. Keys match the color palette: primary, secondary, accent, success, warning, error, elevated, focus.
{
"shadows": {
"primary": "0 20px 45px rgba(6, 182, 212, 0.24)",
"focus": "0 0 0 3px rgba(8, 145, 178, 0.55)"
}
}
primitives and ui¶
primitives sets border radius, max-width measures, and spacing scale. ui sets pixel-level spacing for the shell header/footer, page layouts, and chat feed. These rarely need changing — adjust only when the default density or layout proportions don't match your design.
{
"primitives": {
"radius": { "surface": "1rem", "control": "0.5rem", "bubble": "18px" },
"measure": { "shell": "1440px", "chat_feed": "1040px" },
"spacing": { "tight": "0.5rem", "base": "1rem", "loose": "1.5rem" }
}
}
shell.json¶
app/config/shell.json is the main config for how the shell looks and behaves. It has five top-level sections.
header¶
Controls the logo, wordmark, and header action buttons.
{
"header": {
"logo": {
"src": "my_logo.svg",
"wordmark": "my_wordmark.png",
"alt": "My App",
"href": "/"
},
"actions": [
{
"id": "create",
"label": "Create",
"path": "/create",
"variant": "primary",
"visible": true
}
]
}
}
logo.srcandlogo.wordmarkreference files inapp/brand/assets/logo.hrefis where clicking the logo navigatesactionsare the buttons shown in the top-right of the header- Each action supports
variant(primaryorsecondary),visible, and optionalpath_by_rolefor role-based routing
shortcuts¶
Declares which built-in shortcut ids appear in each shell zone. The backend expands these into the full config returned by /api/shell-config.
{
"shortcuts": {
"profile": ["profile", "settings", "signout"],
"mobile": ["create", "profile"],
"footer": ["legal", "terms", "cookies"],
"footerHideOnMobile": true
}
}
| Zone | Where it renders |
|---|---|
profile | Profile/avatar dropdown menu |
mobile | Bottom bar on mobile |
footer | Footer links |
header | Header icon strip (optional) |
Common shortcut ids: home, apps, workspace, create, profile, settings, signout, signin, notifications, wallet, admin, support, legal, terms, cookies, privacy. Use dashboard only when the app declares a page or route with id dashboard.
create always means a fresh app-build journey and resolves to /create?new=1. Continue-build or resume behavior belongs in Studio/App Studio history, not in the shell shortcut.
navigation¶
Controls where global and local navigation are placed on desktop and mobile.
{
"navigation": {
"policy": {
"desktop": {
"global": "header",
"local": "sidebar",
"footer": "visible"
},
"mobile": {
"global": "bottomBar",
"local": "sheet",
"footer": "hidden"
},
"maxMobileItems": 5,
"autoFromPages": false
}
}
}
global— where primary nav destinations appear (headerorbottomBar)local— where section/module nav appears (sidebarorsheet)footer—visibleorhiddenmaxMobileItems— cap on bottom bar items before overflowautoFromPages— keepfalse; add navigation explicitly in page YAML
chrome¶
Defines which shell surfaces (header, footer, bottom bar, local nav) are visible per shell_mode on desktop and mobile. Pages set their own shell_mode — see Add a Page. Only override here when the app-wide default for a mode needs changing.
{
"chrome": {
"defaultMode": "standard",
"modes": {
"standard": {
"desktop": { "header": true, "footer": true, "bottomBar": false, "localNav": true },
"mobile": { "header": true, "footer": false, "bottomBar": true, "localNav": "sheet" }
},
"conversation": {
"desktop": { "header": true, "footer": false, "bottomBar": false, "localNav": false },
"mobile": { "header": true, "footer": false, "bottomBar": false, "localNav": false }
}
}
}
}
Available modes: standard, workspace, conversation, focused, immersive, public.
notifications¶
Controls the notification bell in the header.
{
"notifications": {
"show": true,
"path": "/notifications",
"emptyText": "No unread notifications"
}
}
Set "show": false to hide the bell entirely.
Startup Route¶
Set the landing page in app/app.json:
What Branding Does Not Control¶
Branding controls visual tokens and shell chrome. It does not control admin ownership and behavior.
- Admin pages and panels — declared in
app/admin/admin_registry.yamland registered inapp/admin/index.js. Branding does not affect admin page routing or component registration. - Module behavior — business logic and actions live in
app/modules/. Theme changes do not alter module contracts. - Page content — page structure and data bindings live in
app/ui/pages/*.yaml. Branding sets visual style only. - Navigation structure — top-level nav items and routes come from
app/config/shell.jsonandapp/ui/route_manifest.json, not from theme tokens.