White-Label & Branding

AVA ships vendor-neutral. Out of the box, with no branding variables set,
it presents as a generic deployment: the company name is Your Company, the
dashboard rail shows an AVA monogram tile, the footer reads Powered by AVA, the bundled AVA logo renders on the client page, and there is no
support phone number and no client-portal link anywhere in the UI. Nothing
in the product points at any real company.

Every identity surface a client or engineer sees is driven by environment
variables, read at call time — set them in your runtime env file, restart
the container, and the new identity is live. No rebuild, no code fork. This
includes the client landing page, which is rendered per-request (not
prebuilt), so branding set on the host reaches it immediately.

The one deliberate exception to "all optional" is SUPPORT_FALLBACK_EMAIL:
it has no default at all and the container refuses to boot without it —
AVA will never silently route your clients' after-hours emails to a built-in
address.


1. The identity knobs, one by one

Full type/default table in
configuration.md; this section
explains what each knob actually touches.

COMPANY_NAME — default Your Company

Your full display name. Appears in the browser-tab metadata
(AVA — <COMPANY_NAME> IT Support), the page metadata description, the client
contact form, and anywhere the UI names the company. Also feeds the AI summary
prompt together with the descriptor.

COMPANY_DESCRIPTOR — default IT Support

The short descriptor that follows your name in prose — the metadata
description and the AI summary prompt read "<COMPANY_NAME> <COMPANY_DESCRIPTOR>", e.g. "Acme IT Managed Services".

COMPANY_MONOGRAM — default AVA

The 1–4 character tile at the top of the engineer dashboard's icon rail.
Values longer than 4 characters are silently truncated to 4.

COMPANY_TAGLINE — default Powered by AVA

The footer identity line, shown on both the client chat page and the engineer
dashboard panel footer (next to the version number).

WELCOME_MESSAGE — default: neutral greeting

The system message posted into every chat at session start. The default is a
neutral greeting ("Welcome to Tech Support! Your session has been created and
an engineer will be with you shortly. …") that includes two clauses worth
keeping if you rewrite it in your own voice: the notice that the conversation
may be recorded and a ticket created, and the request not to share passwords
or other sensitive information.

SUPPORT_PHONE — default: unset (hidden everywhere)

Your displayed support phone number. This knob has hide-when-empty
semantics: when unset or empty, every phone element in the product disappears
cleanly rather than showing a blank —

- the client landing-page phone banner is not rendered;
- the contact form's off-hours copy drops the "call us" wording (and swaps
the phone icon for a clock);
- the queue-timeout overlay omits the call option;
- the off-hours API message omits the "or call …" suffix.

When set, AVA also derives a clickable tel: link automatically: formatting
characters are stripped, a bare 10-digit number is assumed North American and
gets a +1 prefix, and a number you write with a leading + (e.g.
+44 20 …) is passed through exactly as dialable — so international tenants
control the dialed string by formatting SUPPORT_PHONE in E.164.

AT_CLIENT_PORTAL_URL — default: unset (plain ticket number)

The base URL of your AutoTask client portal's ticket-detail page. When set,
ticket references render as links into your portal; when unset or empty, the
UI shows a plain ticket number instead. Typically:

https://ww1.autotask.net/ClientPortal/ServiceTickets/ServiceTicketDetail.aspx

(or your portal's vanity domain equivalent).

LOGO_PATH — default /ava-logo.svg

The public path of the brand logo shown on the client landing page and the
dashboard's mobile top bar. The bundled AVA wordmark ships at
/ava-logo.svg; to use your own, add your SVG under public/ (this bakes it
into the image — a rebuild) and point LOGO_PATH at it (runtime — a
restart). An empty value falls back to the default.

COMPANY_PROFILE — default a managed service provider (MSP) supporting business clients

A one-sentence description of your clientele, injected into the AI triage
prompt. Not client-visible, but worth setting: "an MSP serving medical and
dental practices"
classifies a "the imaging workstation is down" chat better
than the generic default. See ai-providers.md.

Business-hours copy — BUSINESS_HOURS_*

Not branding vars strictly, but an identity surface: the schedule you set via
BUSINESS_HOURS_TZ / OPEN / CLOSE / DAYS is what the client-facing
availability copy quotes — the off-hours message renders your actual
hours ("Live chat is available Monday–Friday, 8 AM–5 PM Eastern…"), never a
hardcoded string. See
configuration.md.

DISPLAY_TZ — default: → BUSINESS_HOURS_TZAmerica/Los_Angeles

The timezone for every human-facing timestamp: message times, day dividers,
the transcript posted to AutoTask, and the wrap-up/billing draft's wall-clock
fields. If you've already set BUSINESS_HOURS_TZ, you get a consistent
display timezone for free; set DISPLAY_TZ only to diverge the two.

Email identity — required and fail-closed

VariableSemantics
SUPPORT_FALLBACK_EMAILRequired to boot — recipient of the after-hours "email a ticket" form. No vendor default exists.
SMTP2GO_FROMSender on all outbound mail. No default; when unset, email routes fail closed (skip the send, return an error) rather than mailing from a placeholder.
FEEDBACK_EMAILEngineer-feedback recipient. Optional; unset = the send is skipped and an error logged — never a vendor fallback.
REPORTS_EMAILWeekly survey-report recipient. Same fail-closed contract.

Hide-when-empty semantics, precisely

For the two nullable knobs (SUPPORT_PHONE, AT_CLIENT_PORTAL_URL):

StateResult
Variable unsetHidden (the vendor-neutral default is "none")
Variable present but empty (SUPPORT_PHONE=)Hidden
Variable setYour value, rendered

For every non-nullable knob (COMPANY_NAME, COMPANY_MONOGRAM, etc.), unset
and empty/whitespace both mean "use the neutral default" — you cannot blank
the company name.


2. Worked example — "Acme IT"

A complete branding block for a fictional MSP on the US East Coast, ready to
drop into your runtime env file:

# --- Identity ---
COMPANY_NAME="Acme IT"
COMPANY_DESCRIPTOR="Managed Services"
COMPANY_MONOGRAM=ACME
COMPANY_TAGLINE="Powered by AVA — Acme IT"
WELCOME_MESSAGE="Welcome to Acme IT support! Your session has been created and an engineer will be with you shortly. By using this chat, you agree that this conversation may be recorded and a support ticket will be created on your behalf. Please do not share sensitive information such as passwords."
SUPPORT_PHONE="(555) 123-4567"
AT_CLIENT_PORTAL_URL=https://ww1.autotask.net/ClientPortal/ServiceTickets/ServiceTicketDetail.aspx
LOGO_PATH=/acme-logo.svg

# --- AI context ---
COMPANY_PROFILE="an MSP serving small law firms and accounting practices"

# --- Hours & timezones ---
BUSINESS_HOURS_TZ=America/New_York
BUSINESS_HOURS_OPEN=8
BUSINESS_HOURS_CLOSE=17
BUSINESS_HOURS_DAYS=1,2,3,4,5
# DISPLAY_TZ inherits America/New_York from BUSINESS_HOURS_TZ

# --- Email identity ---
[email protected]
[email protected]
[email protected]
[email protected]

Plus the asset step: drop acme-logo.svg into public/, replace
src/app/favicon.ico with the Acme favicon, and rebuild the image once.
Everything in the env block above is a restart, not a rebuild.


3. Honest limitations — what is still a code change

White-labeling covers identity, copy, and configuration. The following are
not env-driven today; set expectations accordingly before promising a
change:

- Colors / theme tokens. The brand palette lives as CSS custom properties
in src/app/globals.css — a --color-ea-* token set (the token names are a
historical internal identifier and are stable; do not rename them):

--color-ea-green: #136734;
--color-ea-green-light: #1a8a4a;
--color-ea-purple: #782C8F;
--color-ea-purple-light: #9C27B0;
--color-ea-amber: #F59E0B;
--color-ea-amber-dark: #D97706;

Accent surfaces derive from these (e.g. the dashboard rail's active state is
var(--color-ea-green)), so editing the token values and rebuilding
re-skins the UI — but that is a source edit + rebuild, not a config change.
An env-driven per-tenant palette is a planned future item, not implemented.
- Logo files and the favicon. LOGO_PATH selects which file renders,
at runtime — but the file itself must exist under public/ in the built
image, and the browser favicon is the static src/app/favicon.ico. Adding
your own logo/favicon assets is a file drop + image rebuild (once; the env
var can then switch between bundled assets freely).
- The product name "AVA". The tenant-facing tagline is fully yours via
COMPANY_TAGLINE, but the product's own name still appears in a few fixed,
product-labeled places: the browser-tab title pattern
(AVA — <your company> IT Support), notification/tab-title updates, email
subject prefixes like [AVA], and occasional product references in
engineer-facing dialog copy. These are not independently env-configurable.
- Fonts / typography. The type scale and font family are design-system
code, not config.
- Layout, component structure, and copy beyond the knobs in §1. Changing
those is a fork/customization, not white-labeling.
- Per-tenant multi-branding in one deployment. AVA is single-tenant per
deployment: one running instance = one brand (identity comes from that
host's env). Serving multiple brands means multiple deployments.


4. Verifying your branding

After setting your variables and restarting, walk this checklist. Total time:
about five minutes.

Client-facing (open the chat page in a private/incognito window):

- [ ] Browser tab reads AVA — <your company> IT Support.
- [ ] Your logo renders (not the AVA wordmark) — LOGO_PATH correct and the
file present in the image.
- [ ] Footer shows your COMPANY_TAGLINE.
- [ ] Phone banner shows your SUPPORT_PHONE with a working tel: link that
dials the number you intended — or is entirely absent if you run
phone-less.
- [ ] Start a test chat: the first system message is your WELCOME_MESSAGE.
- [ ] Off-hours (or with a temporarily narrowed schedule): the unavailability
copy quotes your hours and timezone, and mentions calling only if a
phone is set.

Engineer-facing (sign in to the dashboard):

- [ ] Rail tile shows your COMPANY_MONOGRAM.
- [ ] Panel footer shows your COMPANY_TAGLINE.
- [ ] Message timestamps and day dividers render in your DISPLAY_TZ.
- [ ] Ticket references link into your portal (AT_CLIENT_PORTAL_URL) — or
show a plain ticket number if you left it unset.

Email & AI:

- [ ] Submit the after-hours email form: it arrives at your
SUPPORT_FALLBACK_EMAIL, sent from your SMTP2GO_FROM.
- [ ] Send a piece of engineer feedback: it arrives at FEEDBACK_EMAIL (or,
if you left it unset, the send is skipped with a logged error — by
design).
- [ ] Start a test chat describing a clientele-specific issue and confirm the
triage classification reflects your COMPANY_PROFILE.

Boot-log spot-checks (once, after the first branded start):

- [ ] No warning about an invalid DISPLAY_TZ / BUSINESS_HOURS_TZ.
- [ ] No AUTOTASK_DEFAULT_ROLE_ID fallback warning (you set your own role
ID — see
configuration.md).


See also

- configuration.md — every variable, with types and
defaults.
- ai-providers.md — AI provider/model selection and
COMPANY_PROFILE.
- quickstart.md — where branding fits in the bring-up
order.


Did this page help you?