01TL;DR
Search drives 32.1% of all sessions — ~10× the browse landing. HawkSearch already powers it, but renders through Hawk's Handlebars templates plus a hawksearch-search-results web component that carries its own shadow DOM — so Caster's structural classes can't reach inside, and the result looks nothing like the redesigned site.
The fix splits by surface: own the entry surfaces as native Caster (hero search, autocomplete, machine lookup — calling Hawk's API), and skin the results surfaces in place (override Hawk's Handlebars templates + a .hawk-results-scoped Caster skin). Fix the searchRequest race as code hygiene.
| Phase | Surface | Effort |
|---|---|---|
| Phase 1 Front door | Native Caster hero search, autocomplete panel, and machine-lookup affordance, calling Hawk's suggest/search API. Fix the searchRequest null-reference race. Drop a token-level .hawk-results skin on the existing SERP. | Medium — Caster front-end + one theme-JS bug fix |
| Phase 2 Reclaim SERP | Full Hawk Handlebars-template override: results render Caster .product-cards; facets render the Caster accordion + removable chips + pagination. Compatibility-aware via compatible_models[]. | Higher — template override + content ops |
| Phase 3 Replace rendering | Swap Hawk's Handlebars UI for its React/headless SDK as native Caster components (keep Hawk's API/index). Personalized ranking for signed-in fleets + AI/concept facets. | Highest — Catalyst-replatform candidate |
02Current state
The integration is more controllable than first assumed — three corrections carry through the rest of this brief:
- Vendored, not CDN.
hawksearch-handlebars-uiis committed into the theme atassets/js/hawksearch/and webpack-built (env varsWEBPACK_HAWKSEARCH_*). Entry point:assets/js/hawksearch/index.js, run fromapp.js. - The theme already overrides Hawk's templates.
index.jsregisters theme-owned Handlebars templates for every major component —search-results,search-results-item/-list,facets-list,autocomplete,search-field,sorting,page-size(inassets/js/hawksearch/templates/*.hbs). The header search is<hawksearch-search-field>(native BC quick-search is commented out). We already control the markup. - Shadow DOM is not a blocker — there's a sanctioned injection point. Hawk renders into
hawksearch-*web components (some with shadow DOM), but the init passescss: { customStyles: 'hawksearch-custom-styles' }, andhawksearch-custom-styles.htmlis a<template>whose<style>opens:host, :root { --hawksearch-color-accent: #00209F; … }— i.e. it is adopted inside the shadow roots. Any CSS placed there, Caster's included, reaches inside the encapsulation.
Net: bringing search under Caster is concentrated work in two places — the .hbs templates (markup → Caster classes) and hawksearch-custom-styles (CSS → Caster tokens/components) — plus the searchRequest null-guard. It is not a fight against encapsulation.
USA Clean's /search is powered by HawkSearch (Bridgeline Digital), via the vendored @bridgeline-digital/hawksearch-handlebars-ui library (committed in the theme, webpack-built) wired into the BigCommerce Stencil theme. It renders through theme-owned Handlebars templates mounted inside a tree of hawksearch-* web components — the /search page mounts <hawksearch-search-results>, which contains hawksearch-facets-list, hawksearch-search-results-list, hawksearch-autocomplete, hawksearch-sorting, hawksearch-pagination, and the theme's own pagination-summary element (which does carry its own shadow DOM).
What's wrong today:
- It's visually foreign. Hawk injects its own component CSS late in the page (its own
.button, its own card markup). The Caster site stops at the edge of search results and a different design language takes over. The stencil-integration doc already flags this and prescribes.hawk-results .btn { … }scoping. - A known race condition blanks the grid. The theme's
partSearchLinksreadsHawkSearch.searchRequestbefore async init resolves (Cannot read properties of null, 251 sessions). On a cold/searchload Hawk counts 268,271 results but renders zero. Limited real-world impact, but a real bug. - The front door is generic. The homepage leads with browse CTAs, not search — despite the 9.8× search:browse ratio. Autocomplete is Hawk's stock suggestions, not tuned to part number / brand / machine model.
- There's no machine-lookup intercept. The dominant job is "I have a Tennant T5, I need its parts," but nothing captures a brand+model at the point of search. Hawk has the data; the UI doesn't expose it.
- Hawk contributes to CLS (0.29, above Google's 0.25 "poor" threshold) by injecting results after first paint.
Search is already the navigation; the redesign should make search feel like the rest of the site and meet the brand→model mental model head-on.
03References
Grainger
Best-in-class industrial autocomplete: as you type, the panel splits into suggested terms, categories, and product previews with thumbnails + price. The model to emulate for the Caster autocomplete panel — grouped, scannable, keyboard-navigable.
McMaster-Carr
The gold standard for industrial faceted search: instant results, server-fast facets, no full-page reload, dense scannable rows. Sets the bar for what "reclaiming the SERP" should feel like — Hawk's engine can approach this; its stock UI does not.
Sweepscrub
Parts search scoped to cleaning equipment by brand→model. Same catalog shape as USA Clean; their search is a flat filtered list with no machine intercept — the gap our machine-lookup affordance closes.
Tennant.com (OEM)
Model-scoped search routes to a spec/doc page but has no parts-purchase path. Confirms the brand→model intent is universal; USA Clean's opportunity is to be the rich, buyable search destination for every machine.
Baymard Institute — B2B search & autocomplete
B2B research shows part-number / SKU search and "scoped search" (search within a machine's compatible parts) are patterns buyers expect. Autocomplete that previews products, not just query strings, measurably reduces abandonment.
The search-app comparison class — Algolia / Klevu / Searchspring
The peer set for HawkSearch. Relevant only to confirm that swapping the engine is not warranted (see shortlist): Hawk's relevance/merchandising/facets are competitive; the deficiency is the front-end skin, which is ours to fix.
04What BC Stencil gives us
- HawkSearch is already integrated and paid for. The engine (index, relevance, facets, synonyms, "did you mean," keyword redirects, recommendations, merchandising/pinning, analytics) is configured in the Hawk dashboard and serves the
/searchtemplate. No engine work needed. - Hawk's Handlebars UI is template-overridable.
@bridgeline-digital/hawksearch-handlebars-uirenders from Handlebars partials we can override, and accepts supplemental CSS. This is the hook for the Phase 2 Caster skin. - Hawk's suggest/search API is callable directly. The autocomplete and machine-lookup surfaces (Phase 1) can query Hawk's API and render our own Caster markup — we don't have to accept Hawk's stock suggestion UI.
/searchStencil template override —templates/pages/search.htmlis ours to control for the page chrome around Hawk's component.- Product custom field
compatible_models[](the same field that powers model-landing) lets results and facets be compatibility-aware — "parts that fit your Tennant T500e" as a Hawk facet or scoped search. - Storefront API for supplemental product data the result cards need (stock, price tiers).
05Stencil limitations
- Shadow DOM is encapsulated, but the theme has a sanctioned styling channel. Global
components.cssand a.hawk-results .btn {…}scope do not reach inside Hawk'shawksearch-*components. The path that does work is already wired: author CSS into thehawksearch-custom-stylestemplate (adopted into the shadow roots) and edit the.hbstemplates for structure. The real cost is that Caster's search CSS lives in that Hawk-specific template, parallel tocomponents.css— not that styling is impossible. - Two templating systems to maintain. Search markup lives in
assets/js/hawksearch/templates/*.hbs, separate from Stencil's page templates. Already true today; porting to Caster edits an existing system rather than adding one. - Bespoke autocomplete groups need API-level work.
search-autocomplete.hbsalready groups suggested-queries / categories / content / products — restyling those is template + CSS work. Groups Hawk's response doesn't provide (e.g. recent / saved machines for signed-in fleets) require joining the account to the suggest call — custom front-end beyond a restyle. - No machine-lookup intercept in stock Hawk. Brand+model → scoped parts is a custom affordance on top of Hawk's search API.
- The
searchRequestrace is theme-JS, not Hawk. Confirmed atassets/js/hawksearch/index.js:173, inside the theme'spagination-summaryshadow element:if (HawkSearch.searchRequest.query)runs beforesearchRequestresolves on cold loads. Fix =HawkSearch.searchRequest?.query. (That heading is also hard-codedfont-size:25px; font-weight:700inline — a Caster-token opportunity.) - CLS from late injection. Reserving space for
<hawksearch-search-results>(min-height / skeleton) is a theme-template fix.
06App marketplace shortlist
The usual "native vs. app vs. custom" table is inverted here: HawkSearch is the app, and it's already deployed. The real decision is what to do with its front end.
| Option | What it is | Verdict |
|---|---|---|
| Skin Hawk in place | Edit the theme's .hbs templates + the shadow-injected hawksearch-custom-styles. The theme already owns both — port them to Caster. | ✓ Already the architecture |
| Own the entry surfaces as native Caster | Custom Caster front end (hero, autocomplete, machine lookup) on Hawk's suggest/search API. | ✓ Phase 1 path |
| Swap the search engine (Klevu / Searchspring / Algolia) | Replace HawkSearch with a different search app. | Skip — engine isn't the problem |
| BC native faceted search | Drop Hawk, use Stencil's stock faceted search. | Skip — capability downgrade |
| Replace Hawk's rendering (React/headless SDK) | Keep Hawk's API/index; render results as native Caster React components. | ⏳ Phase 3 / Catalyst |
Swapping engines carries a recurring new-subscription cost plus a large migration; the front-end skin is a one-time build against an engine we already pay for. The custom entry surfaces are a one-time build whose payback is immediate (the front door of a 32%-of-sessions surface) — no subscription competes with them.
07Caster impact
New patterns introduced inline in v2/ first (Rule #7), promoted to Caster when a second consumer arrives:
.search-autocomplete— combobox/suggestions panel: grouped sections (products with thumb+price, categories, popular searches, recent machines), keyboard-navigable, built on the existingdropdown.*tokens..search-hero— search-dominant hero block with model-aware placeholder and inline scope chips..facet-group— collapsible accordion filter group (the gap between Caster's.checkboxand a real facet rail)..filter-chip— removable applied-filter chip (× to clear) — a.pillvariant with a remove affordance..pagination— page controls / load-more (Caster has none today)..input--search— input with a leading magnifier icon (Caster's.inputhas no leading-icon slot)..facet-drawer— off-canvas mobile facet panel (37% of traffic is mobile)..hawk-resultsskin — the scoping convention from stencil-integration.html:.hawk-results { --caster-…: … }to pass tokens across the shadow boundary, plus.hawk-results .btn { … }for non-encapsulated overrides.
Reused as-is: .input / .input-group, .product-card, .pill, .stock-badge, .checkbox, .tabs, .container, .site-header__search, .machine-card.
Downstream impact: the autocomplete panel and .input--search also serve the global header search on every page; the facet patterns serve any future filtered listing. These graduate to Caster quickly because they have multiple consumers by design.
08Phased recommendation
Ship the three entry surfaces as native Caster, calling Hawk's API; fix the race; stop the SERP from clashing.
- Elevated hero search (roadmap #8) — search input as the dominant homepage element, model-aware placeholder, optional scope chips (All / Parts / Machines).
- Caster autocomplete panel — grouped suggestions: products (thumb + SKU + price + stock), categories, popular searches, recent/saved machines. Full keyboard + ARIA combobox semantics.
- Machine-lookup affordance — brand-select + model/serial entry routing to a compatibility-scoped result set (and the model-landing page when one exists). Shares the megamenu "Find by machine" story.
- Bug fix — guard
HawkSearch.searchRequest/ movepartSearchLinksto thehawksearch:search-completeevent; reserve result-area height to cut CLS. - Token-level
.hawk-resultsskin — pass--caster-*into Hawk's shadow DOM so the SERP adopts Caster color/type immediately.
What "winning" looks like: higher search-initiation rate from the homepage, climbing autocomplete-selection rate, machine-lookup usage, and the cold-load blank-grid error going to zero.
Override Hawk's Handlebars templates so results and facets render as Caster:
- Result cards →
.product-card(with compatibility note whencompatible_models[]matches the user's fleet). - Facet rail →
.facet-groupaccordion +.filter-chipapplied-filter row +.pagination. - Mobile →
.facet-drawer. - Compatibility-aware results: a "fits my equipment" Hawk facet driven by
compatible_models[].
Trigger: Phase 1 is live and the token skin proves the SERP is the remaining seam; merch has begun populating compatible_models[] (shared with model-landing Phase 2).
Swap Hawk's Handlebars UI for its React/headless SDK, rendered as native Caster components (Hawk's API/index unchanged). Adds personalized result ranking for signed-in fleets ("parts your fleet has bought for this model first") and AI/concept facets.
Catalyst-replatform candidate — see below.
09Implementation notes
Where the Caster work lands (confirmed file map)
The whole search redesign is two files of theme work plus a one-line fix:
- Markup → Caster classes/structure:
assets/js/hawksearch/templates/*.hbs—search-results.hbs(SERP layout),search-results-item.hbs(result card →.product-card),search-facets-list.hbs(facet rail → accordion),search-autocomplete.hbs(grouped panel),search-field.hbs(input). - CSS → Caster tokens/components:
templates/usac/components/hawksearch-custom-styles.html— the<style>adopted into the shadow roots. Bridge--hawksearch-*to Caster values (e.g.--hawksearch-color-accent: var(--caster-color-brand-default)) and add the.product-card/ facet / autocomplete CSS here (not in globalcomponents.css, which can't reach the shadow DOM). Pull Caster tokens in via@importor by inlining the token layer into this template. - Bug fix:
assets/js/hawksearch/index.js:173→HawkSearch.searchRequest?.query. - The header search (
<hawksearch-search-field>) and autocomplete are the same component pair site-wide, so a single restyle covers the header and any hero placement.
The searchRequest fix
Null-guard HawkSearch.searchRequest?.query in partSearchLinks, or move the call into a hawksearch:search-complete listener so it never runs before async init. Reserve the result container's min-height to cut the post-paint shift.
Autocomplete accessibility
ARIA combobox pattern: role="combobox" input with aria-expanded / aria-controls, role="listbox" panel, aria-activedescendant tracking the highlighted option; full keyboard support (↑/↓, Enter, Esc, Home/End); group headings are non-focusable labels. Debounce the suggest call; show a loading affordance; handle zero-suggestions gracefully.
Compatibility data
Compatibility-aware results/facets read the product compatible_models[] custom field — the same data investment as model-landing Phase 2. Tagging the ~12k-part catalog is the shared content-ops cost; sequence it once for both features.
Analytics
- Search-initiation rate (homepage hero) and autocomplete-selection rate.
- Zero-result query rate (feeds Hawk synonym/redirect tuning in the dashboard).
- Machine-lookup usage and its conversion vs. plain search.
- Search → result-click → PDP → cart funnel; cold-load error count (should hit zero post-fix).
Mobile behavior
Search pinned to the top bar; autocomplete panel full-width below it; facets collapse into the .facet-drawer off-canvas panel (37% of traffic is mobile, and mobile users are disproportionately forced into search because the nav fails at 375px — roadmap #10).
10Catalyst / replatform candidacy
Phase 1 + Phase 2 ship in Stencil. Native Caster entry surfaces calling Hawk's API, a theme-JS bug fix, and a Handlebars-template override are all Stencil-native work. No replatform needed to bring search under Caster.
Phase 3 is the Catalyst case. HawkSearch ships React/headless SDKs that fit a Catalyst storefront far better than its Handlebars UI fits Stencil — rendering Hawk results as first-class React components eliminates the shadow-DOM friction entirely, and personalized server-side ranking (fleet-aware order on first paint) is exactly what Stencil struggles to do without jitter. Combined with the headless roadmap and model-landing Phase 3 personalization, search rendering is a natural anchor for the replatform — but not a reason to replatform on its own. Skinning Hawk in Stencil (Phases 1–2) buys visual consistency now; Phase 3 waits for the personalization + headless forcing function.