28 KiB
Branding Customization Guide
Complete guide for creating and customizing branded instances of the Timebank platform with unique visual identity, configuration, content, and protected deployment.
Table of Contents
- Overview
- Configuration Protection System
- Theme Customization
- Logo Customization
- Platform Configuration
- Footer Customization
- Custom Content Pages
- Database Updates
- Complete Setup Workflow
- Deployment & Updates
- Troubleshooting
- Best Practices
Overview
The platform supports complete branding through four main customization layers:
- Theme System - Visual styling (colors, fonts, spacing)
- Logo System - Theme-specific branding assets
- Platform Configuration - Behavior, limits, translations, footer structure
- Content Seeding - Custom pages and navigation links
All customizations are protected from git overwrites during deployments using a config template system.
Configuration Protection System
How It Works
The Problem:
When running deploy.sh, git pull would overwrite customized configuration files with defaults from the repository.
The Solution:
.examplefiles are tracked in git (templates with defaults)- Actual config files are gitignored (safe from overwrites)
deploy.shautomatically creates configs from templates if they don't exist- Custom changes persist through all deployment updates
Protected Configuration Files
The following files are protected from git overwrites:
| File | Purpose | Template |
|---|---|---|
config/themes.php |
Theme configuration (colors, fonts, logos) | config/themes.php.example |
config/timebank-default.php |
Default platform configuration | config/timebank-default.php.example |
config/timebank_cc.php |
Platform-specific overrides | Create as needed |
Initial Migration
Run once per repository to enable the protection system:
# From repository root
./scripts/migrate-to-example-configs.sh
This will:
- Remove config files from git tracking (keeps your local files intact)
- Add .example template files to git
- Update .gitignore
- Create a commit with all changes
- Ready to push to repository
After migration:
git push origin main
Configuration Workflow
New Installation
git clone <repo>
cd timebank_cc_2
./deploy.sh
What happens:
- No config files exist yet
deploy.shcreates them from.exampletemplates- Customize configs with your branding
- Customizations are now protected
Updating Existing Installation
./deploy.sh
What happens:
- Config check runs BEFORE git pull
- Your custom configs exist → Preserved
- Git pulls latest
.exampletemplates (updated defaults) - Your custom configs remain unchanged
- Review
.examplefiles for new features to merge manually
Merging Updates from Templates
Option 1: Manual Review (Recommended)
# Compare your config with latest template
diff config/themes.php config/themes.php.example
# Review changes and merge relevant updates
nano config/themes.php
Option 2: Regenerate from Template
⚠️ Warning: This erases all customizations!
# Backup first
cp config/themes.php config/themes.php.backup
# Delete and regenerate
rm config/themes.php
./deploy.sh
# Re-apply customizations from backup
Theme Customization
Setting Up a Theme
Location: config/themes.php
Activation: Set TIMEBANK_THEME in .env
TIMEBANK_THEME=your_brand_name
Creating a New Theme
Add your theme definition to config/themes.php:
'your_brand_name' => [
'name' => 'Your Brand Name',
'description' => 'Description of your brand theme',
// Logo Configuration
'logos' => [
'svg_inline' => 'logos.your_brand_name',
'email_logo' => 'app-images/your_brand_name_mail_logo.png',
],
// Color Palette
'colors' => [
// Brand Colors
'brand' => '#FF5733',
'secondary' => '#EBEDEE',
'accent' => '#434343',
// Primary Palette (9 shades)
'primary' => [
50 => '#fef2f2',
100 => '#fee2e2',
200 => '#fecaca',
300 => '#fca5a5',
400 => '#f87171',
500 => '#ef4444', // Main primary color
600 => '#dc2626',
700 => '#b91c1c',
800 => '#991b1b',
900 => '#7f1d1d',
],
// Functional Colors
'danger-dark' => '#b91c1c',
'danger' => '#ef4444',
'danger-light' => '#fecaca',
'reaction' => '#eab308',
'reaction-hover' => '#ca8a04',
// UI Elements
'background' => '#FFFFFF',
'border' => '#CDCFD0',
'surface' => '#F9FAFB',
// Text Colors
'text' => [
'primary' => '#111827',
'secondary' => '#6E6F70',
'light' => '#9CA3AF',
'surface' => '#F9FAFB',
'background' => '#FFFFFF',
],
// Logo Color (for SVG fill)
'logo' => '#000000',
],
// Typography
'typography' => [
'font_family_body' => 'Roboto, sans-serif',
'font_family_heading' => 'Oswald, sans-serif',
'font_size_base' => '16px',
'line_height_base' => '1.7',
'heading_transform' => 'uppercase', // or 'none'
'heading_sizes' => [
'h1' => '30px',
'h2' => '24px',
'h3' => '20px',
'h4' => '16px',
],
'links' => [
'text_decoration' => 'underline',
'text_decoration_hover' => 'underline',
'font_weight' => '600',
],
],
],
Using Theme Colors in Views
CSS Classes (Recommended):
<div class="bg-theme-brand text-white">
<h1 class="text-theme-primary-600">Title</h1>
<p class="text-theme-text-medium">Body text</p>
<button class="border-theme-border bg-theme-primary-500">Click</button>
</div>
PHP Helper Functions:
// In Livewire components or controllers
$brandColor = theme_color('brand');
$primaryColor = theme_color('primary.500');
$fontFamily = theme_font('font_family_body');
$logoView = theme_logo('svg_inline');
$emailLogo = theme_logo('email_logo');
Important: Always use theme-aware classes/functions. Never hardcode colors like bg-blue-500 or text-gray-600.
Testing Themes
Switch themes by changing .env:
TIMEBANK_THEME=timebank_cc
TIMEBANK_THEME=uuro
TIMEBANK_THEME=vegetable
TIMEBANK_THEME=yellow
After changing theme:
php artisan config:clear
npm run build
Test all UI components across themes to ensure consistency.
Logo Customization
Logo System Overview
Each theme can have unique branding through two types of logos:
- SVG Logos - Inline SVG for website (navigation, auth pages)
- Email/PDF Logos - PNG format for emails and PDF reports
Logo File Locations
SVG Logos (Website):
- Location:
resources/views/logos/ - Files:
timebank_cc.blade.php- Default themeuuro.blade.php- Uuro themevegetable.blade.php- Vegetable themeyellow.blade.php- Yellow themeyour_brand.blade.php- Your custom theme
- Format: Blade template with inline SVG
- Git Tracking: Yes (tracked as defaults)
Email/PDF Logos:
- Location:
storage/app/public/app-images/ - Files:
timebank_cc_mail_logo.pnguuro_mail_logo.pngvegetable_mail_logo.pngyellow_mail_logo.pngyour_brand_mail_logo.png
- Format: PNG image
- Git Tracking: No (gitignored, safe from overwrites)
Creating Custom Logos
1. SVG Logo (Website)
Create logo file:
cp resources/views/logos/timebank_cc.blade.php resources/views/logos/your_brand.blade.php
Edit the SVG:
{{-- your_brand.blade.php --}}
<svg width="160" height="112" viewBox="0 0 52.92 37.04" xmlns="http://www.w3.org/2000/svg"
class="fill-theme-logo">
<title>{{ config('app.name') . ' ' . __('logo') }}</title>
<!-- Your custom SVG paths here -->
<path d="..." />
</svg>
Important:
- Keep
class="fill-theme-logo"for theme-aware coloring - Include title tag for accessibility
- Adjust viewBox and dimensions as needed
2. Email/PDF Logo (PNG)
Upload your logo:
# Upload to storage/app/public/app-images/
cp /path/to/your/logo.png storage/app/public/app-images/your_brand_mail_logo.png
Recommended specifications:
- Format: PNG with transparency
- Size: 300-400px width (maintains quality in emails)
- Aspect ratio: Similar to your website logo
3. Configure Theme Logos
In config/themes.php:
'your_brand' => [
'name' => 'Your Brand',
'logos' => [
'svg_inline' => 'logos.your_brand', // Website logo
'email_logo' => 'app-images/your_brand_mail_logo.png', // Email/PDF logo
],
// ... rest of theme config
],
Logo Helper Functions
// Get SVG view name
theme_logo('svg_inline') // Returns: 'logos.your_brand'
// Get email logo path
theme_logo('email_logo') // Returns: 'app-images/your_brand_mail_logo.png'
Logo Usage in Code
The logo system is automatically integrated:
- Navigation menu - Uses
application-mark.blade.php(compact logo) - Authentication pages - Uses
authentication-card-logo.blade.php(full logo) - Email templates - Uses theme email logo
- PDF reports - Uses theme email logo
All automatically switch based on TIMEBANK_THEME setting.
Logo Deployment Protection
SVG logos are tracked in git as theme-specific defaults
Email logos are in storage/ (gitignored, safe from git pull)
No conflicts when deploying updates
Each installation maintains unique branding
Platform Configuration
Setting Up Platform Config
Location: config/ directory
Activation: Set TIMEBANK_CONFIG in .env
TIMEBANK_CONFIG=your_platform_name
Creating a New Platform Configuration
- Copy the default config:
cp config/timebank-default.php config/your-platform.php
- Customize settings in
config/your-platform.php:
return [
// Platform Identity
'platform_name' => 'Your Platform Name',
'currency_name' => 'TimeCredits',
'currency_symbol' => 'TC',
// Email Addresses
'mail' => [
'system_admin' => [
'email' => 'admin@yourplatform.com',
'name' => 'System Admin',
],
'user_admin' => [
'email' => 'users@yourplatform.com',
'name' => 'User Admin',
],
'content_admin' => [
'email' => 'content@yourplatform.com',
'name' => config('app.name'),
],
],
// Account Limits (in minutes)
'accounts' => [
'user' => [
'min_balance' => -300, // -5 hours
'max_balance' => 2400, // 40 hours
],
'organization' => [
'min_balance' => -3000, // -50 hours
'max_balance' => 24000, // 400 hours
],
],
// Transaction Types & Permissions
'transactions' => [
'types' => [
'worked_time' => true,
'gift' => true,
'donation' => true,
'currency_creation' => true,
'currency_removal' => true,
'migration' => false,
],
'permissions' => [
'user_can_create_currency' => false,
'organization_can_create_currency' => false,
'bank_can_create_currency' => true,
],
],
// Profile Visibility
'profiles' => [
'show_public_balances' => true,
'allow_private_profiles' => true,
],
// Search Configuration
'search' => [
'boost_factors' => [
'name' => 3.0,
'description' => 1.5,
'tags' => 2.0,
],
],
// Footer Configuration (see next section)
'footer' => [
// ...
],
];
Accessing Configuration Values
PHP Helper Function:
// Anywhere in the application
$platformName = timebank_config('platform_name');
$minBalance = timebank_config('accounts.user.min_balance');
$canCreateCurrency = timebank_config('transactions.permissions.bank_can_create_currency');
In Blade Views:
<h1>{{ timebank_config('platform_name') }}</h1>
<span>{{ timebank_config('currency_symbol') }}</span>
Footer Customization
Footer Configuration Structure
The footer is defined in your platform config file under the footer key:
'footer' => [
'tagline' => 'Your time is currency', // Translation key
'sections' => [
[
'title' => 'Who we are', // Translation key
'order' => 1, // Display order (lower = left)
'visible' => true, // Show/hide entire section
'links' => [
[
'route' => 'static-whyjoin', // Laravel route name
'title' => 'Why join', // Translation key
'order' => 1, // Display order (lower = top)
'visible' => true, // Show/hide link
],
[
'route' => 'static-association',
'title' => 'Timebank Organization',
'order' => 2,
'visible' => true,
],
// Custom URL example
[
'url' => 'https://example.com',
'title' => 'External Resource',
'order' => 3,
'visible' => true,
],
// Auth-required example
[
'route' => 'static-messenger',
'title' => 'Chat messenger',
'order' => 4,
'visible' => true,
'auth_required' => true, // Only show to logged-in users
],
],
],
[
'title' => 'Help',
'order' => 2,
'visible' => true,
'links' => [
// ... more links
],
],
],
],
Footer Link Types
1. Internal Route Links (most common):
[
'route' => 'static-whyjoin', // Must match route name in routes/web.php
'title' => 'Why join', // Translation key from lang files
'order' => 1,
'visible' => true,
]
2. External URL Links:
[
'url' => 'https://external-site.com/page',
'title' => 'External Resource',
'order' => 2,
'visible' => true,
]
3. Authenticated Links:
[
'route' => 'dashboard',
'title' => 'Dashboard',
'order' => 3,
'visible' => true,
'auth_required' => true, // Only visible when logged in
]
Common Footer Customizations
Reorder sections:
['title' => 'Help', 'order' => 1, ...],
['title' => 'Who we are', 'order' => 2, ...],
['title' => 'Policies', 'order' => 3, ...],
Hide specific links:
['route' => 'static-research', 'title' => 'Research', 'visible' => false],
Add email contact:
['url' => 'mailto:hello@yourplatform.com', 'title' => 'Email Us', 'order' => 5, 'visible' => true],
Add new section:
[
'title' => 'Community',
'order' => 4,
'visible' => true,
'links' => [
['url' => 'https://forum.example.com', 'title' => 'Forum', 'order' => 1, 'visible' => true],
['url' => 'https://blog.example.com', 'title' => 'Blog', 'order' => 2, 'visible' => true],
],
],
Custom Content Pages
Adding New Static Pages
To add new pages that appear in the footer or navigation, seed the database with categories and translations.
Step 1: Add Category Type
File: database/seeders/ExtendCategoriesSeeder.php
$categories = [
// Existing categories...
// Add your new category
['type' => 'SiteContents\\Static\\YourNewPage'],
];
Naming Convention:
- Static pages:
SiteContents\\Static\\PageName - Manage pages:
SiteContents\\Manage\\PageName - Error pages:
SiteContents\\Errors\\ErrorCode
Step 2: Add Translations
File: database/seeders/ExtendCategoryTranslationsSeeder.php
$translations = [
// Existing translations...
'SiteContents\\Static\\YourNewPage' => [
'en' => [
'name' => 'Your New Page',
'slug' => 'your-new-page',
],
'nl' => [
'name' => 'Jouw Nieuwe Pagina',
'slug' => 'jouw-nieuwe-pagina',
],
'de' => [
'name' => 'Deine Neue Seite',
'slug' => 'deine-neue-seite',
],
'es' => [
'name' => 'Tu Nueva Página',
'slug' => 'tu-nueva-pagina',
],
'fr' => [
'name' => 'Votre Nouvelle Page',
'slug' => 'votre-nouvelle-page',
],
],
];
Step 3: Run Seeders
php artisan db:seed --class=ExtendCategoriesSeeder
php artisan db:seed --class=ExtendCategoryTranslationsSeeder
Step 4: Add Route
File: routes/web.php
Route::get('/your-new-page', [StaticController::class, 'yourNewPage'])
->name('static-yournewpage');
Step 5: Add to Footer
File: config/your-platform.php
'footer' => [
'sections' => [
[
'title' => 'Who we are',
'links' => [
[
'route' => 'static-yournewpage',
'title' => 'Your New Page',
'order' => 10,
'visible' => true,
],
],
],
],
],
Database Updates
When to Use Database Updates
Use the DatabaseUpdate command when:
- Renaming seeded categories across all installations
- Updating category slugs or translations globally
- Migrating data structures affecting seeded content
- Making breaking changes to existing static pages
DO NOT use for:
- Adding new categories (use seeders)
- Platform-specific configs (use config files)
- Theme changes (use themes.php)
Adding a Database Update
File: app/Console/Commands/DatabaseUpdate.php
private function updateYourFeature()
{
$this->info('Updating your feature...');
try {
DB::beginTransaction();
// Update category type
$updated = DB::table('categories')
->where('type', 'SiteContents\\Old\\Name')
->update(['type' => 'SiteContents\\New\\Name']);
if ($updated > 0) {
$this->info(" ✓ Updated {$updated} category record(s)");
}
// Update translations
$category = DB::table('categories')
->where('type', 'SiteContents\\New\\Name')
->first();
if ($category) {
DB::table('category_translations')
->where('category_id', $category->id)
->update([
'name' => 'New Name',
'slug' => 'new-slug',
]);
}
DB::commit();
$this->info(' ✓ Update completed successfully');
} catch (\Exception $e) {
DB::rollBack();
$this->error(' ✗ Failed to update: ' . $e->getMessage());
}
}
Call in handle() method:
public function handle()
{
$this->info('Starting database updates...');
$this->updateYourFeature();
$this->info('Database updates completed!');
return 0;
}
Run updates:
php artisan database:update
Complete Setup Workflow
Initial Branded Instance Setup
# 1. Clone repository
git clone <repository-url>
cd timebank_cc_2
# 2. Run first deployment (creates configs from templates)
./deploy.sh
# 3. Configure environment variables
# Edit .env:
TIMEBANK_THEME=mybrand
TIMEBANK_CONFIG=mybrand
# 4. Create theme in config/themes.php
# Add 'mybrand' theme definition with colors, fonts, logos
# 5. Create platform config
cp config/timebank-default.php config/mybrand.php
# Edit config/mybrand.php with your settings
# 6. Create theme logos
# SVG logo:
cp resources/views/logos/timebank_cc.blade.php resources/views/logos/mybrand.blade.php
# Edit mybrand.blade.php with your logo
# Email logo:
cp your-logo.png storage/app/public/app-images/mybrand_mail_logo.png
# 7. Add custom content pages (if needed)
# Edit database/seeders/ExtendCategoriesSeeder.php
# Edit database/seeders/ExtendCategoryTranslationsSeeder.php
# 8. Seed custom content
php artisan db:seed --class=ExtendCategoriesSeeder
php artisan db:seed --class=ExtendCategoryTranslationsSeeder
# 9. Apply database updates
php artisan database:update
# 10. Clear caches and build assets
php artisan config:clear
npm run build
# 11. Test
php artisan serve
Deployment & Updates
Protected Files During Deployment
When you run ./deploy.sh, these files are protected from git overwrites:
Protected (gitignored):
config/themes.php- Your custom theme configurationconfig/timebank-default.php- Your platform configurationconfig/mybrand.php- Your brand-specific configurationstorage/app/public/app-images/*.png- Your email/PDF logos
Updated from git (templates):
config/themes.php.example- Latest theme defaultsconfig/timebank-default.php.example- Latest platform defaultsresources/views/logos/*.blade.php- SVG logo defaults
Deployment Process
./deploy.sh
What happens:
-
Config Check (NEW):
=========================================================== CHECKING CONFIGURATION FILES =========================================================== ✓ config/themes.php exists (custom installation config) ✓ config/timebank-default.php exists (custom installation config) -
Git Pull:
- Pulls latest code
- Updates
.exampletemplates - Your custom configs untouched
-
Dependencies:
composer installnpm install
-
Database:
- Migrations
- Database updates
- Seeders
-
Build Assets:
npm run build- Theme-specific compilation
After Deployment
Review new features:
# Check for new theme options
diff config/themes.php config/themes.php.example
# Check for new platform config options
diff config/timebank-default.php config/timebank-default.php.example
Merge beneficial updates manually into your custom configs.
Emergency Config Recovery
If configs were accidentally overwritten:
# Restore from git (if committed before migration)
git checkout HEAD~1 config/themes.php
# Or regenerate from backup
cp config/themes.php.backup config/themes.php
Troubleshooting
Theme not applying
- Verify
TIMEBANK_THEMEin.envmatches theme name inconfig/themes.php - Run
php artisan config:clear - Run
npm run build - Check browser console for CSS errors
Platform config not loading
- Verify
TIMEBANK_CONFIGin.envmatches filename (without.php) - Ensure config file exists in
config/directory - Run
php artisan config:clear
Logos not displaying
- SVG logos: Verify logo file exists in
resources/views/logos/ - Email logos: Verify PNG exists in
storage/app/public/app-images/ - Check theme config
logossection points to correct files - Run
php artisan config:clear
Footer links not appearing
- Check
visibleis set totruein footer config - Verify route name exists in
routes/web.php - Check translation keys exist in language files
- Clear cache:
php artisan config:clear
Custom page not found
- Verify category seeded: check
categoriestable - Verify translations seeded: check
category_translationstable - Verify route exists and matches
routein footer config - Check category type matches exactly (including backslashes)
Config files overwritten by git
Symptom: Customizations disappeared after git pull
Cause: Migration to .example system not completed
Solution:
# Run migration script
./scripts/migrate-to-example-configs.sh
# Push changes
git push origin main
Database updates not applying
- Check database connection
- Verify update method called in
handle() - Check database permissions
- Look for transaction rollback messages
Best Practices
Configuration Management
- Always use .example files as templates for new installations
- Document your customizations in comments within config files
- Review .example files after each deployment for new features
- Backup configs before major changes
- Never commit actual config files (only .example versions)
Theme Development
- Test across all themes after making UI changes
- Use theme-aware classes exclusively (
bg-theme-brandnotbg-blue-500) - Define complete color palettes (all 9 shades for primary)
- Test logo visibility on light and dark backgrounds
- Verify email logos render correctly in email clients
Platform Configuration
- Keep configs focused on behavior, not styling
- Version control custom configs locally (gitignored from repo)
- Document custom pages in config file comments
- Follow naming conventions for category types consistently
- Provide all 5 language translations for new content
Deployment
- Run ./deploy.sh regularly to stay updated
- Review .example diffs after deployment
- Test in staging before production deployment
- Clear caches after configuration changes
- Monitor deployment logs for config file status
Content Management
- Use DatabaseUpdate for breaking changes to seeded data
- Test footer configuration in all languages
- Clear caches after seeding new categories
- Verify routes before adding to footer config
- Keep slugs URL-friendly and consistent
Quick Reference
Environment Variables
TIMEBANK_THEME=your_brand_name
TIMEBANK_CONFIG=your_platform_name
Helper Functions
// Theme
theme_color('brand')
theme_color('primary.500')
theme_font('font_family_body')
theme_logo('svg_inline')
theme_logo('email_logo')
// Config
timebank_config('platform_name')
timebank_config('accounts.user.min_balance')
timebank_config('footer.sections')
Artisan Commands
# Configuration
php artisan config:clear
# Database
php artisan db:seed --class=ExtendCategoriesSeeder
php artisan db:seed --class=ExtendCategoryTranslationsSeeder
php artisan database:update
# Assets
npm run build
# Deployment
./deploy.sh
./scripts/migrate-to-example-configs.sh
File Locations
Themes: config/themes.php (protected)
config/themes.php.example (tracked)
Configs: config/{platform}.php (protected)
config/{platform}.php.example (tracked)
SVG Logos: resources/views/logos/{theme}.blade.php
Email Logos: storage/app/public/app-images/{theme}_mail_logo.png (gitignored)
Seeders: database/seeders/ExtendCategoriesSeeder.php
database/seeders/ExtendCategoryTranslationsSeeder.php
DB Updates: app/Console/Commands/DatabaseUpdate.php
Translations: lang/{locale}/messages.php
Routes: routes/web.php
Git Tracking
# Tracked in git (defaults/templates)
git ls-files config/*.example
git ls-files resources/views/logos/
# Gitignored (custom/protected)
git check-ignore config/themes.php
git check-ignore storage/app/public/app-images/*.png
Additional Resources
- Theme System Details:
references/THEME_IMPLEMENTATION.md - Logo Customization:
resources/views/logos/README.md - Migration Script:
scripts/migrate-to-example-configs.sh - Main Documentation:
CLAUDE.md
This guide covers all aspects of creating and maintaining a branded Timebank instance with full protection from deployment overwrites.