# Customization Guide

> Audience: developers and resellers white-labelling or extending WaDesk — themes, branding, the asset build, languages, and the environment settings that change behaviour without touching code.

## What You Can Customize

Most white-label changes are no-code: logos, colours, app name, and message footers are admin settings. Deeper changes — restyling, new pages, new translations — touch the front-end build. This page covers both, in roughly increasing order of effort:

- Themes — the four built-in looks and how the theme switch works.
- Branding — logos, favicon, app name, and outbound footers.
- Front-end build — Vite + Tailwind v4, when and how to rebuild.
- Languages — the translation files and adding a new one.
- Environment settings — behaviour you change in the `.env` file.

## Themes

The dashboard ships four themes: `paper` (default), `bright`, `dark`, and `doodle`. The active theme is applied by setting a `data-theme` attribute on the page; the CSS then styles each theme off it:

    html[data-theme="dark"]   .ts-control { ... }
    html[data-theme="bright"] .ts-dropdown { ... }
    /* paper is the default — no attribute set */

The user's choice is remembered in their browser (a `wa-theme` cookie) and applied on the very first paint so the page never flashes the wrong theme on reload. The server reads the same cookie so server-rendered parts (notably the logo) match the active theme straight away — the cookie, not a saved profile setting, is the source of truth.

> Adding a theme: register the new theme key, add its `html[data-theme="..."]` rules in the CSS, and add it to the theme switcher. An unknown saved value safely falls back to `paper`.

## Branding & White-Label

Brand assets come from admin settings — no code edits needed:

Asset | Configured at
--- | ---
Per-theme logo (one per theme) | Admin → Settings → General
Favicon | Admin → Settings → General
App name | Admin settings (falls back to the app's configured name)
Billing identity (company, address, tax ID…) | Admin → Checkout Settings (printed on invoices)

Logos fall back gracefully: a missing per-theme logo uses the default `paper` logo, and if no logo is set at all the UI shows a text wordmark instead.

### Outbound Message Footers

The footer added to outbound messages is decided per-workspace:

- If the workspace's plan does not include "remove branding" → the platform's default footer (set by the admin) is used.
- If the plan does include "remove branding" → the workspace's own footer is used if set, otherwise no footer at all.

The footer is added to plain-text messages and to the footer line on button/interactive messages. Approved WhatsApp templates are excluded — their content cannot be changed after approval. The bridge is given the final footer along with the rest of a number's settings.

> No emojis — SVG only. The product's style is inline SVG icons (16×16, `currentColor` stroke), never emoji. Keep any custom UI, log lines, and message text emoji-free to match.

## Front-End Build (Vite + Tailwind v4)

The front-end is compiled with Vite 7 and Tailwind CSS v4. The build has two style entry points — one for the dashboard/admin and one for the public landing pages — plus the main app script, as declared in `vite.config.js`:

    // vite.config.js
    laravel({
      input: [
        'resources/css/app.css',       // dashboard / admin / user shell
        'resources/css/frontend.css',  // public landing pages
        'resources/js/app.js',
      ],
      refresh: true,
    })

Tailwind v4 is configured in CSS: the colour palette and fonts are defined in an `@theme {}` block inside the dashboard stylesheet.

Commands (from the project root):

    npm install        # install front-end deps (first time)
    npm run dev        # dev server with hot reload (development)
    npm run build      # compile production assets

> Rebuild after any front-end change. Editing the stylesheets or scripts, or adding new Tailwind classes, needs `npm run build` for production (or a running `npm run dev` in development). The whole local stack — web server, queue, logs, and the asset build — can be started together with `composer dev`.

## Adding Languages

Translations are flat JSON files in the `lang/` directory, keyed by the English source string. WaDesk ships `en.json` plus 20 translated locales:

    lang/
    ├── en.json   (source)
    ├── ar.json  bn.json  de.json  es.json  fr.json  he.json  hi.json
    ├── id.json  it.json  ja.json  ko.json  nl.json  pl.json  pt.json
    └── ru.json  th.json  tr.json  ur.json  vi.json  zh-CN.json

Each file maps the original string to its translation:

    // lang/fr.json
    {
      "Team Inbox": "Boîte de réception d'équipe",
      "Send message": "Envoyer le message"
    }

To add a new language:

1. Copy `lang/en.json` to `lang/<code>.json` (e.g. `lang/sv.json`) and translate the values.
2. The default and fallback language are set by `APP_LOCALE` / `APP_FALLBACK_LOCALE` in the `.env` file (both `en` by default); users switch language using the in-app language switcher.
3. A built-in tool can scan the app for any newly-added text and append it to the translation files, keeping them in sync as you add features.

Right-to-left languages (Arabic, Hebrew, Urdu) are already included, and the UI handles right-to-left layout automatically.

## .env Knobs

Behaviour you change without touching code. The most relevant for customization and deployment:

Variable | Effect
--- | ---
`APP_NAME` | Default app name (admin `app_name` setting overrides it in the UI).
`APP_URL` | Public base URL. Must be the real HTTPS domain — used to build media URLs, Twilio `StatusCallback`, and links Meta must be able to fetch.
`APP_LOCALE` / `APP_FALLBACK_LOCALE` | Default + fallback language (both `en` out of the box).
`DB_*` | MySQL connection (host, port, database, username, password).
`QUEUE_CONNECTION` | Queue driver — `database` by default; switch to `redis` for higher throughput.
`CACHE_STORE` / `SESSION_DRIVER` | Cache + session backends (both `database` by default).
`SERVER_URL` | The address of the Node bridge, used by the send path and scheduler.
`NODE_WEBHOOK_TOKEN` | Shared secret that authenticates the app and the bridge to each other. Must match the value in `node/.env`.
`MAIL_*` | Outbound email for invoices, notifications, and password resets.

Several of these also have an admin-panel equivalent that takes precedence — for example the default WhatsApp engine, the allowed engines, the Meta API version, and the bridge URL. Prefer the admin UI for those; the `.env` values act as fallbacks at startup.

> After editing `.env`: clear the config cache (`php artisan config:clear`, or `config:cache` in production). Changes are not picked up while a stale cached config exists.

## Conventions to Respect

- Inline SVG icons only — no emoji anywhere in the UI, scripts, or logs.
- Encrypted credentials — always read and write engine credentials through the provided helpers, never the raw stored value.
- Engine-aware UI — gate engine-specific features behind the active-engine check so operators never hit a dead end.
- Rebuild assets after any front-end change; clear the config cache after any `.env` change.

## Related Pages

- Architecture Overview — the layout these files live in.
- WhatsApp Engines — how engine selection and footers reach a send.
- Node Bridge & Realtime — the bridge that the `SERVER_URL` / `NODE_WEBHOOK_TOKEN` knobs configure.