#FE: Control Panel & White label (from backend Phase 12)
Frontend spec for backend Phase 12 — White label add-on — requirements complete 2026-10-06, not built. V8 requirement The phase has two halves, and only the second one is the add-on:
- A. Control Panel (12.1–12.6) — every user gets this, no add-on needed. The owner creates a login for a customer on one server, with app and database limits and a tick-list of permissions. The customer logs in somewhere else entirely and sees only that server.
- B. White label (12.7–12.11) — the paid add-on. It puts that same Control Panel under the owner's brand and their own domain. It is lifetime (12.7, 12.11, changed twice on 2026-10-06): a plan grants it once after payment, it never goes away, and there is no switch to turn it off — the same as V7.
Central (owner) — create a control panel user on a server, set limits + permissions, one-click login
Central (owner, add-on) — branding, own domain + CNAME check, panel settings (Git, storage, DNS, default pages)
Control Panel (customer) — own login, one server only, apps + databases within limits, permitted features only
Domains — default manage domain (a Central setting) · the owner's own domain when White label is on
i18n namespaces: controlPanel.*, controlPanel.user.*, controlPanel.permissions.*, whitelabel.*, whitelabel.branding.*, whitelabel.domain.*, whitelabel.settings.*.
#Which domain the customer logs in at
The rule is V7's, and the backend says do not change it — so the frontend must not add a fourth case or a "preferred domain" choice.
| Case | Customers log in at |
|---|---|
| White label bought and own domain set up | The owner's own domain |
| White label bought, no domain set up | The default manage domain |
| White label not bought, Control Panel given to customers | The default manage domain |
Two facts the frontend must respect:
- The default manage domain (today
manage.serveravatar.com) is a Central setting, not a hardcoded string (stated in the phase's domain rule, which carries no item number). Never print it in a message, a template or a copy-to-clipboard box — read it from the API. The same goes for any help text that tells a customer where to log in. - One app serves everyone. Central serves the Control Panel on the default domain and on every owner's custom domain, and calls each server's OSS API exactly as Phase 10 does. There is no separate copy per owner, so branding must be resolved per request from the host, never baked into a build.
#A. Control Panel — every user, no add-on
| # | Feature | Screen / control | Rules from the backend doc | Frontend notes |
|---|---|---|---|---|
| 12.1 | Control panel user | Control panel screen under a server — placement undecided, see D-43 | One control panel user per server (as V7): username unique, minimum 8 characters · password minimum 8 · email. Edit or delete at any time. Passwords are stored hashed — V7 stored them in plain text | Because there is exactly one, this is not a list screen: it is an empty state with Create, and after that a single card with Edit and Delete. The hashing changes a V7 screen: V7 could show the customer's password back to the owner, and V8 cannot — so the form offers Set a new password (with a generator), the password is shown once at creation, and nowhere does the screen imply it can be looked up later. Validate the 8-character minimums client-side with the same message the API returns, and treat username taken as a field error, not a toast |
| 12.2 | Limits | Two number fields on the same screen | How many apps and how many databases the customer may create: 0–2000 | Two plain number inputs with the real range in the hint, not a slider. 0 is a legal value and means "none" — so the field must not treat 0 as empty, and the customer's own screens must handle a 0 limit as "you cannot create any" rather than an error. Show what the customer is using now next to each limit, so lowering a limit is an informed act |
| 12.3 | Permissions | Tick-list on the same screen | The owner ticks what the customer may do, from the Control Panel permission list — one entry per app feature of Phase 10 | This is the same shape as the role permission list (Phase 4) and the app features already specced on FE: Application screens, so reuse that grouping rather than inventing a flat list of 20 checkboxes. The list itself is not published yet Missing — the backend says "from the Control Panel permission list", so the screen is specced as groups with select-all, and the entries come from the API |
| 12.4 | One-click login | Open panel action | The owner opens the customer's Control Panel directly with a secure link | A button that calls the API and follows the link it returns — never a URL the frontend builds. Open it in a new tab, and say plainly that it signs the owner in as the customer |
| 12.4a | Find a customer by server IP | Search on the Control panel screen, or the server list | Added 2026-10-06: the owner can look up a server's Control Panel user by the server IP (as V7) | A small thing that tells you how owners actually work: they know the IP, not which Central server record it is. So the lookup belongs where they already are — the server search (9.1 already searches by IP) should find the control panel user too, rather than making this a separate screen. One result at most, since there is only one user per server (12.1) |
| 12.5 | Customer login | Sign in on the Control Panel surface | At the domain from the table above. On the default domain, any control panel user can sign in; on a custom domain, only that owner's customers can — everyone else gets "Invalid username or password". Session lasts 1 day (as V7). Ban and blocked rules are Phase 2's | The error message is deliberately identical for "wrong password" and "right password, wrong domain" — the frontend must not improve it, hint at it, or redirect the customer to the right domain, because that would leak which owner a username belongs to. A 1-day session with no "remember me" is short enough that the screen should say so after sign-in, not surprise the customer later |
| 12.6 | Customer panel | Control Panel app | Shows only that server. Create and manage apps and databases within the limits, using only the permitted features — the same screens as Phase 10. Plus timezone, change password, logout | "Same screens as Phase 10" is the sentence that keeps this cheap: the app screens on FE: Application screens must be built permission-driven and server-agnostic from the start, so they can render inside the Control Panel with a smaller permission set and no server switcher. What must not appear: organizations, members, plans, billing, other servers, the add-server flow, or anything that implies a Central account |
| 12.6a | Customer's own Git & storage | Integrations inside the Control Panel | Added 2026-10-06: inside the Control Panel the customer connects their own Git (GitHub / GitLab / Bitbucket) and cloud storage accounts — using the owner's app keys (12.10), as V7. Added 2026-10-06: Dropbox is skipped for now, the same as Phase 5 | The Dropbox note keeps the product consistent, and the frontend already has the pattern for it — FE: Integrations says the same about Phase 5 storage (Q11), so the Control Panel's storage picker simply leaves Dropbox out and V7 Dropbox users get the same plain message and an alternative. This also explains why 12.10 asks the owner for Git and storage client IDs and secrets: the OAuth app belongs to the owner, the account belongs to the customer. So the Control Panel needs its own small integrations screen, and the customer must never see the owner's keys. If the owner has not filled those keys in, the screen says the owner has not set this up — not a broken OAuth error |
| 12.6b | Allowed app types | Create-app screen | Added 2026-10-06: the customer sees only the app types the owner allows, taken from the permissions | So 12.3's permission list is not only about features — it also picks app types. The create-app screen is therefore built from the permitted list, and an empty list is an explained state, not an empty dropdown |
| 12.6c | Activity log | Owner's activity log | Added 2026-10-06: control panel user created / updated / deleted, and permissions or limits changed, are saved in the owner's activity log (as V7) | New event types for the existing Audit log screen — nothing new to build there, but the log must name the control panel user, and must never record the password |
#What the customer's panel must not inherit
| Thing | Why it must be absent |
|---|---|
| Server switcher, breadcrumb back to a server list | There is one server, and the customer must not learn that others exist |
| Plan limits and upgrade prompts | The customer has no plan — limits come from 12.2, and the message must name the owner's limit, not a plan |
| Billing, credit, organization, member screens | Not theirs, and not in Phase 12 |
| "Powered by" ServerAvatar branding when White label is on | The whole point of 12.8 |
#B. White label — the add-on
| # | Feature | Screen / control | Rules from the backend doc | Frontend notes |
|---|---|---|---|---|
| 12.7 | Turn it on — lifetime | Add-ons card | Changed 2026-10-06, hours after the phase was first published: White label is a lifetime add-on. It comes included in a plan (7.26) — when the user takes and pays that plan, White label is added to their account as purchased (lifetime) and shows as purchased. It can also be bought on its own, also lifetime | Account-level, not per server — so the card lives with the other add-ons and the settings live once in the account area, never under a server. The card state is not "Included" and never "expires": a plan grants it once, after payment, and from then on it is the user's. So the card reads Purchased — the same state whether it was bought directly or arrived with a plan — and the add-ons page must not show a renewal date, an expiry, or an "Included with your plan" label that would vanish on a downgrade. Worth saying in words on the card, because "lifetime" is unusual enough that users will not assume it |
| 12.8 | Branding | Branding tab | App name + folder name — set once, and "serveravatar" is not allowed · title · tag line · brand colour (a colour palette is made from it) · logo · icon · favicon · custom header / footer · Google Analytics ID | "Set once" needs a screen, not a validator: the app name and folder name must be clearly marked permanent before saving, in the form and again in a CONFIRM, because there is no second chance. The "serveravatar" ban belongs in client-side validation with the real reason. The brand colour is the frontend's biggest piece of work here — one colour becomes a whole palette, which our token system does not do today; see the conflict below. Custom header / footer is owner-supplied markup, so it must be sanitised and sandboxed and never rendered inside the Central app itself |
| 12.9 | Own domain | Domain tab | The owner points a CNAME to the default manage domain, then clicks Check CNAME. Central then serves the panel on that domain with automatic SSL. ServerAvatar's own domains cannot be used. An installation-steps guide is shown | A three-state screen — not connected (the guide, with the CNAME target read from the API and a copy button) → checking → connected (with the live domain and the certificate state). Check CNAME is a user action with a real result, so report what was actually found, including "points somewhere else". DNS and certificates are both slow, so the connected state has to tolerate "DNS is right, certificate not issued yet" instead of showing success or failure. Reuse the domain-verification pattern from FE: Application screens 10.4 so there is one DNS-check experience in the product |
| 12.10 | Panel settings | Settings tab, four groups | SMTP was removed from this item on 2026-10-07 — see the note below. What is left: Git apps — GitHub / GitLab / Bitbucket client ID + secret · Cloud storage apps — client ID + secret · DNS — a Route53 or DNSimple account plus the domains used for temporary app domains, phpMyAdmin and the file manager · Default server pages — the web server page, the new-app page and the disabled-app page. Clarified 2026-10-06: all of this is saved in Central at account level, not through the OSS API. Secrets are stored encrypted | The account-level clarification settles which API these screens talk to: unlike almost everything else about a server, these settings are Central's own data, so the screens call Central directly and do not depend on any panel being reachable — worth knowing, because a server being offline must not block them. Four groups, each saveable on its own, because an owner will fill them in over days. Every secret field is write-only: masked hint, never the value back, and a visible "replace" action. The SMTP group and its test email are gone (2026-10-07), so the Settings tab is smaller than this page first described and there is no mail test to design here. The DNS block answers a question our spec had left open about where temporary app domains come from, so link it from the app-domain screens. Default server pages are owner-supplied markup again — same sanitising rule as 12.8 |
| 12.10a | DNS details | Settings → DNS | Added 2026-10-06: turn the DNS provider on / off and view its DNS records (as V7) | A read-only record list next to the on/off switch. Read-only is the right call — this is the owner's real DNS zone, and an editing screen was never specified |
| 12.10b | Preview a default page | Settings → Default pages | Added 2026-10-06: preview the custom default pages before saving (as V7) | The backend asking for a preview settles how this screen works: owner-supplied markup is rendered in a sandboxed frame, never inside the Central page, and the preview is the step before Save rather than a separate screen |
| 12.10c | Callback URLs | Settings → Git apps / Cloud storage apps | Added 2026-10-06: the owner sees the exact redirect / callback URLs — built from their own domain — to paste in when they create their GitHub, GitLab, Bitbucket and cloud-storage apps (as V7) | This is the step that makes 12.6a work at all, and it is easy to get wrong: each URL is derived from the owner's custom domain (12.9), so it changes once the domain is connected and must be read from the API, never assembled in the frontend. Show it read-only with a copy button next to the matching client ID and secret fields, and say which provider each one belongs to. Before a custom domain exists, the URL is the one on the default manage domain — so the screen must make clear it will change, or owners will register the wrong callback |
| 12.11 | It stays for life | Automatic — there is nothing to operate | Rewritten twice on 2026-10-06, and the second version goes further than the first. Once White label is on the account it stays for life, also after a plan change — the same as V7. And there is no on / off switch at all, because V7 has none | Both of this page's earlier versions were wrong, so both corrections are stated rather than hidden. At 10:27 the backend said a plan change or expiry switched the add-on off; at 11:09 it said only an admin could; at 11:37 it says nobody can — the switch does not exist. What that means for the screens: there is no "switched off" state to design, no banner about branding being paused, no admin screen to wait for, and no warning anywhere in the plan flow about losing White label (7.8). Once an account has it, every White label screen is simply always available. The frontend's only remaining unknown is what happens to the custom domain's certificate over time, which no version of the item mentions |
| 12.12 | Free managed server | Private link, not a normal screen | Added 2026-10-06, as V7: a private link creates a Control Panel user on a server for partner emails — the list is kept in Central settings, not hardcoded — and returns the server's install commands | This is very probably the other half of D-41. Phase 8's free ServerAvatar Lite server (8.6) gives someone a "limited panel login" with no Central account and no OSS panel, and Pair 1's Phase 9 still lists it as "hosting users (limited panel login) — part of 8.6, still open". Phase 12 now describes a private link that creates a Control Panel user on a server — which is exactly a login with no Central account. The two line up, but neither doc says they are the same thing, so this page does not merge them Assumption. What is clear either way: it is a private, partner-only link, the partner list is a setting, and the screen returns install commands — so if the frontend owns anything here it is a small gated page, not part of the add-server wizard |
#States & errors
| State | Where | What the screen shows |
|---|---|---|
| No control panel user yet | Owner, per server | Empty state explaining what a control panel user is for, with Create |
| Username taken | Owner, create / edit | Field error on username, form keeps every other value |
| Password set | Owner, create | Shown once, with copy — and a line saying it cannot be shown again (12.1) |
| Limit below current use | Owner, limits | Save is allowed but the screen says what the customer is already using, so it is not a surprise |
| Permission list not loaded | Owner, permissions | The list comes from the API Missing — on failure, show a retry, never an empty tick-list that looks like "nothing allowed" |
| Wrong domain for this customer | Customer, sign-in | "Invalid username or password" — deliberately the same as a wrong password (12.5) |
| Session expired after a day | Customer | Back to the Control Panel sign-in on the same host, with the branding intact |
| Over a limit | Customer, create app / database | Blocked with the owner's limit named, and no upgrade link — the customer cannot buy anything |
| Feature not permitted | Customer | The screen is absent, not disabled — a disabled tab tells the customer their provider is holding something back |
| CNAME not pointing yet | Owner, domain | What was found versus what is needed, with the guide still on screen (12.9) |
| Domain verified, certificate pending | Owner, domain | "Verified — securing the domain", not success and not an error |
| White label switched off | Not a state — it cannot happen (12.11, 11:37 version). There is no on / off switch, so no screen needs a paused or disabled variant | |
| Add-on never bought | Owner | The Control Panel screens still work in full — only branding and the custom domain are behind the add-on |
| Plan changed after getting White label | Owner | Nothing happens — it is lifetime and cannot be switched off (12.11). No warning on the plan change, no "you will lose" line, no expiry on the add-on card |
#Permissions
| Action | Who | Source |
|---|---|---|
| Create / edit / delete a control panel user, set limits and permissions | Not specified by the backend Missing | It is a server-level action, so the organization role and shared-server permissions of Phase 4 are the obvious home — but Phase 12 does not say so, and this spec does not invent a permission |
| Turn White label on, edit branding, domain and panel settings | Account level (12.7 — "the whole account") | So an organization member almost certainly must not — again not stated. Raised with D-42 |
| Anything inside the Control Panel | The customer, limited to the ticks in 12.3 | 12.3, 12.6 |
#What this phase answers
| Open item | Answer |
|---|---|
| Is White label lost on a downgrade? | No — answered 2026-10-06 (12.7, 12.11, 7.26). It is a lifetime add-on: a plan grants it once, after payment, and it stays on the account through any later plan change. In the latest wording there is no off switch at all, so nothing can remove it and the downgrade check (7.8) must leave it out |
| White label was "a later add-on phase" on Product overview and in Phase 11's deferred list | It is now a written phase (12.7–12.11) V8 requirement — branding, own domain and panel settings are specified |
| Withdrawn, not answered — 2026-10-07. It looked answered for a day: 12.10 briefly gave the owner their own SMTP with a test email. Both the setting and Phase 11's "comes later" line have now been deleted, so there is no own-mail feature in the spec at all and nothing is deferred either. See the open item below | |
| Where V7's Control Panel went | Kept, and for everyone (12.1–12.6) — it was never actually part of the add-on |
| Where temporary app domains, phpMyAdmin and the file manager get their domains in a white-labelled panel | 12.10's DNS block — a Route53 or DNSimple account plus the domains to use |
#Still open after this phase
| # | Question |
|---|---|
| D-42 | Who serves the Control Panel, and on whose domains? Central serves one app on the default manage domain and every owner's custom domain, resolving branding per host, with automatic SSL for domains added at any time. Whether that is this Next.js app with host-based routing, or a second app, is not a documentation decision |
| D-43 | Where does the Control panel screen go in the fixed server menu? The server menu order is fixed (U13.4) and has no Control Panel item. Same shape of question as D-37 and D-40 |
| D-44 | How is the palette made from one brand colour, and what happens when the owner's colour cannot meet contrast? See the conflict above |
| — | Whose address do a white-label owner's customers get emails from? On 2026-10-07 the owner's own SMTP was removed from 12.10, and Phase 11's "comes later" line was deleted with it. Nothing replaced either, so the doc no longer says Open question. It matters more than its size suggests: a branded panel on the owner's own domain that emails from serveravatar.com undoes part of the point of white-labelling. Nothing is invented here — there is simply no mail setting on these screens now |
| — | Is the custom domain's certificate kept when White label is switched off? Note 12.11 now says there is no off switch at all, so this may be moot — not stated either way |
| — | The Control Panel permission list itself is not published Missing — the screens are specced to render it from the API |