Customization Overview

Everything you can customize in Nebutra-Sailor — brand colors, themes, dashboard pages, and the onboarding flow.

Nebutra-Sailor is designed to be fully white-labeled. Every visual and structural element — from the brand palette to individual dashboard pages — is customizable without forking core packages.

What you can customize

Architecture

Customization follows a strictly unidirectional token flow. Changes at a lower layer automatically propagate upward.

@nebutra/tokens   ← Edit CSS variables here to rebrand

@nebutra/ui       ← Components consume tokens; add new components here

apps/web          ← Dashboard pages compose components
apps/landing ← Marketing site composes components

Because every color and spacing value in @nebutra/ui is a CSS variable reference (never a hardcoded hex), editing the DTCG token source at packages/design/design-tokens/tokens/*.json — or running the palette script — cascades through the entire product once the token build regenerates packages/design/tokens/styles.css.

Quick wins (under 5 minutes)

Change the brand color

# Swap blue → purple, cyan → amber in one command
node scripts/generate-palette.mjs --primary=#7C3AED --secondary=#F59E0B

The script prints a brand-override.css file to stdout — it does not write anything to disk itself. Redirect it to a file and @import it after @nebutra/tokens/styles.css, or fold the values into the DTCG token source at packages/design/design-tokens/tokens/*.json and rebuild.

Switch the active Brand Package

import { applyLanguage, clearLanguage } from "@nebutra/theme";

applyLanguage("vanta", { persist: true }); // any built-in id from LANGUAGE_REGISTRY
clearLanguage(); // back to the factory default
nebutra theme list
nebutra theme use vanta

Toggle dark mode

import { useTheme } from "@nebutra/tokens";

const { theme, setTheme } = useTheme();
setTheme("dark"); // "light" | "dark" | "system"

Advanced customization

GoalWhere to start
New Brand Packagepackages/design/tokens/brands/<id>/brand.json + an entry in packages/design/theme/src/languages.meta.json, then node packages/design/theme/scripts/sync-languages.mjs (writes the generated languages.json — do not hand-edit it)
New UI primitivepackages/design/ui/src/components/ + Storybook story
New dashboard sectionapps/web/src/app/(dashboard)/[section]/page.tsx
Modify onboarding stepsapps/web/src/app/(onboarding)/
Rewrite the palette generatorscripts/generate-palette.mjs

Token architecture at a glance

All runtime CSS variables are compiled into a single file, packages/design/tokens/styles.css — but that file is generated (its own header says so) and gets overwritten on every token build. The single source of truth is the DTCG token JSON at packages/design/design-tokens/tokens/*.json; edit there, then run the Style Dictionary build so sync-styles.mjs regenerates styles.css. Never hardcode hex values anywhere in the codebase.

/* packages/design/tokens/styles.css — excerpt */
:root {
  --brand-primary:   var(--blue-9);     /* #0033FE */
  --brand-accent:    var(--cyan-9);     /* #0BF1C3 */
  --brand-gradient:  135deg, var(--blue-9) 0%, var(--cyan-9) 100%;

  --neutral-1:  #ffffff;
  --neutral-12: #0a0a0a;
}

Open Storybook's Design Tokens section for a live visual reference of every token in both light and dark mode: pnpm --filter @nebutra/storybook devhttp://localhost:6006


How is this guide?

Edit on GitHub

Last updated on

On this page