Athos Front-End Build Kit — RBD (ready-to-place markup + binding spec)
Companion to: athos-frontend-integration.md (the plan) — this file is the concrete markup/snippets to drop into the cloned SuiteCommerce theme.
Deploy target: NetSuite Sandbox account first (acct 4582045 = prod; Sandbox has its own id).
Confirmed bindings (from athos_product_feed.js + feed CSV, 2026-07-10):
- PDP SKU = item's
itemid(e.g.01666401A) — NOT internal id, NOT rbd_item_id. - Category id = category External ID (numeric, e.g.
1191) — NOT the name, NOT the SC internal id. ⚠️ availability of External ID in the SC front-end model is UNVERIFIED (see §Binding risks).
Dynamic values below are written as
«PLACEHOLDER». The exact SuiteCommerce template handle for each (e.g. howitemidis exposed in the PDP view context) must be confirmed against the cloned theme's actual template context — don't assume the handle name until the theme is pulled.
1. Global Athos script — every page (before </head>)
<script type="text/javascript" src="https://snapui.athoscommerce.io/atqzs8/bundle.js" id="athos-context"></script>
1b. Category pages — same tag + category External ID
<script type="text/javascript" src="https://snapui.athoscommerce.io/atqzs8/bundle.js" id="athos-context">
category = { id: "«CATEGORY_EXTERNAL_ID»" };
</script>
«CATEGORY_EXTERNAL_ID» must resolve to the current category's External ID (matches feed "Category External IDs"). See §Binding risks — this is the hardest binding.
2. Search results page (new URL, keep old page for revert)
- Body element gets class
ss-shopon this page (see §ss-shop toggle). - Injection targets (Athos wipes & replaces everything inside these — keep nothing here):
<div class="facets-facet-browse-facets">
<div id="athos-sidebar" style="min-height: 100vh"></div> <!-- filters -->
</div>
<div class="facets-facet-browse-results">
<div id="athos-content" style="min-height: 100vh"></div> <!-- results -->
</div>
3. Category pages — same injection targets as §2 (no ss-shop class needed; category id comes from §1b)
4. Search form rewrite (ALL forms — desktop header, mobile, any hidden dupes)
On each visible search form:
<form … action="/«NEW_SEARCH_PAGE_URL»/" method="get">- search
<input … name="q"> - remove every
<input type="hidden">inside the form - disable native/plugin autocomplete (SC type-ahead renders over Athos Autocomplete)
- comment out (don't delete) the old form markup for revert
5. Recommendation blocks
«CUSTOMER_ID» = logged-in customer id; omit the whole shopper block if anonymous (never emit id:'' / 'undefined').
Home
<script type="athos/recommendations">
globals = { shopper: { id: '«CUSTOMER_ID»' } };
profiles = [ { tag: 'home', selector: '.ss__recs__home' } ];
</script>
<div class="ss__recs__home" style="min-height: 100px;"></div>
PDP — products: ['«ITEMID»'] where ITEMID = the item's itemid
<script type="athos/recommendations">
globals = { products: ['«ITEMID»'], shopper: { id: '«CUSTOMER_ID»' } };
profiles = [
{ tag: 'bundle', selector: '.ss__recs__bundle' },
{ tag: 'cross-sell', selector: '.ss__recs__cross-sell' },
{ tag: 'similar', selector: '.ss__recs__similar' },
{ tag: 'recently-viewed', selector: '.ss__recs__recently-viewed' }
];
</script>
<div class="ss__recs__bundle" style="min-height: 100px;"></div>
<div class="ss__recs__cross-sell" style="min-height: 100px;"></div>
<div class="ss__recs__similar" style="min-height: 100px;"></div>
<div class="ss__recs__recently-viewed" style="min-height: 100px;"></div>
Cart
<script type="athos/recommendations">
globals = { shopper: { id: '«CUSTOMER_ID»' } };
profiles = [ { tag: 'view-cart', selector: '.ss__recs__view-cart' } ];
</script>
<div class="ss__recs__view-cart" style="min-height: 100px;"></div>
404 ⚠️ use .ss__recs__404 on the div (Athos doc ships a placeholder [profile name] bug)
<script type="athos/recommendations">
globals = { shopper: { id: '«CUSTOMER_ID»' } };
profiles = [ { tag: '404', selector: '.ss__recs__404' } ];
</script>
<div class="ss__recs__404" style="min-height: 100px;"></div>
No-results — nothing to build (Athos-hosted template); verify preview in UAT.
ss-shop body-class toggle (§2)
The new search page's <body> needs class ss-shop. In a SC theme this is a small JS addition on that route (or a body-class hook in the page template) — exact mechanism TBD against the cloned theme.
PLACEMENT MAP (against fetched RBD_Theme — SC platform 2026.1, theme built by Folio3 on 2018.1 templates)
Active theme = RBD_Theme v1.0.4. Overrides/ is empty (no existing template overrides — clean slate). Platform has Site Management Tools (SMT v3), so static rec blocks can go via SMT content areas instead of theme edits.
| Athos piece | Mechanism | Exact target | Notes |
|---|---|---|---|
Global bundle.js head script |
THEME override (or GTM/Commerce config — Q2) | theme shell/head | loads every page before Athos markup |
| Search form rewrite | THEME override | SiteSearch@sco-2018.1.0/Templates/site_search.tpl |
form action="/search"; input is subview data-view="ItemsSeacher" (type-ahead to disable). Add plain <input name="q">, repoint action |
| Search + category results injection (destructive) | THEME override | Facets@sco-2018.1.0/Templates/facets_facet_browse.tpl |
#athos-sidebar inside .facets-facet-browse-facets, #athos-content inside .facets-facet-browse-results. ONE template serves both via isCategory |
| Category identifier | THEME override + OPEN | category head / facets_browse_category_heading.tpl |
⚠️ External ID NOT in theme context — see Binding risk #1 |
| PDP dynamic product key | THEME override | ProductDetails@sco-2018.1.0/Templates/product_details_full.tpl |
context lists model.item.internalid; itemid is in the item model (used by Product.Sku) — surface via small view/context |
| PDP rec blocks | THEME (dynamic itemid) / SMT (static divs) | PDP data-cms-area slots product_details_full_cms_area_5..8 |
static .ss__recs__* divs SMT-able; dynamic itemid global still theme |
| Home recs | SMT | homepage content area | static — no theme edit |
| Cart recs | SMT or theme | cart content area | static — SMT if a cart cms area exists |
| 404 recs | SMT ✅ | error_management_page_not_found_cms_area_1/_2 |
confirmed cms areas — no theme edit |
Bottom line: destructive search/category injection + search-form rewrite + PDP/category dynamic identifiers = theme overrides (unavoidable). Home/404 (and likely cart) rec blocks = SMT, no code deploy.
Binding risks (resolve against the cloned theme before writing final overrides)
- ⚠️ Category identifier — OPEN, gating item. External ID is NOT in the theme templates/context (only breadcrumb SCSS refs); it lives in SC's JS category model, not in the theme fetch. Resolution paths: (a) ask Athos how their bundle IDs the current category on SuiteCommerce (URL? global var we set? SC model read?) and whether it keys on our feed's External ID or another id; (b) if only internal id/URL is reliably available client-side, re-key the feed's category column (feed Suitelet source in hand) from External ID → SC internal category id. Blocks category head binding (§1b). → route as a question to Searchspring/Katie.
- ✅ PDP
itemid— RESOLVED path:product_details_full.tplcontext exposesmodel.item.internalid;itemidlives in the same item model (theProduct.Skuview renders it), so surface it via a small custom view/context in the PDP override. No blocker. - ✅ Customer id — modern SC exposes the logged-in profile via
SC.ENVIRONMENT/profile model; read internalid there, omit theshopperblock for guests. Confirm exact field when writing the override. No blocker.
Feed-side item (not front-end, but affects UAT)
29% of feed rows (all -ROT/variant SKUs) have empty categories in saved search 988 → they won't appear in category browsing/recs. Decide whether variants should inherit parent categories before UAT.
~/ai-projects/mission-control/plans/athos-frontend-build-kit.md