# 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 1. [Overview](#overview) 2. [Configuration Protection System](#configuration-protection-system) 3. [Theme Customization](#theme-customization) 4. [Logo Customization](#logo-customization) 5. [Platform Configuration](#platform-configuration) 6. [Footer Customization](#footer-customization) 7. [Custom Content Pages](#custom-content-pages) 8. [Database Updates](#database-updates) 9. [Complete Setup Workflow](#complete-setup-workflow) 10. [Deployment & Updates](#deployment--updates) 11. [Troubleshooting](#troubleshooting) 12. [Best Practices](#best-practices) --- ## Overview The platform supports complete branding through four main customization layers: 1. **Theme System** - Visual styling (colors, fonts, spacing) 2. **Logo System** - Theme-specific branding assets 3. **Platform Configuration** - Behavior, limits, translations, footer structure 4. **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:** - **`.example` files** are tracked in git (templates with defaults) - **Actual config files** are gitignored (safe from overwrites) - **`deploy.sh`** automatically 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: ```bash # From repository root ./scripts/migrate-to-example-configs.sh ``` This will: 1. Remove config files from git tracking (keeps your local files intact) 2. Add .example template files to git 3. Update .gitignore 4. Create a commit with all changes 5. Ready to push to repository **After migration:** ```bash git push origin main ``` ### Configuration Workflow #### New Installation ```bash git clone cd timebank_cc_2 ./deploy.sh ``` What happens: 1. No config files exist yet 2. `deploy.sh` creates them from `.example` templates 3. Customize configs with your branding 4. Customizations are now protected #### Updating Existing Installation ```bash ./deploy.sh ``` What happens: 1. Config check runs BEFORE git pull 2. Your custom configs exist → Preserved 3. Git pulls latest `.example` templates (updated defaults) 4. Your custom configs remain unchanged 5. Review `.example` files for new features to merge manually ### Merging Updates from Templates **Option 1: Manual Review (Recommended)** ```bash # 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! ```bash # 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` ```bash TIMEBANK_THEME=your_brand_name ``` ### Creating a New Theme Add your theme definition to `config/themes.php`: ```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):** ```blade

Title

Body text

``` **PHP Helper Functions:** ```php // 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`: ```bash TIMEBANK_THEME=timebank_cc TIMEBANK_THEME=uuro TIMEBANK_THEME=vegetable TIMEBANK_THEME=yellow ``` After changing theme: ```bash 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: 1. **SVG Logos** - Inline SVG for website (navigation, auth pages) 2. **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 theme - `uuro.blade.php` - Uuro theme - `vegetable.blade.php` - Vegetable theme - `yellow.blade.php` - Yellow theme - `your_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.png` - `uuro_mail_logo.png` - `vegetable_mail_logo.png` - `yellow_mail_logo.png` - `your_brand_mail_logo.png` - **Format:** PNG image - **Git Tracking:** No (gitignored, safe from overwrites) ### Creating Custom Logos #### 1. SVG Logo (Website) **Create logo file:** ```bash cp resources/views/logos/timebank_cc.blade.php resources/views/logos/your_brand.blade.php ``` **Edit the SVG:** ```blade {{-- your_brand.blade.php --}} ``` **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:** ```bash # 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`:** ```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 ```php // 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` ```bash TIMEBANK_CONFIG=your_platform_name ``` ### Creating a New Platform Configuration 1. **Copy the default config:** ```bash cp config/timebank-default.php config/your-platform.php ``` 2. **Customize settings in `config/your-platform.php`:** ```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:** ```php // 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:** ```blade

{{ timebank_config('platform_name') }}

{{ timebank_config('currency_symbol') }} ``` --- ## Footer Customization ### Footer Configuration Structure The footer is defined in your platform config file under the `footer` key: ```php '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):** ```php [ '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:** ```php [ 'url' => 'https://external-site.com/page', 'title' => 'External Resource', 'order' => 2, 'visible' => true, ] ``` **3. Authenticated Links:** ```php [ 'route' => 'dashboard', 'title' => 'Dashboard', 'order' => 3, 'visible' => true, 'auth_required' => true, // Only visible when logged in ] ``` ### Common Footer Customizations **Reorder sections:** ```php ['title' => 'Help', 'order' => 1, ...], ['title' => 'Who we are', 'order' => 2, ...], ['title' => 'Policies', 'order' => 3, ...], ``` **Hide specific links:** ```php ['route' => 'static-research', 'title' => 'Research', 'visible' => false], ``` **Add email contact:** ```php ['url' => 'mailto:hello@yourplatform.com', 'title' => 'Email Us', 'order' => 5, 'visible' => true], ``` **Add new section:** ```php [ '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` ```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` ```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 ```bash php artisan db:seed --class=ExtendCategoriesSeeder php artisan db:seed --class=ExtendCategoryTranslationsSeeder ``` #### Step 4: Add Route **File:** `routes/web.php` ```php Route::get('/your-new-page', [StaticController::class, 'yourNewPage']) ->name('static-yournewpage'); ``` #### Step 5: Add to Footer **File:** `config/your-platform.php` ```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` ```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:** ```php public function handle() { $this->info('Starting database updates...'); $this->updateYourFeature(); $this->info('Database updates completed!'); return 0; } ``` **Run updates:** ```bash php artisan database:update ``` --- ## Complete Setup Workflow ### Initial Branded Instance Setup ```bash # 1. Clone repository git clone 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 configuration - `config/timebank-default.php` - Your platform configuration - `config/mybrand.php` - Your brand-specific configuration - `storage/app/public/app-images/*.png` - Your email/PDF logos **Updated from git (templates):** - `config/themes.php.example` - Latest theme defaults - `config/timebank-default.php.example` - Latest platform defaults - `resources/views/logos/*.blade.php` - SVG logo defaults ### Deployment Process ```bash ./deploy.sh ``` **What happens:** 1. **Config Check (NEW):** ``` =========================================================== CHECKING CONFIGURATION FILES =========================================================== ✓ config/themes.php exists (custom installation config) ✓ config/timebank-default.php exists (custom installation config) ``` 2. **Git Pull:** - Pulls latest code - Updates `.example` templates - Your custom configs untouched 3. **Dependencies:** - `composer install` - `npm install` 4. **Database:** - Migrations - Database updates - Seeders 5. **Build Assets:** - `npm run build` - Theme-specific compilation ### After Deployment **Review new features:** ```bash # 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: ```bash # 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_THEME` in `.env` matches theme name in `config/themes.php` - Run `php artisan config:clear` - Run `npm run build` - Check browser console for CSS errors ### Platform config not loading - Verify `TIMEBANK_CONFIG` in `.env` matches 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 `logos` section points to correct files - Run `php artisan config:clear` ### Footer links not appearing - Check `visible` is set to `true` in 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 `categories` table - Verify translations seeded: check `category_translations` table - Verify route exists and matches `route` in 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:** ```bash # 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 1. **Always use .example files** as templates for new installations 2. **Document your customizations** in comments within config files 3. **Review .example files** after each deployment for new features 4. **Backup configs** before major changes 5. **Never commit actual config files** (only .example versions) ### Theme Development 1. **Test across all themes** after making UI changes 2. **Use theme-aware classes exclusively** (`bg-theme-brand` not `bg-blue-500`) 3. **Define complete color palettes** (all 9 shades for primary) 4. **Test logo visibility** on light and dark backgrounds 5. **Verify email logos** render correctly in email clients ### Platform Configuration 1. **Keep configs focused** on behavior, not styling 2. **Version control custom configs** locally (gitignored from repo) 3. **Document custom pages** in config file comments 4. **Follow naming conventions** for category types consistently 5. **Provide all 5 language translations** for new content ### Deployment 1. **Run ./deploy.sh** regularly to stay updated 2. **Review .example diffs** after deployment 3. **Test in staging** before production deployment 4. **Clear caches** after configuration changes 5. **Monitor deployment logs** for config file status ### Content Management 1. **Use DatabaseUpdate** for breaking changes to seeded data 2. **Test footer configuration** in all languages 3. **Clear caches** after seeding new categories 4. **Verify routes** before adding to footer config 5. **Keep slugs** URL-friendly and consistent --- ## Quick Reference ### Environment Variables ```bash TIMEBANK_THEME=your_brand_name TIMEBANK_CONFIG=your_platform_name ``` ### Helper Functions ```php // 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 ```bash # 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 ```bash # 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.