The WHMCS theme structure has two parts: system themes in /templates/<name>/, which draw the client area, and order form templates in /templates/orderforms/<name>/, which draw the cart. Each folder has a theme.yaml file. To customize safely, you create a child theme or child order form template that names a parent and holds only the files you change.
Where do WHMCS themes and order form templates live?
System themes are folders directly inside /templates/, and order form templates are folders inside /templates/orderforms/. The Child Themes page names Twenty-One, Nexus and Six as the parent themes that ship with WHMCS. Standard Cart is the default order form template.
templates/
twenty-one/ shipped parent theme, never edit
nexus/ shipped parent theme
six/ shipped parent theme
mytheme/ your child theme
theme.yaml
css/custom.css
footer.tpl only the files you changed
orderforms/
standard_cart/ shipped parent order form
mycart/ your child order form
theme.yaml
products.tpl
Three settings decide what visitors see. System Theme is on the General tab at Configuration > System Settings > General Settings. The default order form template is on the Ordering tab of the same page. A product group can use its own template, set at Configuration > System Settings > Products/Services. One detail surprises people: the View Cart and Checkout steps always use the default order form template, because a cart can hold products from several groups.
All of this applies to self-hosted WHMCS. On WHMCS Cloud, the documentation points you to the Theme Editor addon module instead.
Which shipped theme should a child theme extend?
Extend Twenty-One or Nexus. The developer documentation still calls Twenty-One the default theme, and Nexus arrived with the Nexus Cart in WHMCS 9.0.
| Theme | Directory | What the documentation says |
|---|---|---|
| Twenty-One | twenty-one | The default theme. Uses Bootstrap 4. |
| Nexus | nexus | To enable the Nexus Cart, set Nexus as the system theme, then Nexus Cart as the default order form. Colors, rounding and font sizes are CSS variables such as --primary, --bg, --text and --border. |
| Six | six | Still shipped as a parent theme. Uses Bootstrap 3. I do not start new work on it. |
What goes in a WHMCS theme.yaml file?
A name and a parent are required, and four more keys are optional. The Theme Configuration File page lists them all.
name: "My Theme"
description: "Brand overrides for Twenty-One"
author: "Example Hosting"
config:
parent: twenty-one
nameis what the System Theme menu shows. For an order form template, it shows on the Ordering tab and in product group settings.config: parentis the parent's directory name, never its display name.dependenciesandprovideslist assets such as Bootstrap or jQuery versions. WHMCS compares them when you select a theme, and assumes compatibility whendependenciesis empty.
The file must be valid YAML with the indentation shown. Older tutorials put parent: at the top level or add stylesheets: and scripts: keys. The documented format has neither.
How do you build a WHMCS child theme that survives updates?
Create a new folder, give it a theme.yaml that names the parent, and add only what you change. The documented steps are:
- Create the folder in
/templates/. Use lowercase letters, numbers, hyphens and underscores, with no spaces. - Add
theme.yamlwithnameandconfig: parent. - Add
css/custom.css. The parent loads it after its own styles, so your rules win. A child theme that only changes CSS needs nothing else. - Copy any template you want to change from the parent into the same path in the child, then edit the copy. Start from the parent's file, never an empty one, especially for the header and footer.
- Preview with
?systpl=mytheme, then select the theme under System Theme and save.
A child can have a parent that is itself a child, but the documentation does not recommend it. For theme assets, the {assetPath file='app.js'} helper lets a child override a parent's file without changing paths.
What survives a WHMCS update, and what does not?
Your own folders survive, and anything inside a shipped folder does not. The table is how I explain it to clients.
| Customization | After an update |
|---|---|
Edits inside twenty-one, nexus, six or standard_cart | At risk. These are the files WHMCS ships and replaces. |
A child theme's theme.yaml and css/custom.css | Kept, and the parent's fixes still reach every file you did not copy. |
| Template files copied into a child | Kept, but frozen. Parent changes to those files no longer reach you. |
| A full copy with no parent | Kept, but every file is frozen and needs manual updates. |
{php}, {include_php} and {fetch} tags | Broken on 9.0. The WHMCS 9.0 release notes say WHMCS moved to Smarty 4.0 and removed these tags. Remove them before you upgrade. |
| Logo uploaded in the General tab | Kept. It is a setting, read by the themes through $assetLogoPath. |
The documentation says that if you use custom templates, you must check each version's template changes and apply them before you update. The release notes link to GitHub comparisons for Nexus, Twenty-One, Six and Standard Cart. After applying them, go to Utilities > System > System Cleanup and click Go under Empty Template Cache. My WHMCS upgrade guide has the full update checklist.
Which theme files do you override most often?
The header and footer, then the include files that render shared parts of every page. The developer documentation lists these includes for WHMCS 8.1 and later:
| File | What it controls |
|---|---|
header.tpl, footer.tpl | The wrapper around every page. The footer's JavaScript before </body> must stay. |
includes/head.tpl | CSS and JavaScript loaded in the head. |
includes/navbar.tpl, includes/sidebar.tpl | How menu and sidebar items render. The items themselves are defined inside WHMCS, so you change them with hooks. |
includes/alert.tpl, includes/panel.tpl, includes/tablelist.tpl | Alerts, card panels and the filterable list tables. |
includes/flashmessage.tpl, includes/modal.tpl | One-time messages and modals. |
Invoices are their own subject. viewinvoice.tpl and the PDF template are covered in my WHMCS invoice template guide, so I do not repeat them here.
Which files make up a WHMCS order form template?
About twenty .tpl files, one or more per cart step. A child order form needs a theme.yaml with config: parent: standard_cart and only the files you change. Premium Comparison is the documented example: it holds only products.tpl and takes every other step from Standard Cart. The Custom Order Form Templates page lists every file. These are the ones I edit most:
| File | Cart step |
|---|---|
products.tpl | Lists product groups and products. |
configureproduct.tpl | Billing cycle, configurable options and custom fields. |
viewcart.tpl | Cart contents, tax estimate and promotion code. |
checkout.tpl | Contact and payment details. |
complete.tpl | The order completed page. Code inside {if $ispaid} runs only once the order is paid. |
My configurable options guide covers what configureproduct.tpl displays, and my GTM and GA4 guide covers tracking on the complete page.
The Nexus Cart is the exception. The Nexus Cart page says the layout of its single-page screens, such as domain pricing, results and the cart, cannot be modified. You can change colors and formatting through CSS variables. If a client needs a different cart layout, I build a Standard Cart child instead.
Which template variables can every WHMCS theme use?
A fixed set is available to every system theme and order form template, listed on the Variables page. The ones I use most:
{$WEB_ROOT}and{$systemurl}for links and asset paths.{$loggedin}and{$client}to show content only to a logged-in client.{$template}and{$filename}to know which theme and page are rendering.{$token}, the CSRF token for any POST form you add.{$companyname},{$language}and{$pagetitle}.
Each page adds its own variables. Put {debug} in a template, load the page and you get a popup listing everything available, then remove it. To add a variable of your own, use a page hook rather than PHP in the template. The documented example returns an array from ClientAreaPageViewTicket, and the keys become variables in viewticket.tpl:
add_hook('ClientAreaPageViewTicket', 1, function ($vars) {
return ['supportHours' => 'Monday to Friday, 9:00 to 17:00 UTC'];
});
My WHMCS hooks guide covers where hook files go and how to debug them.
When is editing a theme the wrong approach?
When the change is about data or behavior rather than markup.
- Menu and sidebar items. Add, remove or relabel them with navigation and sidebar hooks. Editing the include files only changes how they look.
- Business logic. Prices, validation and provisioning belong in hooks or modules. A template only displays.
- Nexus Cart layout. It cannot be changed, only restyled.
- Many copied files. Every copied file is a file you check by hand at each release. Keep the list short.
- Bought themes. Updates come from the vendor. The documentation says to check the theme's Marketplace listing and contact the vendor. I founded WHMCSPilot, which sells WHMCS themes, so weigh my view of that market accordingly.
How do you test a WHMCS theme before customers see it?
Preview it with a URL parameter on a staging copy, then check every page type.
- Open the client area with
?systpl=mytheme, or the cart with?carttpl=mycart. WHMCS checks the dependencies first and shows nothing if they are not met, which points you to thetheme.yamlfiles of the theme and its parent. If the page loads, the choice sticks for that browser session. - Walk through the homepage, login, client area home, a service, an invoice, a ticket and a full test order.
- If a page breaks, load it again with
?systpl=twenty-one. If the shipped theme works, the fault is in your files. - Empty the template cache after each round of changes.
When a design needs more than a child theme can give, it becomes WHMCS theme customization or custom module work, which I scope on a free call of about 30 minutes.
Last reviewed 12 October 2026. Disclosure: I sell WHMCS and web development work, so I am not neutral. I am CTO at ElySpace, a freelance developer for Marmaids LLC, and founder of WHMCSPilot and MagizAI. File names and settings are from the WHMCS 9.0 documentation and developers.whmcs.com as I read them on that date.