Simple Smooth Safe / DocGen / docs / rebranding ← All docs

Rebranding

Renaming the whole project to a different brand/publisher (as was done for the Previous Brand → Simple Smooth Safe move) is a single config-driven command, not a manual find-and-replace. This keeps it repeatable for other repos.

How it works

tools/rebrand.mjs applies one ordered replacement map to three things at once:

  1. File contents — every git-tracked text file (minus excludes).
  2. File & folder paths — the same map is applied to each path string, then git mv renames it. So src/SlDocGen.Api/… and solution/.../sl_documenttemplate/ move automatically; there is no separate rename list to maintain.
  3. The Dataverse publisher block in solution/src/Other/Solution.xml — a special case, because a publisher UniqueName must be prefix-safe (no spaces), so it can't just be the display name.

Because the same map drives content and paths, porting to another project is just a new preset — no code changes.

Usage

npm run rebrand -- --preset sl-to-sss --dry-run   # preview every edit/move
npm run rebrand -- --preset sl-to-sss             # apply it
npm run rebrand -- --config my-rebrand.json       # bring your own map
node tools/rebrand.mjs --self-test                # verify the replacement logic

The tool is idempotent — running it (or --dry-run) after a completed rebrand reports "nothing to change", which doubles as a check that no residual old-brand tokens remain.

Writing a preset / config

{
  // MOST SPECIFIC FIRST — qualified strings before their substrings, so a broad
  // rule never eats a narrow one. ("SL DocGen" before "SLDocGen"; "sl_" last.)
  "replacements": [
    ["Previous Brand LLP", "Simple Smooth Safe"],
    ["Previous Brand",     "Simple Smooth Safe"],
    ["SL DocGen",       "SSS DocGen"],
    ["SLDocGen",        "SSSDocGen"],
    ["SlDocGen",        "SssDocGen"],   // C# namespace / project / assembly
    ["sl-docgen",       "sss-docgen"],  // container image / kebab codename
    ["sldocgen",        "sssdocgen"],   // ACR / lowercased resource names
    ["sl_",             "sss_"]         // Dataverse schema prefix
  ],
  "publisher": {                        // omit if not renaming a Dataverse publisher
    "uniqueName": "sss",                // pull from the target org's publisher table
    "prefix": "sss",
    "optionValuePrefix": "10000",
    "display": "Simple Smooth Safe"
  },
  "excludes": [                         // regexes matched against repo-relative paths
    "^docs/legacy/", "^source-material/", "^node_modules/",
    "(^|/)(bin|obj)/", "\\.(png|jpg|pdf|zip|dll)quot;
  ]
}

Get the target publisher's uniqueName / prefix / optionValuePrefix from the destination environment (e.g. SELECT uniquename, customizationprefix, customizationoptionvalueprefix FROM publisher WHERE customizationprefix = 'sss').

Template look-and-feel is deliberately not a text substitution. Each template centralizes its brand in a single :root token block (semantic roles, not scattered hex), so a visual rebrand is editing those few variables, not hunting hex codes across the file. The templates/practice-pro-365/* group carries the end client's own brand, since those documents go out under the client's name:

:root {
  --brand-primary: #004226;      /* client green */
  --brand-primary-dark: #375623;
  --brand-tint: #EAF2ED;
  --brand-accent: #FFC000;       /* client gold  */
  --font-brand: Arial, Helvetica, "Liberation Sans", "DejaVu Sans", sans-serif;
}

The logo is the client's real mark, inlined as a base64 data URI on .logo img (source: account-statement-openchecks/logo.png). There is no asset pipeline — a template ships to Dataverse as one HTML string — so an image has to be embedded, not linked. Remittance details are literal text in account-statement-openchecks/template.html; see the Usage & Customization guide.

Rebranding this group to a different firm = swap the five :root values, swap the data URI, and update the remittance block. tools/rebrand.mjs does not touch any of them by design.