Builder Guide
Apply a TailAdmin-style design and customize every React page
Set up an owned CSS and token system from a licensed React template, refine shared components, edit each SaaS page in Puck, and publish the finished design safely.
A premium React template such as TailAdmin can provide the visual language for a BuildWithHQ SaaS: spacing, cards, tables, forms, navigation, badges, charts and responsive layouts. BuildWithHQ remains the application runtime. Adapt the design into the owned component and token system; do not replace authentication, routing, data bindings, secured module APIs or canonical page JSON.
If you are only customizing an installed template through the Builder, begin at “Edit each page in Design mode.” Repository-level CSS and React changes are for the template maintainer who is creating the reusable foundation.
1. Prepare an owned design source
- Choose a React/admin design whose license permits your intended use. Record its version, source, license and any required notice.
- Keep the unmodified vendor snapshot as review evidence. Do not make it the production runtime.
- Create an owned BuildWithHQ adaptation. For the current TailAdmin-derived system, use
templates/tailadmin-battle-system/; its README records the reviewed TailAdmin 2.3.0 source andLICENSE.tailadmin.mdcarries the MIT notice. - Inventory useful patterns—shell, page header, cards, tables, fields, dialogs, status badges, charts, empty states and mobile navigation—and map each to an existing BuildWithHQ primitive or native module.
- Do not import the template's router, login, mock API, data store or example business logic.
Never load a CSS framework from a CDN or paste scripts, arbitrary HTML, secrets, database names or executable event strings into page JSON. Repository-maintained foundations use bundled React and compiled CSS; an individual SaaS may also publish validated app-scoped CSS through App Assets.
2. Work in a guarded workshop SaaS
- Create or select an account-owned workshop SaaS—not a customer tenant.
- Install the current Professional Foundation or the guarded TailAdmin battle manifest.
- Confirm that the expected first-class pages and registered components resolve before changing their appearance.
- Capture the starting desktop and mobile screens so visual changes can be compared rather than judged from memory.
- Keep all lifecycle behavior in the existing native modules. The workshop is for design and template authoring, not direct database editing.
3. Confirm the shared CSS entry points
The tenant runtime already loads the shared professional primitives first and the app-level stylesheet second:
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import App from "./App";
import "@buildwithhq/ui/professional.css";
import "./styles.css";
This order is intentional. @buildwithhq/ui/professional.css supplies safe reusable component styling. apps/tenant-runtime/src/styles.css owns the shell, theme defaults and product-level refinements and may deliberately override shared rules.
Do not paste all of TailAdmin's generated CSS into styles.css. Translate the selected pattern into small owned classes and existing --runtime-* tokens. This keeps the bundle understandable and prevents unrelated template selectors from changing Puck, native modules or dialogs.
App-scoped CSS and design assets
For one SaaS, open App Assets. The Custom CSS window accepts UTF-8 CSS, previews it locally, and publishes it as that app's public theme.css. Use this for brand tokens and bounded app overrides; use the repository CSS entry points above when creating or changing the shared reusable foundation.
- Enter an optional virtual Asset upload folder, such as
brand/images. This organizes metadata only; it cannot select a server or operating-system directory. - Assets are private by default. Select Public design asset only for a logo, image, font, video, PDF, or file that a rendered template must request without an authenticated download call.
- Upload the file, then use the returned immutable URL:
https://assets.buildwithhq.com/{saasAppId}/{assetId}. - Reference that URL from a registered component property, an image/logo field, or a stylesheet
url(...). Published CSS may reference only relative paths, fragments, or the same SaaS app's asset prefix. - Use Preview CSS, review desktop and mobile pages, then choose Publish CSS. The runtime activates the latest public stylesheet for the signed-in app.
The appliance operator sets the physical upload root with BWHQ_FILE_STORAGE_ROOT and routes DNS/TLS for assets.buildwithhq.com. Builders never receive a filesystem path or database permission.
Uploads accept all extensions except .dll, .com and .exe. That is an upload rule, not an inline-execution rule: only validated CSS and passive image, video, font and PDF types render inline. HTML, SVG, scripts, archives and unknown types are downloaded as inert attachments with nosniff and a sandbox policy.
4. Establish the theme before styling individual pages
Choose one light, dark or system direction and set the allowlisted theme variables through the supported version-fenced theme contract. A starting light theme looks like this:
{
"schemaVersion": 1,
"themeKey": "my-saas-light",
"themeJson": { "schemaVersion": 1, "name": "My SaaS Light", "mode": "light" },
"cssVariables": {
"--runtime-primary": "#465fff",
"--runtime-primary-strong": "#3641f5",
"--runtime-primary-tint": "#ecf3ff",
"--runtime-page": "#f9fafb",
"--runtime-surface": "#ffffff",
"--runtime-ink": "#101828",
"--runtime-ink-muted": "#667085",
"--runtime-line": "#e4e7ec"
},
"designTokensJson": { "spacingBase": 8, "radiusBase": 8 }
}
Use tokens for page/surface colors, ink, muted ink, boundaries, primary and semantic tones. The runtime also supplies the shared spacing, font-size, radius and shadow vocabulary. Change the theme when a value represents the SaaS brand; change component CSS when it represents component structure.
Do not insert theme rows directly into a tenant database and do not add arbitrary CSS or script fields to the theme document. Save through the supported theme API so expected-version checks and validation remain active.
5. Polish shared primitives once
Before customizing twenty pages independently, finish one shared treatment for each repeated element:
- shell content width, gutters, sidebar, top bar, selected navigation and mobile menu;
- page headers, breadcrumbs and action alignment;
- primary, secondary, quiet, danger and icon-only buttons;
- fields, labels, help text, validation, disabled controls and focus rings;
- cards, metrics, tables, tabs, badges, dropdowns, dialogs and confirmations;
- loading, empty, permission-denied, stale-write, error and success states;
- the shared 25×25 gray/gold favorite star and its accessible label/focus state.
Shared React primitives live in packages/ui/src/professional-primitives.tsx; their styles live in packages/ui/src/professional-primitives.css; the bounded icon vocabulary lives in packages/ui/src/icon-registry.tsx. Improve these when every module should receive the same treatment.
6. Customize the React look and behavior at the correct layer
| Desired change | Correct owner |
|---|---|
| Brand color, page background, shared ink or border color | SaaS theme tokens |
| All cards/tables/metrics need the same refinement | packages/ui shared primitive and CSS |
| Shell, sidebar, top bar, dialog or application-wide state | apps/tenant-runtime/src/styles.css and the owning shell component |
| Only Calendar, Mail, Contacts or another native module needs a special interaction | That module's apps/tenant-runtime/src/*Module.tsx and focused CSS/tests |
| Page order, columns, responsive spans or registered component properties | Puck/canonical page JSON |
| A new reusable visual block | Reviewed React component, static renderer registration, Puck property schema and tests |
| A new data mutation | Typed client, authorized route/service and reviewed stored procedure before any control is shown |
Keep renderer registration static. Component metadata must never become an arbitrary import path. Expose only intentional, validated Puck properties, and render server-returned text as React content rather than executable markup.
When adapting a TailAdmin component
- Remove demo data, routing, authentication and network calls.
- Replace hard-coded colors, spacing, shadows and radii with runtime tokens.
- Replace arbitrary SVG/HTML with the reviewed icon vocabulary or a separately reviewed licensed asset.
- Accept a bounded typed presentation document or the native module's typed data—not a free-form payload.
- Add loading, empty, error, denied, long-content and narrow-screen behavior.
- Add keyboard focus, accessible names and reduced-motion behavior.
- Register it only if it needs to be independently placeable in Puck; otherwise keep it inside its native module.
7. Edit each page in Design mode
- Open the workshop SaaS and choose Design.
- Select the User Type and verify the menu that should contain the page.
- Select the shared page and open its editor.
- Use Puck (primary) to add, remove, rearrange and configure registered components.
- Use Monaco (advanced) only for a canonical property that Puck cannot yet express conveniently.
- Keep block
_idvalues stable. A copied block needs a new unique ID. - Preserve
bindingKey, optionaldataKey, responsive settings, actions and security metadata. - Preview, save a draft with a meaningful note, validate, inspect role preview and publish only after the review matrix passes.
Page JSON arranges registered components; it does not grant access. Role preview changes presentation only. Live data continues to use the signed-in user's server-derived tenant, DataRoles and Locations.
8. Build responsive page compositions
Use core.container with the 12-column grid when hierarchy matters. For example, an eight-column primary workspace can collapse below its four-column context panel at tablet/mobile sizes:
{
"_id": "primary-workspace",
"_type": "core.card",
"responsive": {
"desktop": { "span": 8 },
"tablet": { "span": 12 },
"mobile": { "span": 12 }
},
"props": { "title": "Current work", "tone": "primary" },
"children": []
}
- Metrics: 3/3/3/3 desktop, 6/6 tablet, 12 mobile.
- Main dashboard: 8/4 or 7/5 desktop, stacked on tablet/mobile.
- Record detail: primary record content beside related context, then one-column on narrow screens.
- Forms: one column by default; use two columns only for short naturally paired fields.
Review at approximately 1440px desktop, 1024px tablet and 390px mobile. The existing runtime changes grid spans at 1024px and 760px and adds compact component behavior below 640px.
9. Finish pages in a deliberate order
- Finish one dashboard: Home or Executive Overview.
- Finish one queue/list: Work Orders.
- Finish one record/detail experience: Contacts or Work Order detail.
- Use those three pages to settle the shared spacing, card, toolbar, form, table and responsive patterns.
- Apply the stable patterns to Mail, Universal Inbox, GoClaw and AI Insights.
- Continue through operations, collaboration, knowledge and utility pages.
Avoid bespoke restyling across every page at once. Repeated patterns will drift and the early pages will need to be redone.
10. Complete every real page state
For every user-managed module, review loading, empty, populated, long-content, validation-error, permission-denied, server-error, stale-write and successful-mutation states. Exercise create, view, edit/update and remove/archive, plus favorite/unfavorite, record association, files and activity where applicable.
Derived pages such as Global Search, Record Activity and audit/history remain read-only. Give them a clear path to the secured native module that owns the record instead of duplicating destructive controls.
11. Verify the implementation
Repository maintainers should run:
python -m pytest templates\professional-foundation\tests -q
npm --prefix apps\tenant-runtime test -- src\ProfessionalPrimitives.test.tsx src\PageRenderer.test.tsx src\PuckPageDesignerAdapter.test.ts src\SaasDesignStudio.test.tsx
npm --prefix apps\tenant-runtime run build
python tests\e2e\run_visual_build_proof.py --static-only
Then run authenticated desktop and mobile journeys against a route-resolved disposable tenant. Static preview proves layout and contracts; it does not prove live publication, permissions or database behavior.
- No inert or invented actions.
- No browser database identity, credentials or provider secrets.
- Visible controls match actual permissions and routes.
- Focus order, labels, contrast, touch targets and overflow are usable.
- Mutations refresh the affected record/list/count/favorite state.
- Long and zero-result data remain polished.
12. Harvest and publish the finished template
- Finish and publish the pages in the account-owned workshop SaaS.
- Harvest each owned Page through
POST /api/apps/{saasAppId}/template-harvests. - Attach the artifacts to a draft Template Library package and validate it.
- Publish an immutable exact version.
- Install that exact version into a different disposable SaaS.
- Repeat lifecycle, permission, desktop and mobile checks in the installed copy before offering it to other builders.
Current template-pack members do not copy SaaS asset bytes or remap source-app asset URLs into the installed app. Public asset URLs are immutable and usable by the working source SaaS, but an asset-dependent template is not yet a self-contained exact-version install. Package-and-remap support must be completed before offering such a template as portable.
Use TailAdmin to set the quality bar. Let BuildWithHQ own the final CSS, React, data contracts and page JSON. That produces a distinctive professional SaaS without creating a fragile second application inside the platform.
Continue with the Professional Template Foundation, page editor, React component catalog, and exact-version template guide.
Compare all six styling approaches in Support for React.
Capability review: 2026-09-14. For exact current technical availability, use the generated API Map and first-class module inventory.