How to Customize the Open‑SEO UI: A Complete Guide for Developers
Customize the Open‑SEO UI by editing layout primitives in web/src/lib/layout.shared.tsx, extending tailwind.config.ts for styling, and adding file‑based routes under web/src/routes/ to create new pages.
Open‑SEO's front‑end is a modern React application built with TypeScript, Vite, and the Fumadocs UI component library. Understanding how to customize the Open‑SEO UI requires familiarity with its file‑based routing system, reusable layout primitives, and Tailwind‑powered theme system. This guide walks through the core architecture and provides concrete, runnable examples for changing visual styles, adjusting layouts, and adding new pages.
Core Architecture of the Open‑SEO UI
The Open‑SEO UI is organized around five interconnected areas. Each area has specific responsibilities and well‑defined source files.
| Area | Purpose | Key Source Files |
|---|---|---|
| Routing | File‑based router maps URL paths to React components | web/src/router.tsx |
| Layouts | Shared page layouts (home, docs, blog) using Fumadocs UI layouts | web/src/lib/layout.shared.tsx |
| Theme | useThemePreference hook manages system, light, or dark modes |
src/client/components/ThemePreferenceMenuItems.tsx |
| Main UI Components | Reusable pieces including footer, header, and marketing blocks | web/src/components/feature-page.tsx, web/src/components/site-footer.tsx |
| Styling | Tailwind CSS configuration for colors, spacing, and utilities | tailwind.config.ts |
How the Theme System Works
The useThemePreference hook reads and writes a themePreference value to localStorage. It injects an inline script (themePreferenceInitScript) into the HTML head to prevent flash of unstyled content on first paint.
Components consume this value and apply Tailwind dark‑mode classes such as bg-base‑200 and text-base‑content. The theme toggle UI itself lives in src/client/components/ThemePreferenceMenuItems.tsx.
Layout Flow and Shared Options
All pages render inside a layout component. The docs section, for example, uses DocsLayout from Fumadocs UI:
import { DocsLayout } from "fumadocs-ui/layouts/docs";
import { baseOptions } from "@/lib/layout.shared";
export default function DocsPage() {
return <DocsLayout {...baseOptions}>…</DocsLayout>;
}
The baseOptions object in web/src/lib/layout.shared.tsx is the single source of truth for navigation items, theme toggle visibility, and other global UI behaviors.
How to Customize Visual Styles in Open‑SEO
All UI elements use Tailwind utility classes. Follow these steps to introduce brand colors or adjust spacing.
Step 1: Extend Tailwind Configuration
Open tailwind.config.ts at the repository root and add custom values:
module.exports = {
darkMode: "class",
theme: {
extend: {
colors: {
brand: "#0A84FF",
},
},
},
};
Step 2: Apply Custom Classes in Components
Reference the new theme values directly in your components:
<div className="bg-brand text-white p-4 rounded">
Welcome to the customized Open‑SEO UI!
</div>
Changes hot‑reload instantly when running npm run dev.
How to Override Existing UI Components
Components are imported directly by layouts, so editing the source file propagates changes site‑wide.
Modifying the Site Footer
Edit web/src/components/site-footer.tsx to update branding:
export function SiteFooter() {
return (
<footer className="bg-gray-900 text-gray-100 py-6">
<p>© 2024 MyCompany – All rights reserved.</p>
</footer>
);
}
Restricting Theme Options to Dark Only
Modify src/client/components/ThemePreferenceMenuItems.tsx to remove light and system options:
const THEME_OPTIONS = [
{ value: "dark", label: "Dark", icon: Moon },
];
How to Add New Pages to the Open‑SEO UI
Open‑SEO uses a file‑based routing convention. The router automatically discovers files under web/src/routes/ and maps their paths to URLs.
Creating a Marketing Page
Create a new file following the underscore‑prefix convention for route groups:
// web/src/routes/_marketing/new-feature.tsx
import { FeaturePage } from "@/components/feature-page";
export default function NewFeature() {
return (
<FeaturePage
title="My New Feature"
description="Explain what it does."
/>
);
}
This page becomes available at /marketing/new-feature because the file path mirrors the URL hierarchy.
Adding Custom Navigation Links
Update web/src/lib/layout.shared.tsx to expose new pages in the site navigation:
export const baseOptions = {
nav: [
{ title: "Features", href: "/features" },
{ title: "My Custom Page", href: "/marketing/custom-page" },
],
};
Complete Customization Examples
Example: Full Custom Marketing Page with Brand Styling
// web/src/routes/_marketing/custom-page.tsx
import { FeaturePage } from "@/components/feature-page";
export default function CustomPage() {
return (
<FeaturePage
title="Custom Page"
description="A brand‑new marketing page with custom branding."
primaryCta={{ label: "Get Started", href: "/signup" }}
/>
);
}
Example: Extended Tailwind with Full Brand Palette
// tailwind.config.ts
module.exports = {
theme: {
extend: {
colors: {
brand: {
50: "#E3F2FD",
500: "#0A84FF",
900: "#0D47A1",
},
},
},
},
};
Key Files for Open‑SEO UI Customization
| File | Role |
|---|---|
web/src/router.tsx |
Central router wiring URL paths to components |
web/src/lib/layout.shared.tsx |
Shared layout options for navigation and theme toggle |
src/client/components/ThemePreferenceMenuItems.tsx |
Theme selection UI |
web/src/components/feature-page.tsx |
Reusable marketing page component |
web/src/components/site-footer.tsx |
Site footer for branding updates |
tailwind.config.ts |
Tailwind CSS configuration |
Summary
- Customize the Open‑SEO UI by editing
web/src/lib/layout.shared.tsxfor global layout changes,tailwind.config.tsfor styling, andweb/src/routes/for new pages. - The
useThemePreferencehook insrc/client/components/ThemePreferenceMenuItems.tsxcontrols light, dark, and system modes. - File‑based routing automatically maps
web/src/routes/_marketing/page.tsxto/marketing/pageURLs. - All components use Tailwind classes, enabling rapid visual customization without touching core business logic.
Frequently Asked Questions
How do I change the default theme in Open‑SEO?
Edit src/client/components/ThemePreferenceMenuItems.tsx and modify the THEME_OPTIONS array. To default to dark mode only, remove the light and system entries. The theme persists via localStorage and applies on first paint through an inline script injected by useThemePreference.
Where do I add new navigation links in Open‑SEO?
Add navigation links in web/src/lib/layout.shared.tsx within the baseOptions.nav array. Each entry requires a title and href. The router automatically resolves paths relative to your route files in web/src/routes/.
Can I use custom colors throughout the Open‑SEO UI?
Yes. Define custom colors in tailwind.config.ts under theme.extend.colors, then reference them with standard Tailwind utility classes like bg-brand or text-brand-500. The Vite dev server hot‑reloads these changes immediately.
How do I create a completely new page layout in Open‑SEO?
Create a new layout component in web/src/components/ and import it in route files under web/src/routes/. For Fumadocs‑compatible pages, import layout variants from "fumadocs-ui/layouts/docs" or "fumadocs-ui/layouts/home" and pass your custom baseOptions.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →