Customization
Jumbo React Next separates configuration into three layers: the MUI theme (colors, typography, spacing), the layout options (sidebar width, header height, footer visibility), and the global config (route lists, theme composition). This page explains each layer and how to modify it.
Theme configuration
The app theme is assembled by createJumboTheme from four independent region tokens. The root
config in src/config/index.ts composes these into a single JumboThemeConfig:
// src/config/index.ts
import { footerTheme } from '@/themes/footer/default';
import { headerTheme } from '@/themes/header/default';
import { mainTheme } from '@/themes/main/default';
import { sidebarTheme } from '@/themes/sidebar/default';
import { createJumboTheme } from '@jumbo/utilities/helpers';
export const CONFIG = {
THEME: createJumboTheme(mainTheme, headerTheme, sidebarTheme, footerTheme),
PUBLIC_ROUTES: publicPaths,
ANONYMOUS_ROUTES: anonymousPaths,
DISABLE_PROTECTED_ROUTE_CHECK: false,
};Theme regions
Each region has three mode variants — default (light), dark, and semi-dark — located in
src/themes/{region}/:
| Region | Default file | Dark file | Semi-dark file |
|---|---|---|---|
| Main (page body) | src/themes/main/default.ts | src/themes/main/dark.ts | src/themes/main/semi-dark.ts |
| Header | src/themes/header/default.ts | src/themes/header/dark.ts | src/themes/header/semi-dark.ts |
| Sidebar | src/themes/sidebar/default.ts | src/themes/sidebar/dark.ts | src/themes/sidebar/semi-dark.ts |
| Footer | src/themes/footer/default.ts | src/themes/footer/dark.ts | src/themes/footer/semi-dark.ts |
To change the primary color for the main region, edit the main theme token file:
// src/themes/main/default.ts
import { createTheme } from '@mui/material/styles';
export const mainTheme = createTheme({
palette: {
primary: {
main: '#7352C7', // change this to your brand color
light: '#9E86DB',
dark: '#3F1D9B',
contrastText: '#fff',
},
// ...
},
});Define your brand colors as palette tokens (primary.main, secondary.main) and reference them
in components via theme.palette.primary.main or MUI's sx prop. This ensures dark mode and
CustomizerSettings mode switching work correctly without any extra code.
Demo-specific themes
Each demo layout (Demo1–Demo4) has its own theme config that extends or overrides the defaults. Demo 4, for example, uses a fully dark stack:
// src/components/Demo4Layout/themes/index.ts
import { mainThemeDark } from '@/themes/main/dark';
import { headerThemeDark } from '@/themes/header/dark';
import { sidebarThemeDark } from '@/themes/sidebar/dark';
import { footerThemeDark } from '@/themes/footer/dark';
import { createJumboTheme } from '@jumbo/utilities/helpers';
export const CONFIG4 = {
THEME: createJumboTheme(mainThemeDark, headerThemeDark, sidebarThemeDark, footerThemeDark),
};To create a new theme variant, add a new token file in the appropriate region folder and reference it in your layout's config.
Layout configuration
The (common) layout group uses defaultLayoutConfig from src/config/layouts/default.ts. This
object maps to LayoutOptions from @jumbo/types:
// src/config/layouts/default.ts
const defaultLayoutConfig: LayoutOptions = {
sidebar: {
open: true,
hide: false,
variant: SIDEBAR_VARIANTS.PERSISTENT, // 'persistent' | 'temporary' | 'permanent'
style: SIDEBAR_STYLES.FULL_HEIGHT, // 'full-height' | 'clipped-under-header'
view: SIDEBAR_VIEWS.FULL, // 'full' | 'mini'
scrollType: SIDEBAR_SCROLL_TYPES.FIXED, // 'fixed' | 'default'
anchor: SIDEBAR_ANCHOR_POSITIONS.LEFT, // 'left' | 'right'
width: 240,
minWidth: 80,
drawer: true,
drawerBreakpoint: 'xl',
},
header: {
hide: false,
fixed: true,
sx: { height: 80 },
drawerBreakpoint: 'xl',
},
footer: {
hide: false,
},
content: {
sx: { py: 4 },
},
};
export const CONTAINER_MAX_WIDTH = 1320;Layout variant comparison
| Layout group | Sidebar | Header height | Footer | Right sidebar |
|---|---|---|---|---|
(common) — default | Persistent, 240px | 80px | Visible | — |
(demo1-layout) | None | 130px | Visible | — |
(demo2-layout) | Temporary | 90px | Visible | — |
(demo3-layout) | Temporary | 72px | Hidden | Enabled |
(demo4-layout) | Temporary | 72px | Hidden | Enabled |
Changing layout options at runtime
Use the useJumboLayoutSidebarOptions / useJumboLayoutHeaderOptions hooks (from @jumbo/components/JumboLayout)
to update options from any component:
// src/components/SidebarToggleButton/SidebarToggleButton.tsx
'use client';
import { useJumboLayoutSidebarOptions } from '@jumbo/components/JumboLayout';
export function SidebarToggleButton() {
const { setSidebarOptions, sidebarOptions } = useJumboLayoutSidebarOptions();
return (
<button
onClick={() => setSidebarOptions({ open: !sidebarOptions.open })}
>
Toggle Sidebar
</button>
);
}CustomizerSettings drawer
The CustomizerSettings component (src/components/CustomizerSettings/) provides a runtime UI
for switching theme modes and layout options. It is rendered inside every layout that uses it:
// src/app/[lang]/(common)/layout.tsx (excerpt)
import { CustomizerButton } from '@/components/CustomizerButton/CustomizerButton';
import { CustomizerSettings } from '@/components/CustomizerSettings/CustomizerSettings';
export default function CommonLayout({ children }) {
return (
<JumboLayoutProvider defaultLayoutConfig={defaultLayoutConfig}>
<JumboLayout header={<Header />} sidebar={<SidebarWithMenus />} footer={<Footer />}>
{children}
<CustomizerButton />
<CustomizerSettings />
</JumboLayout>
</JumboLayoutProvider>
);
}To hide the customizer in production, remove <CustomizerButton /> and <CustomizerSettings />
from your layout file.
Global config
src/config/index.ts exports the CONFIG object, which is the single source of truth for
app-wide settings:
export const CONFIG: ConfigType = {
THEME: createJumboTheme(mainTheme, headerTheme, sidebarTheme, footerTheme),
PUBLIC_ROUTES: publicPaths, // routes accessible without authentication
ANONYMOUS_ROUTES: anonymousPaths, // routes that redirect authenticated users away
DISABLE_PROTECTED_ROUTE_CHECK: false, // set to true to bypass auth in development
};The route lists are defined in src/config/routes/path.ts and used by the proxy handlers in
src/proxy/ to determine how to handle each incoming request. See the
Proxy & Middleware guide for details.