whitebrand
v1.6.51
Published
Deterministic AST rewriting engine for multi-tenant whitelabeling
Maintainers
Readme
Whitebrand Enterprise CLI Documentation
Version: 1.6.47
Type: Deterministic Build-Time Whitelabel Engine
Supported Environments: React (Vite), Next.js, React Native (Expo)
Whitebrand is a PROJECT-LEVEL WHITELABELING CLI and AST (Abstract Syntax Tree) rewriting engine. It is specifically engineered to convert rigid, single-tenant frontend codebases into dynamic, multi-tenant B2B architectures.
The Problem vs The Solution
The Problem: Development agencies often build a successful platform and want to sell it to multiple distinct clients. Similarly, SaaS companies frequently land enterprise clients who demand their own fully branded, isolated version of the platform. Historically, developers have solved this by copy-pasting the entire source code into new repositories, creating an unmaintainable nightmare of divergent codebases ("fork hell"), or by manually hunting down hundreds of hardcoded colors, logos, and strings.
The Solution: Whitebrand solves this by operating at the compiler level. Instead of duplicating the codebase, Whitebrand keeps your single source of truth intact. It deterministically abstracts all hardcoded literals (strings, colors, URLs) into strict JSON schemas, allowing a single codebase to serve infinite distinct branding and content profiles. When you need a new client version, you just add a new tenant configuration—no source code duplication required.
Unlike traditional methods that rely on manual extraction or inherently unstable Generative AI rewrites, Whitebrand operates strictly on deterministic mathematical confidence algorithms to ensure zero runtime performance penalties and absolute code safety.
1. The Core Architectural Philosophy
1.1 The Deterministic AST Mandate
Relying on LLMs to parse, modify, and rewrite source code directly introduces catastrophic risks to production applications. LLMs frequently hallucinate syntax, destroy scope, misplace imports, or silently delete essential logic.
Whitebrand explicitly forbids AI from modifying source code. The architecture strictly isolates intelligent abstraction from deterministic modification.
1.2 The 3-Layer Pipeline
The system operates across three distinct, sandboxed layers:
Layer 1: Extraction (AST)
The CLI recursively parses the target application utilizing the ts-morph compiler API. It identifies terminal literals and assigns a strict Technical Semantic (e.g., TRANSLATION_TEXT, BRANDING_COLOR, API_ENDPOINT) based exclusively on the AST context (JSX attribute type, variable declaration, property assignment). This layer executes with zero linguistic bias and outputs raw AST nodes to a registry.json file.
Layer 2: Interpretation (AI / Manual)
The raw registry.json is provided to an LLM Copilot or a human engineer. The sole objective of this layer is to group technically identical values and assign them a Business Semantic (e.g., PRIMARY_BUTTON_LABEL, CHECKOUT_HEADER) and a Domain (e.g., AUTH, DASHBOARD). The output is a .whitebrand/mapping.json file. The AI has zero access to the actual source code files.
Layer 3: Verification & Rewriting (Deterministic)
Before modifying the AST, Whitebrand normalizes the assigned domains and calculates an Evidence-Based Confidence Score (0-100) for each mapped semantic group. Confidence is derived exclusively from mathematical internal consistency:
- 100 Score: All nodes in a group share the exact same technical type, AST ancestor chain depth, and value profile.
- < 80 Score: Nodes within the group exhibit disparate technical types (e.g., mapping a color literal and a URL string into the same business semantic).
The engine executes surgical AST substitutions via ts-morph only for high-confidence mappings. It explicitly avoids regex replacements.
2. Installation & Bootstrapping
Whitebrand is designed to run seamlessly in local developer environments and headless CI pipelines.
2.1 Global Installation
For utilizing the CLI across multiple repositories:
npm install -g whitebrand2.2 Local Dependency (Recommended)
For strict version locking within a team:
npm install --save-dev whitebrand2.3 Bootstrapping
Execute the initialization protocol in the root of your frontend repository:
npx whitebrand initExecution Flow:
- Framework Detection: Scans
package.jsonfor Vite, Next.js, or Expo dependencies. - Directory Scaffolding: Generates the
.whitebrand/internal cache andtenants/configuration directories. - Runtime Injection: Generates
src/whitebrand.tsx(the Context Provider) and injects it into your root layout (_app.tsx,layout.tsx,App.tsx, ormain.tsx). - Initial Extraction: Automatically executes the
extractpipeline to build the baselineregistry.json.
3. The Data Schemas
Understanding the JSON configurations generated by Whitebrand is essential for mastering the pipeline.
3.1 registry.json
Generated by whitebrand extract. Represents raw, unopinionated AST nodes.
{
"projectStats": {
"filesScanned": 142,
"literalsFound": 1054
},
"nodes": [
{
"id": "node_7a8b9c",
"value": "#3B82F6",
"type": "StringLiteral",
"filePath": "src/components/Button.tsx",
"startLine": 42,
"endLine": 42,
"technicalSemantic": "BRANDING_COLOR",
"context": "JSXAttribute[name='color']"
}
]
}3.2 mapping.json
Generated by whitebrand suggest (via AI) or manually. Maps nodes to business logic.
{
"theme": {
"primaryColor": {
"nodes": ["node_7a8b9c", "node_1f2d3e"],
"value": "#3B82F6"
}
},
"copy": {
"loginTitle": {
"nodes": ["node_4x5y6z"],
"value": "Welcome Back"
}
}
}3.3 Tenant config.json
Generated during whitebrand rewrite. This represents the actual runtime configuration injected into the application.
{
"$schema": "../schema.json",
"theme": {
"primaryColor": "#3B82F6"
},
"copy": {
"loginTitle": "Welcome Back"
}
}4. Comprehensive CLI Command Reference
The CLI is strictly segmented by operational lifecycle phases.
4.1 Initialization & Analysis Commands
whitebrand init [options]
Initializes the system and scaffolds dependencies.
| Flag | Description |
|---|---|
| --force | Bypasses all confirmation prompts and overwrites existing configurations. |
| --no-extract | Halts execution after scaffolding, bypassing the heavy AST extraction phase. |
| --dir <path> | Specifies a custom root directory (default: .) |
whitebrand extract [options]
Executes the ts-morph AST scanner to rebuild registry.json.
| Flag | Description |
|---|---|
| --include <glob> | Specifies strict inclusion paths (e.g., src/components/**/*). |
| --exclude <glob> | Specifies strict exclusion paths (e.g., tests/**/*, e2e/**/*). |
| --verbose | Outputs live AST parsing data to stdout. |
whitebrand suggest [options]
Reads the registry.json and outputs a mathematically optimized prompt for an LLM to generate the mapping.json.
| Flag | Description |
|---|---|
| --clip | Automatically copies the generated prompt to the system clipboard. |
| --context <text>| Injects domain-specific context into the prompt (e.g., "This is a healthcare app"). |
4.2 Rewriting & Restoration Commands
whitebrand rewrite [options]
The most critical command. Applies the mapping.json to the source code, altering the AST, generating schema.d.ts, and scaffolding tenants/default/config.json.
| Flag | Description |
|---|---|
| --dry-run | Executes the confidence scoring algorithm and outputs the proposed AST diffs without writing to disk. |
| --strict | Enforces a minimum Evidence-Based Confidence Score of 80. Mappings scoring <80 will immediately fail the rewrite. |
whitebrand rollback [options]
Restores the source code to its exact state prior to the last rewrite execution.
| Flag | Description |
|---|---|
| --force | Bypasses confirmation prompts. |
| --target <commit>| Restores from a specific internal backup hash rather than the latest. |
whitebrand undo
Safely uninstalls the entire Whitebrand system. Removes the Context Provider, .whitebrand/, and tenants/ directories. Restores the source code to the default tenant state.
4.3 Tenant Management Lifecycle
whitebrand add [options] <tenant-id>
Scaffolds a new tenant configuration directory, clones default assets (icon.png, logo.png), and actively locates and copies the home.tsx component from the default tenant to bootstrap the new environment.
| Flag | Description |
|---|---|
| -n, --name <string> | Specifies the display name of the App. |
| -c, --color <hex> | Instantly sets the primary branding color for the new tenant. |
| -m, --manual | Skips automatic AST router injection and only generates the tenant configuration folders. |
The AI Escape Hatch & Strict Mode:
If whitebrand.config.ts is set to mode: 'strict', the CLI automatically forces --manual mode, preventing automated injection into highly complex or custom router files.
If automatic patchRouter fails due to an architectural mismatch, Whitebrand gracefully catches the exception and prints an AI Escape Hatch—a pre-written prompt designed for you to copy/paste directly into an AI Copilot (Cursor, Claude, Windsurf) for instant manual resolution.
whitebrand remove <tenant-id>
Permanently deletes a tenant directory and all associated assets.
whitebrand list
Displays a tabulated list of all configured tenants, indicating their current validation status, schema compliance, and active dev server ports.
4.4 Execution & Compilation
whitebrand dev [options] <tenant-id>
Starts the underlying framework's development server, binding the specified tenant's configuration to the environment.
| Flag | Description |
|---|---|
| --port <number> | Overrides the default framework port. |
| --inspect | Enables Node.js debugging. |
whitebrand build <tenant-id>
Executes a production build for the specified tenant. The output artifacts are isolated to prevent cross-tenant contamination.
whitebrand build-all
Sequentially executes production builds for every valid tenant in the tenants/ directory.
4.5 Diagnostics & Validation
whitebrand validate
Parses every tenant config.json against the central schema.json. Throws a 1 exit code if any keys are missing, improperly typed, or extraneous.
whitebrand migrate [options]
When mapping.json is updated and a new rewrite is executed, the schema changes. migrate patches all existing tenant configurations with the new baseline default values to prevent runtime crashes.
| Flag | Description |
|---|---|
| --dry-run | Outputs the JSON patches without writing them. |
whitebrand doctor
Runs aggressive internal diagnostics. Verifies framework adapter compatibility, identifies orphaned .whitebrand/backups, and validates the structural integrity of registry.json.
whitebrand generate
Manually regenerates schema.d.ts from the schema.json. Useful if the schema was manually modified (not recommended).
4.6 Graphical Interfaces
whitebrand studio [options]
Bootstraps the local React-based management dashboard.
| Flag | Description |
|---|---|
| --port <number> | Specifies the port for the dashboard (default: 3000). |
4.7 Enterprise Licensing & Free-Tier Limits
Free-Tier Tenant Cap: The Whitebrand CLI actively enforces a maximum limit on the number of tenants you can manage under the Free Tier. Exceeding this limit via whitebrand add will exit the process and block creation.
whitebrand activate <key>
Activates the CLI for Enterprise features, unlocking unlimited tenants, deterministic AST ejection, and multi-threaded parallel building. Validates the key cryptographically against an offline authority or centralized server.
whitebrand status
Outputs the current license tier, active tenant count vs limit, expiration date, and enabled telemetry preferences.
4.8 Artifact Delivery
whitebrand eject <tenant-id>
Generates a standalone, completely vanilla copy of the repository for client handoff. Removes all traces of the Whitebrand engine, hardcoding the specific tenant's values directly into the AST.
5. Whitebrand Studio Internal Architecture
Whitebrand Studio is a full-stack local application bundled within the CLI. It serves as a visual abstraction over the CLI commands.
(Note: To display your actual UI, place your screenshot at ./docs/studio.png and update this link)
5.1 Technology Stack
- Frontend: React, Vite, CSS Modules.
- Backend: Express.js (runs internally within the CLI process).
- Communication: Standard REST API.
5.2 Core Capabilities
- Visual JSON Editing: Enforces schema compliance during tenant configuration editing via graphical form inputs.
- Process Orchestration: Spawns and manages child processes for
whitebrand devandwhitebrand builddirectly from the UI. - The Global Timeline Auditor: Maintains an append-only JSON ledger (
.whitebrand/timeline.json) powering the Studio's Timeline view. The CLI utilizes a global Commander hook (program.hook('preAction')) to silently intercept and log every single command executed by any developer on the repository, ensuring complete, auditable traceability of all multi-tenant operations.
5.3 Security Profile
The Studio is bound strictly to localhost (127.0.0.1). It aggressively rejects connections originating from external interfaces to prevent arbitrary local execution attacks.
6. Runtime Provider Architecture
Whitebrand operates entirely at build time, but it utilizes a highly optimized runtime singleton to expose the mapped configuration to the frontend components.
6.1 The getConfig() Singleton
During the init phase, Whitebrand generates a strict TypeScript provider.
import { getConfig } from 'whitebrand/runtime';
export function Button() {
const config = getConfig();
return (
<button style={{ backgroundColor: config.theme.primaryColor }}>
{config.copy.submitButton}
</button>
);
}getConfig() relies on a globally injected variable (window.__WHITEBRAND_CONFIG__ in browsers, or process.env.WHITEBRAND_CONFIG in SSR environments) to read the active tenant data synchronously.
6.2 Framework Injection Vectors
6.2.1 Vite Injection
Whitebrand provides a custom Vite plugin (whitebrand/adapters/vite). When whitebrand dev is executed, the CLI dynamically modifies the Vite command to inject this plugin, which binds the tenant JSON to import.meta.env.
6.2.2 Next.js Webpack Hook
For Next.js, Whitebrand hooks into the next.config.js via whitebrand/adapters/next. It utilizes Webpack's DefinePlugin to serialize the tenant configuration and bypass Next.js's strict environment variable static replacement constraints.
6.2.3 Expo Dynamic Configuration
For React Native (Expo), Whitebrand utilizes the app.config.js dynamic configuration feature. It reads the tenant ID from the Node environment and injects tenant-specific bundle identifiers, names, icons, and splash screens directly into the Expo compilation lifecycle.
7. The Ejection Protocol (Deep Dive)
Ejection is a critical enterprise requirement for agencies handing off single-tenant repositories to end clients.
Workflow:
- Repository Cloning: Whitebrand duplicates the current working directory to
../<app-name>-<tenant-id>-standalone. - Reverse AST Traversal: The
ts-morphengine scans the cloned repository for all occurrences ofgetConfig(). - Property Resolution: It traces the property access path (e.g.,
config.theme.primaryColor) back to the specific tenant'sconfig.json. - Hardcoded Substitution: The engine replaces the dynamic JSX attribute or variable with the hardcoded literal.
- Dependency Purge:
whitebrand/runtimeimports are deleted.whitebrandis removed frompackage.json. The.whitebranddirectory is destroyed. - Delivery: The resulting repository is a pristine, standard React/Vite/Next app with zero reliance on Whitebrand.
8. CI/CD Enterprise Integration
Implementing Whitebrand in a continuous integration environment requires understanding the validation and loop sequences.
8.1 GitHub Actions: Sequential Build Pipeline
name: Whitebrand Multi-Tenant Pipeline
on:
push:
branches: [ "main" ]
jobs:
build-tenants:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '20'
- name: Install Dependencies
run: npm ci
- name: Validate Tenant Schemas
run: npx whitebrand validate
- name: Sequential Build Execution
run: npx whitebrand build-all
- name: Upload Artifacts
uses: actions/upload-artifact@v3
with:
name: tenant-builds
path: dist/8.2 GitLab CI: Matrix Parallelization
For repositories with dozens of tenants, sequential building is too slow. Use parallel matrix jobs in GitLab:
stages:
- validate
- build
validate_schemas:
stage: validate
script:
- npm ci
- npx whitebrand validate
build_tenant:
stage: build
parallel:
matrix:
- TENANT_ID: ["acme", "globex", "soylent", "initech"]
script:
- npm ci
- npx whitebrand build $TENANT_ID
artifacts:
paths:
- dist/$TENANT_ID/(Note: To automate matrix population, you can pipe npx whitebrand list --json into your CI orchestrator).
9. Handling @wb-ignore Directives
The AST extraction engine relies on aggressive lexical analysis. Occasionally, developers use literals in complex logical evaluations that should never be abstracted into tenant configurations.
Example of Dangerous Extraction:
const isDark = theme === 'dark'; // The string 'dark' should NOT be extracted.To prevent the AST scanner from capturing a node, the strict @wb-ignore directive must be placed on the line immediately preceding the node.
// @wb-ignore
const isDark = theme === 'dark';When the ts-morph engine encounters a node, it checks the leading trivia (comments). If @wb-ignore is detected, the node is pruned from the extraction tree entirely. It will not appear in registry.json and cannot be modified by rewrite.
10. Internationalization (i18n) & AST Pruning
Whitebrand explicitly recognizes that it is not an i18n translation platform. If your codebase uses libraries like react-i18next, next-intl, or lingui, Whitebrand utilizes a smart pruning mechanism to avoid interfering with your existing localized translation logic.
10.1 The Three Types of Literals
Whitebrand's architecture semantically separates strings into three categories:
- TRANSLATION_KEY (
t("auth.login")): Pointers to translation dictionaries. These must be skipped to avoid polluting the AST config with useless keys and nesting pointers inside pointers. - BUSINESS_COPY (
"Welcome to Acme"): Hardcoded display text. These must be extracted and mapped to a tenant configuration. - TECHNICAL_LITERAL (
"admin","dark","success"): Internal state values or prop types. These must be skipped.
10.2 Automatic AST Pruning
During whitebrand init, the CLI automatically detects i18n libraries in your package.json. It will prompt you to provide your translation function signatures (e.g., t, i18n.t, translate) and append them to your whitebrand.config.ts:
export default defineConfig({
extractor: {
ignoreCallPatterns: ["t", "i18n.t", "translate"]
}
});When whitebrand extract runs, the AST scanner aggressively matches any CallExpression against these patterns. If a match is found, the literal argument is instantly pruned. Furthermore, JSX attributes named i18nKey (e.g., <Trans i18nKey="login" />) are automatically bypassed.
10.3 The Translation Asset Pipeline
Because Whitebrand ignores your translation keys, how do you provide different text for Tenant A vs Tenant B? You utilize Whitebrand's Asset Pipeline. Simply place your custom tenant translation files inside the tenant's asset directory:
tenants/
├─ client-a/
│ └─ assets/
│ └─ locales/
│ └─ en.jsonDuring whitebrand build client-a, Whitebrand seamlessly syncs the locales/ directory into your framework's public output directory, overriding the baseline translations cleanly without tightly coupling to specific i18n frameworks.
11. Known Constraints & Strict Limitations
Whitebrand is an exceptionally powerful tool, but it is bounded by its static analysis architecture. Violating these constraints will result in broken builds.
11.1 Dynamic String Concatenation & Interpolation
The AST extraction engine strictly targets static StringLiteral, NumericLiteral, and static TemplateLiteral nodes. If your application computes values dynamically at runtime, Whitebrand cannot abstract them automatically.
Unsupported Architecture (Will NOT be abstracted):
const environment = process.env.NODE_ENV;
const apiBase = `https://api.${environment}.com`; Required Manual Refactor:
// Define both explicit URLs in the tenant configuration
const apiBase = isProd ? getConfig().api.prod : getConfig().api.dev;11.2 Divergent User Interfaces
Whitebrand assumes that the logical underlying DOM tree and application state machine are identical across all tenants. It exists to abstract data and styling, not component logic.
If Tenant A requires a sidebar navigation model, and Tenant B requires a bottom-tab navigation model, Whitebrand is the wrong tool. In such cases, standard component-level branching or separate repositories should be utilized.
11.3 Backend Multi-Tenancy
Whitebrand is strictly a frontend compilation and runtime orchestration layer. It does not provide mechanisms for:
- Database Sharding
- Row-Level Security (RLS) policies
- JWT Tenant Claims validation
- Backend API tenancy isolation
These must be implemented independently in your backend architecture.
12. Troubleshooting & Support
If you encounter unexpected behavior during a rewrite or dev execution:
- Check the Confidence Scores: Run
whitebrand rewrite --dry-runand inspect the output. Low confidence scores often indicate that themapping.jsongrouped incompatible AST nodes together. - Execute Doctor: Run
whitebrand doctorto verify that your.whitebrand/internal cache hasn't been manually corrupted or modified. - Verify Git State: Always ensure your working tree is clean before running
rewriteso thatgit checkout .remains a viable fallback ifwhitebrand rollbackfails.
13. Frequently Asked Questions (FAQ)
Performance: How does the engine handle massive codebases (10,000+ files)?
Honestly: AST parsing via ts-morph is inherently memory-intensive. For enterprise codebases exceeding 10,000 files, running a global whitebrand extract in a single pass will likely exceed the default Node.js V8 memory limit.
Solution: You must execute the process with expanded memory allocation (NODE_OPTIONS="--max-old-space-size=8192" npx whitebrand extract) or utilize the --include flag to extract iteratively by bounded contexts (e.g., extracting src/auth/ then src/dashboard/).
Monorepo Support: Does this work with Nx, Turborepo, or Lerna?
Yes, but with strict scoping rules. Whitebrand must be initialized (npx whitebrand init) inside the specific frontend application workspace (e.g., apps/web), not at the monorepo root. The Vite/Next.js runtime adapters and config generation rely on being adjacent to the actual framework's package.json and bundler configurations.
How does Whitebrand handle CSS-in-JS (styled-components, Emotion, Tailwind)?
Whitebrand extracts based on the TypeScript AST.
- Styled-Components/Emotion: It effortlessly parses and extracts literals inside tagged template literals (e.g.,
styled.div`color: #FFF;`) and object styles (sx={{ color: "#FFF" }}). - Tailwind CSS: Whitebrand does not extract Tailwind utility classes (e.g.,
text-blue-500). Tailwind relies on predefined classes, not string literals containing raw values. To whitelabel Tailwind, use Whitebrand to extract the values driving yourtailwind.config.jstheme file, not the inline classes themselves.
Is support for Vue.js or Angular planned?
No. Whitebrand's extraction engine is deeply coupled to the internal TypeScript Compiler API via ts-morph. While this works flawlessly for React, Next.js, and React Native (where JSX/TSX is natively supported by the TS AST), Vue Single File Components (.vue) and Angular HTML templates utilize entirely distinct, proprietary template compilers. There is currently no roadmap to build custom AST parsers for Vue or Angular
14. Deep Technical Audit & Brutally Honest Q&A
For enterprise architects evaluating Whitebrand, here are the unfiltered, highly technical realities of the engine.
AST & Rewriting Mechanics
1. How do you handle static strings vs template literals?
const title = "Login";-> Supported. Extracted as aStringLiteral.const title = \Login`;-> **Supported.** Extracted as aNoSubstitutionTemplateLiteral`.const title = \Login ${name}`;` -> UNSUPPORTED. Dynamic template literals are skipped entirely. Whitebrand cannot deterministically abstract logic evaluated at runtime.
2. JSX Text vs JSX Expressions (<Text>{"Login"}</Text> vs <Text>Login</Text>)
They produce the exact same fingerprint. ts-morph normalizes both as JSX string literals, resulting in identical technical semantics.
3. Object Key Collision ({ title: "Login" } vs { label: "Login" })
They do not collide. The AST ancestorChain traces the exact property assignment (PropertyAssignment[name='title'] vs PropertyAssignment[name='label']). They generate distinct fingerprints.
4. How does the engine handle massive collision (e.g., 50 <Text>Save</Text> components)?
Fingerprint hashing includes the absolute file path, AST structure, and occurrence index. If <Text>Save</Text> appears 50 times in 50 different files, the unique filePath ensures 50 unique fingerprints. If it appears 50 times in the same file, the unique occurrence index differentiates them.
5. Does moving a string to a completely different file change its ID?
Yes. Because filePath is part of the hash, moving a string to a new file makes it a completely new node.
6. Does reordering components in the same file break the fingerprint? No. Fingerprinting is resilient to vertical line shifts. The hash relies on the component's internal tree depth, not its visual line number.
7. Do you rely on line numbers at all?
No. Since v1.2, line numbers are completely removed from the matching mechanism. They are only saved in registry.json as metadata for the Studio UI so humans can click and find the string.
8. What is the rewrite success rate after running prettier --write .?
100%. Prettier only alters whitespace. It does not alter the underlying Abstract Syntax Tree structure. The ancestor chains remain mathematically identical.
9. What are --include and --exclude? How do they affect Cache Invalidation?
The --include and --exclude flags allow you to run AST extraction on specific glob patterns (e.g., --include src/auth/**/*).
When you run a partial extraction, Whitebrand performs Intelligent Cache Invalidation. It only purges nodes from registry.json that belong to the newly targeted files. Nodes from un-targeted files remain completely intact in the cache.
10. Is AST scanning single-threaded or does it use Parallel Scanning?
Single-threaded. ts-morph wraps the internal TypeScript compiler, which relies on a massive shared memory graph. It cannot be safely parallelized across threads without losing cross-file semantic context.
11. How does Incremental Scanning work?
When you modify a codebase and re-run extract, the engine doesn't blindly wipe the registry. It hashes the file contents. If a file's hash hasn't changed, it skips the file (Incremental Scanning). If the file changed, it surgically invalidates the old nodes from that specific file in registry.json and pushes the newly extracted nodes.
12. Is rewrite completely idempotent?
Yes. The AST extraction explicitly ignores nodes that are already MemberExpressions originating from a getConfig() call. Re-running rewrite twice will not rewrite already rewritten code.
13. Why use ts-morph over @babel/parser or oxc (which is 10x faster)?
While oxc and swc are vastly superior for raw parsing speed, their AST mutation APIs are extremely low-level and optimized for bundlers, not high-level refactoring. ts-morph provides an incredibly rich, mutable wrapper around the TypeScript compiler. It allows Whitebrand to surgically modify the AST and emit the code while perfectly preserving original formatting, whitespace, and comments. We chose mutation reliability and developer velocity over raw parsing speed. There are no current plans to rewrite the engine for oxc.
The Confidence Engine
14. How is Confidence actually calculated? Is there a real equation? Confidence is calculated using strict weighting:
- 50%: Exact match of
technicalSemantic(e.g.,JSXTextvsStringLiteral). - 30%: Exact match of the immediate
parentKindin the AST. - 20%: Exact parity of the
ancestorChaindepth. If nodes grouped by AI have wildly different technical semantics, the score drops drastically.
15. Give a real example of a 95 confidence mapping that was WRONG.
A user mapped the generic string "Cancel" to BUTTON_LABELS. However, "Cancel" was also used as a hidden internal state enum (status === 'Cancel'). Both were simple StringLiterals with similar depths. The engine gave it high confidence. It broke the app state when rewritten.
16. Is confidence actually used during rewrite?
Yes. When you run whitebrand rewrite --strict, the engine actively reads the confidence score. If any mapping group scores below 80, the CLI throws a fatal error and refuses to rewrite.
The AI Layer & Scale Constraints
17. How do you handle Context Overflow (e.g., 15,000 literals)?
If you feed 15,000 literals to suggest, it will exceed standard LLM context windows. Whitebrand does not natively chunk AI prompts yet. You must chunk manually using the --include flag (e.g., extracting and mapping src/auth first, then src/dashboard).
18. What is the RAM usage during extraction?
Parsing 300 files consumes approximately ~1.5GB of RAM. A 10,000-file project will crash standard Node memory limits unless executed with NODE_OPTIONS="--max-old-space-size=8192".
Tenant Architecture & Maintenance
19. How does whitebrand migrate actually work?
When your mapping.json changes (e.g., you extract a new color), the schema updates. migrate loops through all tenant config.json files and deep-merges them with tenants/default/config.json. The default tenant acts as the master fallback, providing the initial value for the new secondaryColor key.
20. What happens if a client manually deletes a key from their config?
whitebrand validate will throw a hard failure (Exit Code 1). However, at runtime, getConfig() does NOT deep merge with defaults for performance reasons. The app will likely crash. This is why validate must run strictly in your CI pipeline.
21. How do you prevent Config Drift across dozens of tenants over a year?
There is no background auto-sync daemon. You must proactively run whitebrand migrate across your tenants whenever the central schema changes.
22. How does build-all execute locally? Sequential or Parallel?
The CLI build-all command executes strictly Sequentially via a simple for loop to prevent RAM starvation locally. Parallelization must be handled by external CI matrix jobs (e.g., GitHub Actions / GitLab).
23. Is the tenant config lazy-loaded at runtime?
No. The entire config.json is bundled and injected synchronously into the frontend memory. If your config hits 5MB, you are misusing the tool to store database records instead of branding tokens.
Assets & Extensibility
24. Does the scanner extract static image imports like <Image source={require('./hero.png')} />?
No. The AST scanner does not abstract local file requires or imports. Whitebrand manages dynamic assets entirely at the file-system level by syncing files from tenants/<id>/assets/ directly into the public directory at build time.
25. Is there a Plugin System (e.g., whitebrand-plugin-shopify)?
No. Whitebrand uses internal adapters for Vite, Next.js, and Expo, but there is currently no generic architecture to hook into third-party CMS providers or backend platforms.
Studio Dashboard
26. What exactly can Studio do?
Studio allows visual JSON editing of the tenant configs (enforcing schema compliance). It shows timeline logs and spawns dev/build processes. It does not visually edit the mapping.json, nor does it show test coverage or AST diffs.
The Ejection Protocol
27. How robust is Eject? Does it trace variables (const theme = config.theme)?
No. The current eject traversal algorithm expects inline resolution (<Button color={getConfig().theme.primaryColor} />). If you assign config values to intermediate variables, eject will fail to substitute them and leave dead code.
28. What is the actual success rate of eject?
~85% on standard projects. Deeply destructured variables will require manual cleanup post-ejection.
Business Realities
29. What is the biggest problem a real user faced?
Next.js App Router aggressively caching the process.env.WHITEBRAND_TENANT variable across dev server reloads, causing the wrong tenant branding to appear until the cache was wiped.
30. How long does it take to convert an existing project? For a 300-file SaaS app, expect 3 to 4 hours. The AST extraction takes seconds, but cleaning up the AI's mapping, resolving dynamic string concatenations, and fixing broken variables takes hours of manual engineering work.
License: MIT License
Maintainer: Alem Mohamed Sohaib
