Skip to main content

Branding and Theming

In this tutorial, you will learn how to manage application identity and branding using the built-in components of this template. You will implement theme-aware logos, configure responsive branding for sidebars, and set up a branded authentication layout.

Prerequisites

Before starting, ensure you have the following configured:

  • The ThemeProvider must be wrapping your application root (found in frontend/src/main.tsx).
  • Tailwind CSS must be configured to support dark mode (using the class strategy).
  • The cn utility from frontend/src/lib/utils.ts must be available for class merging.

Step 1: Implementing Theme-Aware Logos

The Logo component is the primary tool for displaying your brand. It automatically detects the current theme using the useTheme hook and selects the appropriate SVG asset.

To use the logo in its simplest form, import it from the Common components:

import { Logo } from "@/components/Common/Logo"

export function Header() {
return (
<header className="flex items-center p-4">
<Logo variant="full" className="h-8" />
</header>
)
}

The Logo component uses the resolvedTheme from useTheme() to decide which asset to render. This ensures that even if the user selects "System", the logo correctly matches the actual dark or light state of the OS.

// Internal logic in frontend/src/components/Common/Logo.tsx
const { resolvedTheme } = useTheme()
const isDark = resolvedTheme === "dark"

const fullLogo = isDark ? logoLight : logo
const iconLogo = isDark ? iconLight : icon

Step 2: Configuring Responsive Branding in Sidebars

In many dashboard applications, the logo needs to change shape when a sidebar collapses. The Logo component handles this via the responsive variant, which leverages Tailwind's group-data selectors.

In frontend/src/components/Sidebar/AppSidebar.tsx, the logo is placed within a SidebarHeader:

import { Logo } from "@/components/Common/Logo"
import { Sidebar, SidebarHeader } from "@/components/ui/sidebar"

export function AppSidebar() {
return (
<Sidebar collapsible="icon">
<SidebarHeader className="px-4 py-6 group-data-[collapsible=icon]:px-0 group-data-[collapsible=icon]:items-center">
<Logo variant="responsive" />
</SidebarHeader>
{/* ... other sidebar content */}
</Sidebar>
)
}

When the sidebar is in its expanded state, the full logo is visible. When collapsed (indicated by the [collapsible=icon] data attribute), the Logo component hides the full version and displays the icon version:

// Logic for variant="responsive" in Logo.tsx
<img
src={fullLogo}
alt="FastAPI"
className={cn(
"h-6 w-auto group-data-[collapsible=icon]:hidden",
className,
)}
/>
<img
src={iconLogo}
alt="FastAPI"
className={cn(
"size-5 hidden group-data-[collapsible=icon]:block",
className,
)}
/>

Step 3: Branding the Authentication Flow

The AuthLayout component provides a split-screen design for login and signup pages. It places a large, non-interactive version of the logo in a sidebar on large screens.

To use the AuthLayout for a new page, wrap your form content with it:

import { AuthLayout } from "@/components/Common/AuthLayout"

export function LoginPage() {
return (
<AuthLayout>
<div className="flex flex-col gap-2 text-center">
<h1 className="text-2xl font-semibold tracking-tight">
Welcome back
</h1>
{/* Your Login Form Here */}
</div>
</AuthLayout>
)
}

Inside frontend/src/components/Common/AuthLayout.tsx, the logo is configured with asLink={false} to prevent navigation while the user is in the middle of an auth flow:

<div className="bg-muted dark:bg-zinc-900 relative hidden lg:flex lg:items-center lg:justify-center">
<Logo variant="full" className="h-16" asLink={false} />
</div>

Step 4: Managing Theme-Specific Icons

For UI elements like theme switchers, you may need to map specific icons to theme states. The project uses the LucideIcon type to ensure consistency when working with the lucide-react library.

In frontend/src/components/Common/Appearance.tsx, an ICON_MAP is used to associate themes with icons:

import { Monitor, Moon, Sun } from "lucide-react"
import type { LucideIcon } from "@/components/Common/Appearance"

const ICON_MAP: Record<string, LucideIcon> = {
light: Sun,
dark: Moon,
system: Monitor,
}

You can use this pattern whenever you need to render an icon dynamically based on the application state.

Step 5: Customizing Brand Assets

To replace the default FastAPI branding with your own, you only need to update the imports in frontend/src/components/Common/Logo.tsx. Replace the following files in the public/assets/images/ directory:

  1. fastapi-logo.svg: Full logo for light mode.
  2. fastapi-logo-light.svg: Full logo for dark mode.
  3. fastapi-icon.svg: Icon-only version for light mode.
  4. fastapi-icon-light.svg: Icon-only version for dark mode.

The Logo component will automatically pick up these changes across the entire application, including the sidebar and authentication layouts.

Summary

By using the Logo component and AuthLayout, you have:

  1. Created a theme-aware identity system.
  2. Implemented a responsive branding strategy for collapsible sidebars.
  3. Standardized the look and feel of your authentication pages.

Next, you might want to explore frontend/src/components/theme-provider.tsx to customize the available color palettes or default theme settings.