This guide explains how to customize the Nebutra Sailor template for your own brand.
# 1. Fork and clone the repository
git clone https://github.com/YOUR_USERNAME/YOUR_REPO.git
cd YOUR_REPO
# 2. Run the brand initialization wizard
pnpm brand:init
# 3. Add your logo assets (see Asset Requirements below)
# 4. Apply your branding
pnpm brand:apply
# 5. Install dependencies and start development
pnpm install
pnpm devThe white-label system updates the following:
| Component | Changes |
|---|---|
| README.md | Brand name, tagline, repository URLs, badges |
| README.zh-CN.md | Chinese version with same updates |
| packages/brand/src/metadata.ts | Brand constants, colors, domains |
| packages/brand/assets/ | Logo files, favicons |
| packages/design/tokens/ | Typography, theme tokens, colors (CSS vars) |
| package.json files | NPM scope (@nebutra → @yourbrand) |
| .env.example | Domain URLs |
After running pnpm brand:init, you'll have a brand.config.ts file with these options:
const config: BrandConfig = {
// Brand Identity
brand: {
name: "MyBrand",
tagline: "The Open-Source Enterprise SaaS Platform",
description: "AI-native enterprise platform",
vision: {
pillars: [
{ word: "My", meaning: "Your unique value" },
{ word: "Brand", meaning: "Your story" },
],
},
},
// Company Info
company: {
name: "My Company Inc.",
nameCN: "我的公司", // Optional Chinese name
email: "hello@mybrand.com",
year: 2024,
},
// Domains
domains: {
landing: "mybrand.com",
app: "app.mybrand.com",
api: "api.mybrand.com",
studio: "studio.mybrand.com",
cdn: "cdn.mybrand.com",
},
// Social Links
social: {
twitter: "https://twitter.com/mybrand",
github: "https://github.com/mybrand/platform",
discord: "https://discord.gg/mybrand",
},
// GitHub Repository (for badges)
repo: {
owner: "mybrand",
name: "platform",
},
// Colors (hex values)
colors: {
primary: { 500: "#6366f1", ... },
accent: { 500: "#14b8a6", ... },
neutral: { 900: "#18181b", ... },
},
// Feature Toggles
features: {
web3: false, // Disable blockchain features
ecommerce: false, // Disable Shopify integration
recsys: false, // Disable recommendation system
content: true, // Keep content/feed system
stripe: true, // Keep Stripe payments
resend: true, // Keep email service
},
// NPM Scope
packageScope: "@mybrand",
// License
license: {
type: "FSL-1.1-ALv2",
commercialExempt: ["My Company Inc."],
},
};Place your custom assets in brand.config/assets/:
brand.config/
└── assets/
├── logo/
│ ├── logo-color.svg # Main colorful logo
│ ├── logo-inverse.svg # White version (for dark backgrounds)
│ ├── logo-mono.svg # Monochrome version
│ ├── logo-horizontal-en.svg # Horizontal layout (English)
│ └── logo-horizontal-zh.svg # Horizontal layout (Chinese)
└── favicon/
├── favicon.ico # 32x32 ICO
├── favicon.svg # SVG favicon
├── apple-touch-icon.png # 180x180 PNG
├── android-chrome-192x192.png
└── android-chrome-512x512.png
| Asset | Dimensions | Format | Usage |
|---|---|---|---|
logo-color.svg |
Any | SVG | Primary logo |
logo-inverse.svg |
Any | SVG | Dark mode / dark backgrounds |
logo-mono.svg |
Any | SVG | Monochrome contexts |
logo-horizontal-*.svg |
~320×80 | SVG | README header |
| Asset | Dimensions | Format |
|---|---|---|
favicon.ico |
32×32 | ICO |
favicon.svg |
Any | SVG |
apple-touch-icon.png |
180×180 | PNG |
android-chrome-192x192.png |
192×192 | PNG |
android-chrome-512x512.png |
512×512 | PNG |
Disable features you don't need in your deployment:
features: {
// Disable blockchain features
web3: false,
// Disable e-commerce integration
ecommerce: false,
// Disable recommendation system
recsys: false,
}When a feature is disabled:
- Related services won't be built
- Documentation references are adjusted
- Environment variables are commented out
The color system uses Tailwind's 50-950 scale. At minimum, define the 500 shade for each color:
colors: {
primary: {
50: "#f0f9ff",
100: "#e0f2fe",
// ... more shades
500: "#3b82f6", // ← Your main brand color
// ... darker shades
950: "#172554",
},
accent: {
// Secondary/accent color scale
500: "#10b981",
},
}Tip: Use Tailwind Color Generator to generate a full scale from a single color.
The design system uses open-source fonts by default:
| Purpose | Default Font | License |
|---|---|---|
| UI / Body | Inter | OFL 1.1 |
| Headings | Inter | OFL 1.1 |
| Code | JetBrains Mono | OFL 1.1 |
| CJK | Noto Sans SC | OFL 1.1 |
To replace with your own fonts:
Edit packages/design/tokens/styles.css:
:root {
--font-sans: "YourBrandFont", "Inter", -apple-system, sans-serif;
--font-heading: "YourDisplayFont", "Inter", -apple-system, sans-serif;
/* ... */
}Typography is now CSS-only — there is no longer a TypeScript token file. All font usage in components reads from these CSS variables via Tailwind (
font-sans,font-heading) orvar(--font-*).
If self-hosting fonts, add them to public/fonts/ and update the @font-face declarations:
@font-face {
font-family: "YourBrandFont";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("/fonts/YourBrandFont-Regular.woff2") format("woff2");
}Update the font imports in fonts.css:
@import url("https://fonts.googleapis.com/css2?family=YourBrandFont:wght@400;500;600;700&display=swap");The design system exposes these typography tokens:
| Token | Usage |
|---|---|
fontFamilies.primary |
Body text, UI elements |
fontFamilies.heading |
Titles, headlines |
fontFamilies.mono |
Code, technical content |
fontFamilies.cjk |
Chinese/Japanese/Korean text |
fontSizes.* |
xs, sm, base, lg, xl, 2xl-8xl |
typeStyles.* |
h1-h6, body, caption, code, button |
See Typography Documentation for full details.
The design system (@nebutra/ui) is the single source of truth for all UI styling.
packages/design/
├── tokens/ # Runtime CSS variables (★ SOURCE OF TRUTH) — colors, spacing, typography
├── brand/ # Brand constants, colors, motion language
├── theme/ # Multi-theme presets (oklch, 6 variants — neon / dark-dense / etc.)
├── ui/ # Component library — Radix + HeroUI + Nebutra primitives + layout
└── icons/ # 541 Geist icons as tree-shakable TSX components
Create brand-specific theme overrides in packages/design/brand/src/metadata.ts
(brand constants) and packages/design/tokens/styles.css (runtime CSS variables):
// packages/design/brand/src/metadata.ts
export const BRAND_COLORS = {
primary: "#6366f1", // Your brand primary
emphasis: "#4f46e5",
};/* packages/design/tokens/styles.css */
:root {
--brand-primary: #6366f1;
--brand-accent: #4f46e5;
--brand-gradient: linear-gradient(135deg, var(--brand-primary), var(--brand-accent));
}For multi-theme presets (neon / dark-dense / minimal / vibrant / ocean), see
packages/design/theme/.
| Layer | Package | Purpose |
|---|---|---|
| SSOT | @yourbrand/tokens |
Runtime CSS variables, single source of truth |
| Brand | @yourbrand/brand |
Brand constants, colors, motion language |
| Components | @yourbrand/ui |
Radix + HeroUI + Nebutra primitives + layout |
| Themes | @yourbrand/theme |
Multi-theme presets (oklch, 6 variants) |
See Component Library Policy for governance rules.
Some elements require manual updates:
The README uses hero banners from packages/brand/assets/hero/. Create your own:
hero-light.svg(1200×420)hero-dark.svg(1200×420)hero-zh-light.svg(Chinese, 1200×420)hero-zh-dark.svg(Chinese, 1200×420)
Custom icons in packages/brand/assets/icons/:
ai.svgtenants.svgenterprise.svgworkflows.svgsecurity.svgtoolkit.svg
After modifying brand.config.ts, run:
pnpm brand:applyThis is non-destructive and can be run multiple times.
To get updates from the original Nebutra Sailor repository:
# Add upstream remote (one time)
git remote add upstream https://github.com/Nebutra/Nebutra-Sailor.git
# Fetch and merge updates
git fetch upstream
git merge upstream/main
# Re-apply your branding
pnpm brand:applyEnsure brand.config.ts is in the root directory and exports a default config:
import type { BrandConfig } from "./scripts/brand-types";
const config: BrandConfig = { ... };
export default config;- Check that assets are in
brand.config/assets/(not directly inpackages/brand/assets/) - Run
pnpm brand:applyagain - Clear build caches:
pnpm clean
After changing packageScope, you may need to:
# Clean and reinstall
pnpm clean
rm -rf node_modules
pnpm installFor questions about white-labeling:
- Open an issue on GitHub
- Tag with
white-labellabel