BRANDING SYSTEM - nself-org/cli GitHub Wiki
The nself Branding System provides comprehensive white-label functionality for managing brand identity, including logos, colors, fonts, typography, and custom CSS. It supports multi-tenant isolation, asset versioning, and security validation.
File: /Users/admin/Sites/nself/src/lib/whitelabel/branding.sh
Lines of Code: 1,782
Functions: 26
Status: Production-ready
- Create and manage brand identity
- Multi-tenant support with isolation
- Brand metadata (name, tagline, description)
- Update and delete brands with confirmation
- Upload logos (PNG, JPG, JPEG, SVG, WebP)
- Multiple logo types: main, icon, email, favicon
- File size validation (max 5MB)
- MIME type verification
- Asset versioning with timestamps
- Symlink management for easy access
- Full color palette management
- Hex color validation (#RGB or #RRGGBB)
- Accessibility validation
- Support for 10+ color categories:
- Primary, Secondary, Accent
- Background, Text, Text Light
- Border, Success, Warning, Error, Info
- Font family settings (primary, secondary, code)
- Font size configuration (base, small, large, h1, h2, h3)
- Font weight settings (normal, medium, semibold, bold)
- Line height options (tight, normal, relaxed)
- Custom font upload (WOFF, WOFF2, TTF, OTF)
- Font file validation (max 1MB)
- Upload custom CSS files (max 2MB)
- Syntax validation (balanced braces)
- Security scanning:
- External URL detection
- @import statement warnings
- XSS vulnerability checks (expression())
- Versioned CSS with rollback
- Automatic version backups on changes
- Keep last 10 versions
- Restore previous versions
- Version listing with timestamps
- Secure file permissions (0644 for files, 0755 for dirs)
- File size limits enforcement
- MIME type validation
- CSS security scanning
- Input sanitization
- Multi-tenant isolation
- Auto-generate CSS variables from config
- Color variables (
--color-*) - Font variables (
--font-*) - Size variables (
--font-size-*) - Weight variables (
--font-weight-*) - Line height variables (
--line-height-*)
# Initialize branding system (default tenant)
nself whitelabel branding init
# Initialize for specific tenant
nself whitelabel branding init --tenant mycompany
# Verify initialization
ls -la branding/
# Output:
# branding/
# โโโ config.json # Main configuration
# โโโ logos/ # Logo assets
# โโโ css/ # CSS files
# โโโ fonts/ # Custom fonts
# โโโ assets/ # Other assets
# โโโ versions/ # Version backups# Create a brand
nself whitelabel branding create "My Company"
# Create with tagline and description
nself whitelabel branding create "My Company" \
--tagline "Innovation Through Technology" \
--description "Leading provider of cloud solutions"
# Create for specific tenant
nself whitelabel branding create "Client Brand" --tenant client123# Update brand name
nself whitelabel branding update --name "New Company Name"
# Update tagline only
nself whitelabel branding update --tagline "New Tagline"
# Update multiple fields
nself whitelabel branding update \
--name "Updated Name" \
--tagline "Updated Tagline" \
--description "Updated description"# Upload main logo
nself whitelabel logo upload /path/to/logo.png
# Upload specific logo type
nself whitelabel logo upload /path/to/icon.svg --type icon
nself whitelabel logo upload /path/to/email-logo.png --type email
nself whitelabel logo upload /path/to/favicon.ico --type favicon
# List all logos
nself whitelabel logo list
# Remove a logo
nself whitelabel logo remove main
nself whitelabel logo remove icon
# Get logo information
nself whitelabel branding asset-info branding/logos/logo-main.pngSupported Logo Types:
-
main- Primary brand logo -
icon- App icon/square logo -
email- Email template logo -
favicon- Browser favicon
Supported Formats:
- PNG, JPG, JPEG, SVG, WebP
- Maximum size: 5MB per file
# Set primary color
nself whitelabel branding set-colors --primary "#0066cc"
# Set multiple colors
nself whitelabel branding set-colors \
--primary "#0066cc" \
--secondary "#ff6600" \
--accent "#00cc66"
# Set full palette
nself whitelabel branding set-colors \
--primary "#0066cc" \
--secondary "#ff6600" \
--accent "#00cc66" \
--background "#ffffff" \
--text "#333333"Color Validation:
- Must be valid hex code (#RGB or #RRGGBB)
- Accessibility check for color contrast
- Warning if primary and secondary are too similar
# Set font families
nself whitelabel branding set-fonts \
--primary "Inter, system-ui, sans-serif" \
--secondary "Georgia, serif" \
--code "Fira Code, monospace"
# Set typography settings
nself whitelabel branding set-typography \
--base-size "16px" \
--h1-size "32px" \
--h2-size "24px" \
--normal-weight "400" \
--bold-weight "700" \
--line-height "1.5"
# Upload custom font file
nself whitelabel font upload /path/to/custom-font.woff2 --name "CustomFont"Supported Font Formats:
- WOFF, WOFF2, TTF, OTF
- Maximum size: 1MB per file
# Set custom CSS
nself whitelabel branding set-css /path/to/custom.css
# Remove custom CSS
nself whitelabel branding remove-css
# View CSS security scan results
# (automatically runs on upload)CSS Security Checks:
- External URL detection (data exfiltration risk)
- @import statement detection (external stylesheet loading)
- expression() detection (XSS vulnerability)
- Syntax validation (balanced braces)
# List all versions
nself whitelabel branding list-versions
# Output:
# 1. 2026-01-30 14:30:00
# 2. 2026-01-29 10:15:00
# 3. 2026-01-28 16:45:00
# Restore a previous version
nself whitelabel branding restore 20260129_101500
# Versions are automatically created on every change
# Last 10 versions are kept (older ones auto-deleted)# Export configuration (JSON)
nself whitelabel config export > branding-backup.json
nself whitelabel config export --tenant client123 > client-branding.json
# Export as YAML (requires yq or python3)
nself whitelabel config export --format yaml > branding.yaml
# Import configuration
nself whitelabel config import branding-backup.json
nself whitelabel config import client-branding.json --tenant client123
# Validate configuration
nself whitelabel branding validate
nself whitelabel branding validate --tenant client123# View asset information
nself whitelabel branding asset-info branding/logos/logo-main.png
# Clean unused assets
nself whitelabel branding clean-unused
# List all resources
nself whitelabel list# List all tenants
nself whitelabel tenants list
# Create tenant-specific brand
nself whitelabel branding create "Client Brand" --tenant client123
# Export tenant config
nself whitelabel config export --tenant client123
# Import tenant config
nself whitelabel config import config.json --tenant client123{
"version": "1.0.0",
"tenantId": "default",
"brand": {
"name": "nself",
"tagline": "Powerful Backend for Modern Applications",
"description": "Open-source backend infrastructure platform"
},
"colors": {
"primary": "#0066cc",
"secondary": "#ff6600",
"accent": "#00cc66",
"background": "#ffffff",
"text": "#333333",
"textLight": "#666666",
"border": "#e0e0e0",
"success": "#00cc66",
"warning": "#ff9900",
"error": "#cc0000",
"info": "#0066cc"
},
"typography": {
"fonts": {
"primary": "Inter, system-ui, sans-serif",
"secondary": "Georgia, serif",
"code": "Fira Code, Consolas, monospace"
},
"sizes": {
"base": "16px",
"small": "14px",
"large": "18px",
"h1": "32px",
"h2": "24px",
"h3": "20px"
},
"weights": {
"normal": "400",
"medium": "500",
"semibold": "600",
"bold": "700"
},
"lineHeights": {
"tight": "1.25",
"normal": "1.5",
"relaxed": "1.75"
}
},
"logos": {
"main": "logo-main-20260130_143000.png",
"icon": "logo-icon-20260130_143015.svg",
"email": "logo-email-20260130_143030.png",
"favicon": null
},
"customCSS": "custom-20260130_143045.css",
"customFonts": [
{
"name": "CustomFont",
"path": "CustomFont-20260130_143100.woff2"
}
],
"theme": "light",
"createdAt": "2026-01-30T14:30:00Z",
"updatedAt": "2026-01-30T14:31:00Z"
}/**
* nself White-Label CSS Variables
* Auto-generated from branding configuration
* Do not edit manually - changes will be overwritten
*/
:root {
/* ========================================
* Colors
* ======================================== */
--color-primary: #0066cc;
--color-secondary: #ff6600;
--color-accent: #00cc66;
--color-background: #ffffff;
--color-text: #333333;
--color-textLight: #666666;
--color-border: #e0e0e0;
--color-success: #00cc66;
--color-warning: #ff9900;
--color-error: #cc0000;
--color-info: #0066cc;
/* ========================================
* Typography - Fonts
* ======================================== */
--font-primary: Inter, system-ui, sans-serif;
--font-secondary: Georgia, serif;
--font-code: Fira Code, Consolas, monospace;
/* ========================================
* Typography - Sizes
* ======================================== */
--font-size-base: 16px;
--font-size-small: 14px;
--font-size-large: 18px;
--font-size-h1: 32px;
--font-size-h2: 24px;
--font-size-h3: 20px;
/* ========================================
* Typography - Weights
* ======================================== */
--font-weight-normal: 400;
--font-weight-medium: 500;
--font-weight-semibold: 600;
--font-weight-bold: 700;
/* ========================================
* Typography - Line Heights
* ======================================== */
--line-height-tight: 1.25;
--line-height-normal: 1.5;
--line-height-relaxed: 1.75;
}/* Use generated variables in your CSS */
.header {
background-color: var(--color-primary);
color: var(--color-background);
font-family: var(--font-primary);
font-size: var(--font-size-h1);
font-weight: var(--font-weight-bold);
line-height: var(--line-height-tight);
}
.button-primary {
background: var(--color-primary);
color: white;
border: 1px solid var(--color-border);
}
.button-secondary {
background: var(--color-secondary);
color: white;
}
.text-muted {
color: var(--color-textLight);
}branding/
โโโ config.json # Main configuration file
โโโ .gitignore # Ignore uploaded assets
โ
โโโ logos/ # Logo assets
โ โโโ .gitkeep
โ โโโ logo-main-20260130_143000.png
โ โโโ logo-main.png โ logo-main-20260130_143000.png # Symlink to current
โ โโโ logo-icon-20260130_143015.svg
โ โโโ logo-icon.svg โ logo-icon-20260130_143015.svg
โ
โโโ css/ # CSS files
โ โโโ .gitkeep
โ โโโ variables.css # Auto-generated CSS variables
โ โโโ custom-20260130_143045.css
โ โโโ custom.css โ custom-20260130_143045.css # Symlink to current
โ
โโโ fonts/ # Custom fonts
โ โโโ .gitkeep
โ โโโ CustomFont-20260130_143100.woff2
โ
โโโ assets/ # Other assets
โ โโโ .gitkeep
โ
โโโ versions/ # Version backups
โ โโโ config-20260130_143000.json
โ โโโ config-20260129_101500.json
โ โโโ config-20260128_164500.json
โ
โโโ client123/ # Tenant-specific (example)
โโโ config.json
โโโ logos/
โโโ css/
โโโ fonts/
โโโ assets/
-
Size Limits
- Logos: 5MB max
- CSS: 2MB max
- Fonts: 1MB max
-
Format Validation
- Logos: PNG, JPG, JPEG, SVG, WebP only
- Fonts: WOFF, WOFF2, TTF, OTF only
- CSS: .css extension required
-
MIME Type Verification
- Uses
filecommand for real type detection - Prevents extension spoofing attacks
- Uses
- Directories: 0755 (rwxr-xr-x)
- Files: 0644 (rw-r--r--)
- Prevents unauthorized modification
# Automatically scans uploaded CSS for:
1. External URLs (potential data exfiltration)
- Pattern: url(http://... or url(https://...
2. @import statements (external stylesheet loading)
- Can load malicious external code
3. expression() usage (IE-specific XSS)
- Known XSS vulnerability vector
4. Syntax validation
- Ensures balanced braces
- Prevents broken CSS injection- Each tenant has separate directory structure
- Configuration files are tenant-specific
- No cross-tenant asset access
- Tenant ID validation on all operations
- Brand names sanitized (alphanumeric + spaces, hyphens, underscores)
- Hex color validation with regex
- File path resolution to prevent directory traversal
- No shell command injection vulnerabilities
create_brand <name> [tenant_id] [tagline] [description]
update_brand --name <name> [--tagline <tagline>] [--description <desc>]
delete_brand [tenant_id]upload_brand_logo <path> [type]
upload_logo <path> --type <type>
list_logos
remove_logo <type>set_brand_colors --primary <hex> [--secondary <hex>] [--accent <hex>] [--background <hex>] [--text <hex>]
validate_hex_color <color>
validate_color_palette <primary> <secondary> [background]set_brand_fonts --primary <font> [--secondary <font>] [--code <font>]
set_typography --base-size <size> [--h1-size <size>] [--normal-weight <weight>] [--line-height <height>]
upload_font <path> [name]set_custom_css <path>
remove_custom_css
generate_css_variablesbranding::create_version_backup
branding::list_versions
branding::restore_version <timestamp>
branding::cleanup_old_versionsbranding::get_asset_info <path>
clean_unused_assetslist_tenants
branding::get_tenant_config_path <tenant_id>
branding::ensure_tenant_isolation <tenant_id>initialize_branding_system [tenant_id]
preview_branding
validate_branding_config [tenant_id]
export_whitelabel_config [format] [tenant_id]
import_whitelabel_config <path> [tenant_id]
list_whitelabel_resources# File not found
Error: Logo file not found: /path/to/logo.png
# Solution: Check file path is correct
# Unsupported format
Error: Unsupported logo format 'gif'. Supported: png jpg jpeg svg webp
# Solution: Convert to supported format
# File too large
Error: Logo file too large (6.50 MB). Maximum: 5 MB
# Solution: Compress or resize the file
# Invalid color
Error: Invalid primary color format. Use #RRGGBB
# Solution: Use hex format: #0066cc
# Branding not initialized
Error: Branding not initialized. Run 'nself whitelabel init' first.
# Solution: Initialize branding system first
# Invalid JSON
Error: Invalid JSON in config file
# Solution: Validate JSON syntax
# Missing required field
Error: Config missing required 'brand' section
# Solution: Use proper config structure
# CSS syntax error
Error: CSS syntax error - mismatched braces
# Solution: Fix CSS syntax
# Security issue
Error: CSS contains expression() - potential XSS vulnerability
# Solution: Remove dangerous CSS patterns# Always create backups before major changes
nself whitelabel config export > backup-$(date +%Y%m%d).json
# Use version restore for rollbacks
nself whitelabel branding list-versions
nself whitelabel branding restore 20260130_143000# Optimize images before upload
# PNG: Use pngcrush or optipng
pngcrush -brute logo.png logo-optimized.png
# JPG: Use jpegoptim or imagemagick
jpegoptim --max=85 logo.jpg
# SVG: Use svgo
svgo logo.svg -o logo-optimized.svg
# Fonts: Use woff2 for best compression
# Convert TTF to WOFF2 with fonttools# Always validate uploaded files
# Use CSS security scanning
# Set proper file permissions
# Isolate tenant data
# Regular security audits
nself whitelabel branding validate
nself security audit# Use consistent tenant naming
# tenant_id format: lowercase-alphanumeric-dashes
# Examples: client-abc, company-123, org-xyz
# Keep tenant configs separate
# Export/import for backup
nself whitelabel config export --tenant client-abc > client-abc-backup.json# Always use generated CSS variables
# Don't hardcode colors or fonts in application
# Regenerate after changes
nself whitelabel branding set-colors --primary "#newcolor"
# CSS variables automatically regenerated
# Include variables.css in your HTML
<link rel="stylesheet" href="/branding/css/variables.css">// Import CSS variables
import '/path/to/branding/css/variables.css';
// Use in styled-components
const Button = styled.button`
background: var(--color-primary);
color: var(--color-background);
font-family: var(--font-primary);
font-size: var(--font-size-base);
font-weight: var(--font-weight-medium);
`;
// Or with inline styles
<div style={{
backgroundColor: 'var(--color-primary)',
color: 'var(--color-text)',
fontFamily: 'var(--font-primary)'
}}>
Content
</div><template>
<div class="branded-component">
<h1>{{ title }}</h1>
<p>{{ description }}</p>
</div>
</template>
<style scoped>
@import '/path/to/branding/css/variables.css';
.branded-component {
background: var(--color-background);
color: var(--color-text);
font-family: var(--font-primary);
}
h1 {
color: var(--color-primary);
font-size: var(--font-size-h1);
font-weight: var(--font-weight-bold);
}
</style><!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/branding/css/variables.css">
<link rel="stylesheet" href="/branding/css/custom.css">
<style>
body {
font-family: var(--font-primary);
color: var(--color-text);
background: var(--color-background);
}
.header {
background: var(--color-primary);
color: white;
}
</style>
</head>
<body>
<header class="header">
<img src="/branding/logos/logo-main.png" alt="Logo">
<h1>Welcome</h1>
</header>
</body>
</html># Check CSS file exists
ls -la branding/css/variables.css
# Regenerate CSS variables
nself whitelabel branding set-colors --primary "#0066cc"
# Verify config is valid
nself whitelabel branding validate
# Check browser console for errors
# Ensure CSS file is loaded in HTML# Check logo exists
ls -la branding/logos/
# Verify logo in config
cat branding/config.json | jq '.logos'
# Check symlink
ls -la branding/logos/logo-main.png
# Re-upload logo if needed
nself whitelabel logo upload /path/to/logo.png --type main# List available versions
nself whitelabel branding list-versions
# Check version file exists
ls -la branding/versions/
# Try manual restore
cp branding/versions/config-TIMESTAMP.json branding/config.json
nself whitelabel branding validate# Review CSS file
cat branding/css/custom.css
# Remove external URLs
# Replace: url(https://example.com/font.woff)
# With: url(/branding/fonts/font.woff)
# Remove @import statements
# Replace: @import url('https://fonts.googleapis.com/...');
# With: Local font files
# Re-upload cleaned CSS
nself whitelabel branding set-css /path/to/cleaned.css- Optimize file sizes before upload
- Use CDN for branding assets in production
- Enable browser caching for logos and CSS
- Lazy load non-critical assets
- Minimal performance impact
- Better than inline styles
- Cacheable by browser
- Consistent theming
- Versions stored as JSON (small files)
- Auto-cleanup keeps only 10 versions
- No performance impact on runtime
-
Dark Mode Support
- Automatic dark theme generation
- Color palette inversion
- User preference detection
-
Advanced Typography
- Letter spacing configuration
- Text transform settings
- Custom font pairings
-
Theme Previews
- Live preview in browser
- Before/after comparison
- Mobile responsive preview
-
Asset CDN Integration
- Upload to S3/MinIO
- CloudFlare integration
- Automatic image optimization
-
Brand Kit Export
- PDF style guide generation
- Logo pack download
- Color palette swatches
-
API Endpoints
- REST API for brand management
- GraphQL mutations
- Webhook notifications on changes
- Main docs:
/docs/whitelabel/ - API reference: This file
- Examples:
/src/examples/whitelabel/
- GitHub Issues: Report bugs and feature requests
- Discussions: Ask questions and share tips
- Wiki: Community-contributed guides
- Email: [email protected]
- Enterprise: Custom branding solutions
- Training: White-label implementation workshops
MIT License - See LICENSE file for details
Last Updated: 2026-01-30 Version: 1.0.0 Author: nself Development Team