Navigation Configuration

Configure and customize navigation menus, headers, footers, and sidebars in your SaaS application.

Configure the navigation structure for your application including headers, footers, dashboard sidebars, and mobile menus.

The kit has several navigation contexts:

  • Header Navigation (Marketing site)
  • Footer Navigation (Marketing site)
  • Dashboard Sidebar (Logged-in users)
  • Admin Navigation (Admin users)

Header Navigation (Marketing)

Public-facing navigation for marketing pages can be found at apps/web/app/[locale]/(public)/_components/site-navigation.tsx:

const links = {
Blog: {
label: 'marketing.blog',
path: '/blog',
},
Changelog: {
label: 'marketing.changelog',
path: '/changelog',
},
Docs: {
label: 'marketing.help',
path: '/help',
},
FAQ: {
label: 'marketing.faq',
path: '/faq',
},
};

The menu will automatically be generated from the links object. The label is the translation key for the link, and the path is the path to the link. If you don't want to use translations, you can use the label property directly without using an i18n key (ex. label: 'Blog').

The footer navigation is defined in the SiteFooter component defined at apps/web/app/[locale]/(public)/_components/site-footer.tsx. You can customize the footer by updating the sections property.

import { AppLogo } from '@components/app-logo';
import { appConfig } from '@config/app.config';
import { Footer } from '@kit/ui/marketing';
import { Trans } from '@kit/ui/trans';
export function SiteFooter() {
return (
<Footer
logo={<AppLogo className="w-[85px] md:w-[95px]" />}
description={<Trans i18nKey="marketing.footerDescription" />}
copyright={
<Trans
i18nKey="marketing.copyright"
values={{
product: appConfig.name,
year: new Date().getFullYear(),
}}
/>
}
sections={[
{
heading: <Trans i18nKey="marketing.about" />,
links: [
{ href: '/blog', label: <Trans i18nKey="marketing.blog" /> },
{ href: '/contact', label: <Trans i18nKey="marketing.contact" /> },
],
},
{
heading: <Trans i18nKey="marketing.product" />,
links: [
{
href: '/help',
label: <Trans i18nKey="marketing.help" />,
},
],
},
{
heading: <Trans i18nKey="marketing.legal" />,
links: [
{
href: '/terms-of-service',
label: <Trans i18nKey="marketing.termsOfService" />,
},
{
href: '/privacy-policy',
label: <Trans i18nKey="marketing.privacyPolicy" />,
},
{
href: '/cookie-policy',
label: <Trans i18nKey="marketing.cookiePolicy" />,
},
],
},
]}
/>
);
}

Dashboard Sidebar

The main dashboard sidebar is defined in the routes configuration at apps/web/config/app-navigation.config.tsx. The full schema can be found at packages/ui/src/makerkit/navigation-config.schema.ts, where you can find the full list of properties you can use to customize the sidebar.

Here's the default configuration:

const routes: z.output<typeof NavigationConfigSchema>['routes'] = [
{
label: 'common.routes.application',
children: [
{
label: 'common.routes.dashboard',
path: '/dashboard',
Icon: <Home className={iconClasses} />,
},
],
},
];

By default, we only display the Dashboard route. Here is where you will add your own application routes.

Let's see a few examples of how we can add more routes to the sidebar.

In the example below, we will add a Chat route to the sidebar under the "Application" group and create a new "Settings" group with a Profile route.

const routes: z.output<typeof NavigationConfigSchema>['routes'] = [
{
label: 'common.routes.application',
children: [
{
label: 'common.routes.dashboard',
path: '/dashboard',
Icon: <Home className={iconClasses} />,
},
{
label: 'common.routes.chat',
path: '/dashboard/chat',
Icon: <MessageSquare className={iconClasses} />,
},
],
},
{
label: 'common.routes.settings',
children: [
{
label: 'common.routes.profile',
path: '/settings/profile',
Icon: <User className={iconClasses} />,
},
],
},
];

We have:

  • The Application group with the Dashboard route
  • The Chat route under the Application group
  • The Settings group with the Profile route

You can add as many routes as you want to the sidebar.

Organizing routes by context

You can control which routes appear based on the current account context (personal vs organization) by using the context property on route children.

The context property accepts three values:

  • 'personal' - Only visible when viewing a personal account
  • 'organization' - Only visible when viewing an organization
  • 'all' - Visible in all contexts (this is the default)
const routes: z.output<typeof NavigationConfigSchema>['routes'] = [
{
label: 'common.routes.application',
children: [
{
label: 'common.routes.dashboard',
path: '/dashboard',
Icon: <Home className={iconClasses} />,
// No context specified = defaults to 'all' (visible everywhere)
},
{
label: 'common.routes.team',
path: '/dashboard/team',
Icon: <Users className={iconClasses} />,
context: 'organization', // Only visible in organization context
},
{
label: 'common.routes.personalSettings',
path: '/dashboard/personal',
Icon: <User className={iconClasses} />,
context: 'personal', // Only visible in personal context
},
],
},
];

The context filtering works in conjunction with your application's account mode configuration:

  • Organizations-only mode: Routes with context: 'personal' are always hidden
  • Personal-only mode: Routes with context: 'organization' are always hidden
  • Hybrid mode: Routes are shown/hidden based on the current context the user is viewing

This allows you to create a single navigation configuration that adapts automatically based on whether the user is viewing their personal account or an organization.

The context property can also be applied to nested children (RouteSubChild) for more granular control over sub-navigation items.


Next: Authentication