{"id":4459,"date":"2026-09-04T06:15:13","date_gmt":"2026-09-04T06:15:13","guid":{"rendered":"https:\/\/skynethosting.net\/blog\/?p=4459"},"modified":"2026-09-07T06:32:10","modified_gmt":"2026-09-07T06:32:10","slug":"custom-whmcs-client-portal-theme","status":"publish","type":"post","link":"https:\/\/skynethosting.net\/blog\/custom-whmcs-client-portal-theme\/","title":{"rendered":"How to Create a Custom Client Portal Theme in WHMCS Using Smarty Templates"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">WHMCS renders its entire client portal through Smarty, a templating engine that separates page logic from the actual HTML a customer sees, which is what makes a custom, fully branded theme possible without touching WHMCS&#8217;s own PHP code. The safe way to build one is a child theme: a small folder of overrides that sits on top of an existing system theme, Twenty-One or Nexus, rather than a full rewrite that has to be manually reapplied every time WHMCS ships an update.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A child theme is not a shortcut around real customization work. It is a structure that keeps that work intact the next time WHMCS updates its default theme underneath you.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How Does WHMCS Use Smarty to Control the Client Portal?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">WHMCS uses Smarty to control every page a customer sees in the client portal, from the login screen to an invoice to a support ticket thread. Smarty templates define the structure and content placement, WHMCS&#8217;s PHP code supplies the actual data, and the two come together at page load to produce the final HTML.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Understanding Smarty templates in WHMCS<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Smarty is a general purpose PHP templating engine, not something WHMCS built itself, which means the syntax, variables wrapped in curly braces, conditional blocks, loops, follows Smarty&#8217;s own documented rules rather than a proprietary format unique to WHMCS. Anyone who has worked with Smarty on another PHP project already knows most of what they need here.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">WHMCS&#8217;s own developer documentation confirms this directly: WHMCS uses the Smarty templating engine specifically because it is fast and flexible enough to handle the range of dynamic, data driven pages a billing and client management system needs to generate.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How system themes control the Client Area interface<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A System Theme is the overall visual and structural framework applied across the entire client portal, and WHMCS ships two by default: Twenty-One, introduced in WHMCS 8.1, and Nexus, introduced in WHMCS 9.0. An older theme called Six shipped with earlier WHMCS versions and is being phased out, so any new custom theme should build on Twenty-One or Nexus rather than Six.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The active System Theme is set inside WHMCS at Configuration, System Settings, General Settings, under the General tab, and this same setting is where a custom or child theme gets selected once it exists.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Understanding .tpl template files and variables<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Every page in the client portal corresponds to one or more .tpl files, plain text files containing HTML mixed with Smarty syntax. A header.tpl and footer.tpl wrap around most pages, while individual pages like an invoice view or a support ticket list have their own dedicated template files defining that page&#8217;s specific layout.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Variables inside these templates, written as a name wrapped in curly braces, get replaced with real data when WHMCS renders the page. A client&#8217;s name, an invoice total, a support ticket subject, all arrive in the template this way rather than being hard coded anywhere in the file itself.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Smarty also supports conditional logic and loops directly inside the template file, an if block that only shows a renewal notice when a service is actually close to expiring, or a loop that lists every invoice a client has rather than a fixed number written by hand. This is what lets a single .tpl file correctly render a completely different result for a client with one active service versus a client with fifteen.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How WHMCS passes data into templates<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Behind every .tpl file, WHMCS&#8217;s PHP code assembles the actual data, a client&#8217;s invoices, their active services, their ticket history, and hands it to Smarty as a set of named variables the template can then reference and display. The template itself never queries the database directly, it only receives and arranges what WHMCS&#8217;s PHP layer has already prepared.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This same pattern extends beyond the client portal itself. WHMCS&#8217;s automated emails, invoices, welcome messages, renewal reminders, also render through Smarty, which is worth knowing if branded communication matters as much as the portal itself. Pairing consistently branded templates with reliable delivery through <a href=\"https:\/\/www.skynethosting.net\/mailchannels-email.htm\">MailChannels<\/a> email infrastructure means a client&#8217;s entire experience, portal and inbox, stays visually and functionally consistent.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How Can You Create a Safe Custom WHMCS Theme?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A safe custom WHMCS theme means building a child theme rather than editing a system theme directly: choosing a parent, creating a small folder of override files, and activating it, all without ever modifying the original Twenty-One or Nexus files WHMCS ships.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Choosing a suitable parent theme<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Twenty-One and Nexus are both valid parent themes, and WHMCS&#8217;s own documentation recommends building on one of these two rather than the older Six theme, which is on its way out of active support. For a brand new theme with no existing customization history to preserve, Nexus, being the newer of the two, is generally the more future proof starting point.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This decision applies regardless of which reseller tier a business runs WHMCS on, since the <a href=\"https:\/\/www.skynethosting.net\/whmcs.htm\">free WHMCS license<\/a> bundled with a SkyNetHosting reseller account includes the same theming capability across every plan, not a limited version on smaller tiers.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Creating a child theme instead of modifying the default theme<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A child theme starts as a new folder inside the templates directory, named using only lowercase letters, numbers, hyphens, and underscores. Inside that folder, a theme.yaml file identifies it as a child theme and specifies which parent it builds on, using a config section with a parent value matching the parent theme&#8217;s directory name exactly, for example twenty-one.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">That theme.yaml file can also declare a name, an author, and dependencies the theme relies on, but at minimum it needs the theme name and the parent directory reference to function as a valid child theme WHMCS recognizes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This structure is a meaningful change from how WHMCS theming used to work in older versions, where a full custom theme required copying and maintaining an entire parent theme rather than just the pieces actually being changed. Anyone customizing WHMCS on version 8.0 or earlier is still working with that older, heavier approach, which is one more reason an update to a current version is worth prioritizing before investing significant time into a new theme.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Copying the required template files<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A child theme does not need a copy of every file from its parent, only the specific files being customized. To change the footer, for example, only footer.tpl gets copied from the parent theme into the child theme&#8217;s own folder, where it can then be edited freely. Any file not copied into the child theme continues inheriting directly from the parent, which is exactly what keeps a child theme lightweight and easy to maintain.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CSS changes follow a similar, even simpler pattern: creating a css\/custom.css file inside the child theme folder is enough to layer custom styling on top of the parent theme without touching any of its original stylesheets directly.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Activating the custom theme in WHMCS<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Once the child theme folder and its theme.yaml file exist, it appears automatically in the System Theme dropdown at Configuration, System Settings, General Settings, alongside the default Twenty-One and Nexus options. Selecting it there activates it immediately for every client visiting the portal from that point forward.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">WHMCS also checks for compatibility issues between the selected theme and any order form templates in use, and will surface a warning if something does not line up, which is worth resolving before considering the activation fully complete.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How Can You Customize the WHMCS Client Portal With Smarty Templates?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Customizing the client portal through Smarty means editing the specific .tpl files that control each visual element, the header, the footer, navigation, page layouts, while adding CSS and JavaScript through the child theme&#8217;s own asset files rather than touching anything belonging to the parent theme.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Customizing the header and footer<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Copying header.tpl and footer.tpl from the parent theme into the child theme gives full control over the top and bottom of every client portal page, including the logo placement, top navigation links, and footer content like copyright text or support contact details.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Changing navigation and sidebar presentation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Navigation structure and any sidebar content typically live in their own include templates, shared across multiple pages rather than duplicated on each one. Editing these shared includes, rather than individual page templates, is what keeps navigation changes consistent across the entire portal instead of applying inconsistently page by page.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This shared structure is also why a small navigation change, adding one new menu item, renaming a label, only needs a single file edited rather than the same change repeated across every page template individually. Finding the correct include file the first time saves considerably more effort than it costs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Modifying page layouts and content sections<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Beyond the shared header, footer, and navigation, individual pages, the invoice view, the service details page, the support ticket list, each have their own template file controlling that page&#8217;s specific layout. These get copied into the child theme the same way header.tpl and footer.tpl do, only when a specific page actually needs a layout change.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Adding your own CSS and JavaScript<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A child theme&#8217;s css\/custom.css file is the standard place for style overrides, loaded after the parent theme&#8217;s own stylesheets so custom rules take precedence without needing to edit anything in the parent theme directly. Custom JavaScript follows a similar pattern, added as its own file and referenced from the child theme&#8217;s template files rather than injected into parent theme files.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Keeping these assets lean matters beyond just organization. A client portal loaded with unnecessarily heavy custom CSS or JavaScript is a page speed problem as much as a maintenance one, and hosting the WHMCS installation itself on faster infrastructure, such as <a href=\"https:\/\/www.skynethosting.net\/nvme-vps.html\">NVMe backed VPS storage<\/a>, only partially compensates for assets that were never optimized in the first place.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Working with existing WHMCS template variables<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Every copied template file arrives already using WHMCS&#8217;s own variables and include statements, and preserving those, rather than stripping them out during a redesign, is what keeps the page still functioning correctly after customization. A variable displaying a client&#8217;s name or an invoice total is doing real work, not decoration that can be safely deleted.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">WHMCS specifically recommends maintaining the template includes and output variables present in the default header and footer when creating custom versions, since addons and third party extensions often rely on those same includes being present to display their own content correctly inside the portal.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How Can You Make Your WHMCS Client Portal Match Your Brand?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Matching your brand inside WHMCS means applying your logo and colors consistently, structuring navigation the way your own website already does, and treating the client portal as a continuation of your brand rather than a separate, generic looking system a client happens to land on after checkout.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Applying your company logo and visual identity<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The Twenty-One, Nexus, and Six themes all display either a company name or an uploaded logo in the top left corner of the client portal, controlled through the $assetLogoPath variable. Uploading a logo through the Setup Wizard or at Configuration, System Settings, General Settings, saves it as logo.png or logo.jpg inside the assets image directory, where the theme picks it up automatically.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For a reseller already using <a href=\"https:\/\/www.skynethosting.net\/mycompanyweb.htm\">MyCompanyWeb<\/a> storefront templates for the customer facing side of the business, matching that same logo and color treatment inside the WHMCS client portal closes what would otherwise be a visible seam between the storefront and the account management experience a client sees immediately after checkout.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Matching colors, typography, and spacing<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The child theme&#8217;s css\/custom.css file is where brand colors, fonts, and spacing get applied across the portal, overriding the parent theme&#8217;s defaults without needing to hunt through every individual template file to change a color value repeated dozens of times.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Pulling actual values, hex codes, font names, spacing measurements, directly from an existing brand style guide or the main marketing website&#8217;s own stylesheet, rather than eyeballing a close match, is what makes the portal feel genuinely unified rather than merely similar in a general sense.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Creating consistent navigation and customer journeys<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Navigation structure inside the client portal should mirror the logic a client already expects from your main website, grouping billing, support, and account settings the same way a client would intuitively look for them, rather than following WHMCS&#8217;s default arrangement purely because it shipped that way.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For a business managing multiple client facing brands under one <a href=\"https:\/\/www.skynethosting.net\/master-reseller-hosting.htm\">master reseller<\/a> setup, this consistency matters even more, since each brand&#8217;s client portal needs its own distinct navigation and identity rather than all of them visibly sharing the same underlying WHMCS theme.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Designing a professional white-label experience<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A genuinely white-label client portal removes every visible reference to WHMCS itself, replacing default branding, footer text, and any generic terminology with your own company&#8217;s name and voice throughout. This is less about a single dramatic redesign and more about consistently checking every page a client actually encounters for a stray default reference left behind.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Keeping branding consistent with your main website<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A client portal that looks noticeably different from the main marketing website it sits behind creates a small but real moment of doubt for a new customer, wondering briefly whether they have been redirected somewhere unexpected. Matching fonts, colors, and overall visual tone between the two removes that friction entirely.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What Mistakes Should You Avoid When Customizing WHMCS Themes?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The most common WHMCS theme mistakes are not design failures. They are structural ones: editing the wrong files directly, removing something the system actually depends on, or skipping the testing that would have caught a problem before a client did.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Editing the default system theme directly<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Modifying Twenty-One or Nexus files directly, rather than through a child theme, means every single customization gets silently overwritten the next time WHMCS updates that system theme. This is the single most consequential mistake on this entire list, since it can erase weeks of branding work in one routine update with no warning beforehand.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Removing required template variables or includes<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Stripping out a variable or include statement that looked unnecessary during a redesign can quietly break functionality that only becomes visible later, an addon that stops displaying correctly, a piece of account information that no longer appears where a client expects it. WHMCS&#8217;s own guidance on preserving header and footer includes exists specifically because of how often this exact mistake happens.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Overwriting core WHMCS files unnecessarily<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Core WHMCS files, the actual PHP application logic rather than template files, should never need direct modification for a theme customization. Any theming task genuinely requiring a core file edit is very likely being approached the wrong way, since Smarty templates and child themes are specifically designed to cover the entire range of visual customization without touching core code.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Ignoring compatibility after WHMCS updates<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Even a properly built child theme is not entirely immune to future breakage, since a parent theme&#8217;s internal structure can occasionally change enough that a child theme&#8217;s overrides need adjusting to match. Treating a completed theme as permanently finished, rather than checking it after every WHMCS update, is how a small compatibility gap turns into a client noticing a broken page.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Making changes without testing the complete Client Area<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A theme change tested only on the login page or one invoice view can miss a problem sitting on a page nobody thought to check, a support ticket thread, a domain management screen, an order form. Walking through the entire client portal as an actual test account, not just the pages that were directly edited, is what catches this category of mistake before a real client does.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How Can You Maintain Your Custom WHMCS Theme After Future Updates?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Maintaining a custom theme long term means tracking what changes between WHMCS versions, testing updates before they reach production, watching for changes to the parent theme specifically, and keeping the customization work itself organized enough that maintaining it does not depend entirely on one person&#8217;s memory.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Tracking changes between WHMCS versions<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">WHMCS publishes release notes and changelogs for each version, and reviewing these before applying an update, specifically for any mention of theme or template changes, gives advance warning of anything that might affect a custom child theme before it actually goes live on a production portal.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Testing the theme before applying production updates<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A staging or test copy of the WHMCS installation, kept separate from the live client portal, is where an update should land first. Applying the update there, then reviewing the custom theme across the full client portal exactly as described earlier, confirms nothing broke before the same update touches the environment real clients actually use.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Reviewing changes to parent themes<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Since a child theme inherits everything it has not explicitly overridden, a change to the parent theme&#8217;s structure can affect a child theme in ways that are not obvious until an actual page is checked directly. Comparing the parent theme&#8217;s updated files against what the child theme currently overrides, specifically the files it copied and modified, surfaces this kind of gap directly.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Keeping custom CSS and JavaScript organized<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">A single, growing css\/custom.css file with no internal structure becomes difficult to safely edit after enough changes accumulate over time. Grouping related styles together with clear comments, rather than appending new rules to the end of the file indefinitely, keeps future edits, including the person&#8217;s own future edits, far easier to make confidently.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Maintaining a backup or version-controlled copy<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Keeping the child theme folder under version control, even a simple git repository, or maintaining a dated backup copy before every significant change, means a mistake or an unexpected update conflict can be rolled back cleanly rather than rebuilt from memory. For a theme representing real, ongoing brand investment, this is a small habit against a genuinely disruptive kind of loss.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A custom WHMCS theme is only half of a fully branded client experience. The other half is the storefront a client sees before they ever log into the portal at all. See how <a href=\"https:\/\/www.skynethosting.net\/mycompanyweb.htm\">MyCompanyWeb<\/a> storefront templates pair with a custom client portal theme to keep a reseller&#8217;s brand consistent across the entire customer journey.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>WHMCS renders its entire client portal through Smarty, a templating engine that separates page logic from the actual HTML a customer sees, which is what makes a custom, fully branded theme possible without touching WHMCS&#8217;s own PHP code. The safe way to build one is a child theme: a small folder of overrides that sits [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-4459","post","type-post","status-publish","format-standard","hentry","category-skynethostinghappenings"],"blog_post_layout_featured_media_urls":{"thumbnail":"","full":""},"categories_names":{"1":{"name":"Skynethosting.net News","link":"https:\/\/skynethosting.net\/blog\/category\/skynethostinghappenings\/"}},"tags_names":[],"comments_number":"0","wpmagazine_modules_lite_featured_media_urls":{"thumbnail":"","cvmm-medium":"","cvmm-medium-plus":"","cvmm-portrait":"","cvmm-medium-square":"","cvmm-large":"","cvmm-small":"","full":""},"_links":{"self":[{"href":"https:\/\/skynethosting.net\/blog\/wp-json\/wp\/v2\/posts\/4459","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/skynethosting.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/skynethosting.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/skynethosting.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/skynethosting.net\/blog\/wp-json\/wp\/v2\/comments?post=4459"}],"version-history":[{"count":1,"href":"https:\/\/skynethosting.net\/blog\/wp-json\/wp\/v2\/posts\/4459\/revisions"}],"predecessor-version":[{"id":4460,"href":"https:\/\/skynethosting.net\/blog\/wp-json\/wp\/v2\/posts\/4459\/revisions\/4460"}],"wp:attachment":[{"href":"https:\/\/skynethosting.net\/blog\/wp-json\/wp\/v2\/media?parent=4459"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/skynethosting.net\/blog\/wp-json\/wp\/v2\/categories?post=4459"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/skynethosting.net\/blog\/wp-json\/wp\/v2\/tags?post=4459"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}