Search rollout
The search overlay existed. Getting it onto every eligible storefront was its own project. I wrote a TypeScript CLI that installs it through the loader each site already runs, without touching a single brand site, and dry-runs by default.
- 200+brands live, all but one
- 7commands, dry-run default
- 8status classes per brand
- ~1.5klines TypeScript, no build step
- Aug2026
Roll search out to an invented fleet
Run Discover, Plan, then Apply --apply and Verify. Click a brand to see its config diff and backup, or roll one back.
Problem
Installing a storefront script by hand on hundreds of brands means hundreds of chances to break someone's live site.
Each brand had its own search config, its own set of on-site widgets and sometimes the old search running unconditionally. Some configs were disabled, some search indexes were empty, some input selectors no longer matched the live site. Turning a shared status flag on would also switch the old search back on for every visitor.
My role
I designed and wrote the tool, ran the pilot, then the full rollout, and documented the traps it found. It talks to existing panel endpoints; nothing on the storefronts changed.
discoverscans every customer id, checks search health and inventories existing widgetsplanwrites a diff and sends nothing to productionapplystays a dry run until--apply, backs up each brand, writes, then reads backverifychecks config, widget, script host and search results independentlydeconflict,reportandrollback --confirmfor the edge cases
Brand by brand, reversible at every step
- DiscoverClassify every brand: ready, stale-selector, loader-unconfirmed, search-empty, disabled and more.
- PlanDiff for ready brands only. No requests to production.
- ApplyBackup, merge into the full config object, write, read back.
- Existing loaderThe widget loader each site already runs picks up the new search widget.
- Verify + reportIndependent checks and a one-file HTML report with test links.
Violet tint: parts I wrote.
What was hard and what I did
Safe by default
apply without --apply is still a dry run. Real writes take a flag and can be limited to a few brands with --limit or --ids, so a pilot runs on a handful of brands before the rest.
Never overwrite a brand's own work
The save endpoint replaces the whole config object, so the tool always reads, merges and posts the full object. Existing brand CSS is never overwritten, the old search CSS is never touched, and a disabled brand is never switched on silently.
One flag, two products
The old and new search read the same status flag. Turning it on for the new overlay would expose the old search to every visitor on some brands, so that path is off unless you pass --allow-v1-exposure, and those brands are listed instead.
Verify separately from apply
A read-back proves the write landed. verify proves the site works: the script host actually serves the file, and the search endpoint still returns products. A subdomain copied from an old widget once turned out not to exist in DNS.
Old widgets that fight the new one
Some brands ran their own old search widget on every page, so on the demo link both bound to the same input. deconflict adds a URL rule that disables the old one only on the demo link; normal visitors see no change.
Write down the traps
The loader caches the widget list for the whole session, so a test link opened in an old tab shows nothing. The pilot hit exactly that. The README now says to test in a new tab, with the reason.


Notes on this post
Join in
Leave a comment.
Sign in to add your note to this post.
Only your name and avatar are used.