# Subscribe & Save — Reasoning & Recommendations

**Companion to:** [bundle-concepts.md](bundle-concepts.md), [saved-cart-concepts.md](saved-cart-concepts.md), [recently-purchased-concepts.md](recently-purchased-concepts.md)
**Live preview:** https://demo.thecxlabs.com/v2/pdp.html
**Date:** July 2026

This document explains the recommended Subscribe & Save (auto-ship) pattern for `shop.usaclean.com`, the BigCommerce capabilities and apps that map to it, and a phased path from the PDP affordance already built in the prototype through account-side management to an enterprise / replatform-era program. It is the natural sequel to [saved-cart-concepts.md](saved-cart-concepts.md), whose Phase 3 ("schedule a recurring order") is this feature.

---

## TL;DR

Ship the **PDP Subscribe & Save affordance that's already mocked up** in [`v2/pdp.html`](../v2/pdp.html) — a One-time vs. Subscribe & Save purchase-mode toggle, a delivery-frequency select (Every 30 / 60 / 90 days / 6 months), an expandable terms panel, and an Add-to-Cart button that relabels to "Subscribe & Save" — and pilot **one** subscription app on a narrow set of high-repeat consumables (pads, brushes, squeegee blades, detergents, filters). Everything the buyer sees can ship on Stencil; the recurring engine cannot, because **BigCommerce has no native recurring-billing or scheduled-order capability** — that has to come from an app or custom middleware.

**The single most important thing this brief must resolve before promotion is the discount-interaction rule.** The prototype PDP already shows *two* overlapping discount mechanics side by side — a 10% Subscribe & Save price ($42.40 → $38.16) and a volume tier block (5% at 6–11 units, 15% at 12+) that literally says "stacks across the cart line." Applied naively, a 12+ subscriber would compound to ~23.5% off national-account pricing that's often *already* contract-negotiated. The recommendation is **contract price wins, then greater-of (promo vs. volume), never naive stacking** — and the terms panel already carries a "does not stack" bullet that the live pricing engine must actually enforce.

**The second pivotal filter is Net-30.** Most subscription apps assume a card-on-file auto-charge. USA Clean's national accounts pay on Net-30 invoice terms — for them, "auto-ship" is a *scheduled-order* problem, not a *card-billing* problem. The B2B pattern that fits Net-30 is to **decouple the recurring event from the card charge** — the subscription app generates the order and hands billing to the ERP / a net-terms provider on the buyer's terms (see [Optimum7](https://www.optimum7.com/blog/custom-payment-terms-for-b2b-subscriptions-in-shopify-and-bigcommerce-a-practical-guide.html)). This is an *architectural approach*, not any single app's advertised out-of-the-box feature. Rebillia is a reasonable lead candidate to validate it against, but **confirm net-terms / PO support directly with Rebillia before committing** — it is not stated on their public listing. That filter is what narrows the worth-it-now shortlist.

| Phase | Surface | What it solves | Effort |
|---|---|---|---|
| **Phase 1** _(Pilot)_ | PDP Subscribe & Save affordance (this prototype) + one subscription app on high-repeat consumables | Habitual reorder of wear parts: "ship me pads every 60 days so I stop forgetting" | Medium — UI is built; the app is the new dependency |
| **Phase 2** _(Data-gated)_ | Account-side manage-subscription (skip / reschedule / swap / cancel), standing orders for national accounts, per-category cadence tuning | The terms already promise self-serve management; national accounts want a pre-authorized recurring PO | Medium–High — app portal integration + role gating |
| **Phase 3** _(Future)_ | Catalyst / headless subscription surfaces, or an enterprise program (Ordergroove-class) / consumption-based VMI (KeepStock-style) | Rich stateful management, dynamic price recompute, telemetry-driven replenishment | Highest — replatform-era; only if the program earns it |

> **Why Phase 1 is safe to ship.** The affordance is a faithful UI mock that already lives in the prototype and consumes only existing `--caster-*` tokens — nothing in shared Caster CSS changed. It captures *intent* (mode + cadence). Turning that intent into a real recurring order needs the app, which is the one net-new dependency. The rest is glue.

**Decision of record:** (pending — no client decision yet; see [docs/decisions.md](decisions.md))

---

## Current state

The PDP prototype at [`v2/pdp.html`](../v2/pdp.html) ships a complete, working purchase-mode selector — not a static badge:

- **A purchase-mode radiogroup** (`.buy-mode`, `role="radiogroup"`) with two option cards: **One-time** (default, `.is-selected`) and **Subscribe & Save**. Each card wraps a visually-hidden native radio (still focusable and arrow-navigable), a faux radio dot, a title, and a right-aligned price. The subscribe card carries a "Save 10%" flag pill and a strikethrough price (`<s>$42.40</s> $38.16`).
- **A delivery-frequency select** (`#subFreq`) revealed when Subscribe is chosen: Every 30 days / **Every 60 days (default)** / Every 90 days / Every 6 months.
- **An expandable subscription-terms panel** (`#subTerms`) behind a "View subscription terms" disclosure button with correct `aria-expanded` / `aria-controls`. Its five bullets: (1) 10% applies to every recurring delivery; (2) card charged when each order ships on the chosen cadence; (3) change / skip / cancel anytime, no fee; (4) price excludes tax & shipping; (5) **volume pricing does not stack with the subscription discount**.
- **A relabeling Add-to-Cart button** — `#pdpAtcLabel` swaps from "Add to Cart" to "Subscribe & Save" on mode change, via two tiny vanilla `onchange`/`onclick` handlers.

The price appears in three synced places (the `.pdp-price` block, the `.pill-accent` "↺ Subscribe & Save 10%" badge, and the option-card price).

### What's missing (what the prototype fakes)

A live build has to close four gaps the mockup papers over:

- **The frequency select does not recompute price.** Only the mode toggle wires behavior; changing cadence does nothing to the number.
- **No persistence or cart integration.** The choice isn't recorded anywhere — there's no subscription contract, next-ship date, or line-item cadence field.
- **The no-stacking rule is copy-only.** Bullet 5 is a promise, not an enforced pricing rule. This SKU genuinely shows both a Subscribe & Save price *and* a volume-tier block, so the collision is real.
- **No account-side management surface exists.** The terms promise skip / reschedule / cancel, but there's nowhere to do it yet.

> **Why it matters:** Floor-care is an unusually strong subscribe candidate because the catalog is mostly wear parts on predictable duty cycles. Facility managers already reorder pads and brushes on a rhythm — the feature just removes the "did I forget to order pads?" failure mode. But the same buyers are on Net-30, which means the consumer card-on-file model that every subscription app assumes is the *wrong* default for this audience. Getting the affordance right is easy; getting the billing model and the discount math right is the actual work.

---

## References

What Subscribe & Save / auto-ship looks like across the distributors and consumer gold-standards worth lifting from, ordered by usefulness to USA Clean.

### Staples AutoRestock — the closest direct analog

A PDP-level subscribe affordance presented as an alternate purchasing option on the product page, with a tiered save-more-when-you-subscribe-more discount: **5% off for 1 subscribed item, 10% off for 2+**. Free delivery on AutoRestock orders; pause / skip / cancel anytime. Critically for multi-site accounts, it supports **multiple subscriptions each with a different address, payment method, and schedule**, and exposes dual entry points — the PDP option *and* a "Lists → Auto Restock" account hub. This validates USA Clean's inline PDP toggle and argues directly for a companion account-level "Manage subscriptions" surface (Phase 2) plus multi-address support.

### Amazon Business Subscribe & Save — the consolidation-tier + billing model

A two-tier stacking discount: **~5% base, up to 15% when 5+ subscriptions arrive the same day to the same address** — an explicit incentive to batch a site's consumables into one delivery. The frequency picker is a single editable "Auto-delivered: [frequency]" link opening one panel to change quantity, cadence, and next-delivery-date together; cadence spans 2 weeks to 6 months; skip is one click with no penalty. The **price charged is the price on the day the order processes**, not locked at signup. Two lifts for USA Clean: a "ships-together" discount tier maps beautifully to a fleet buyer ordering pads + brushes + squeegees for one building, and the price-at-processing-time model is the honest billing semantics to adopt.

### Zoro Order Subscription — the B2B-gating + bounded-run precedents

Zoro's auto-replenishment is **gated to Business Account customers**, with a coarser cadence set (weekly / bi-weekly / monthly) and — distinctively — customer-set **start and end dates** (bounded runs, not open-ended). It's framed around avoiding production downtime, not savings. Two B2B design cues: gating subscribe behind an authenticated Pro/Net-30 account is a legitimate choice, and start/end bounding suits project- or season-bound facility contracts.

### Grainger KeepStock — the contrast case (what we are NOT building yet)

KeepStock is **not** a PDP subscribe toggle — it's a service-tiered inventory program (Onsite / Managed / VMI / vending / bin-label) where reorder is triggered by min/max thresholds and consumption scanning, not a customer-set calendar. The mental model is *replenishment-to-threshold*, not *deliver-every-N-days*. Worth citing precisely to keep the two distinct: a calendar-cadence Subscribe & Save is the light-touch self-serve entry point; a true consumption/VMI program is a separate, heavier Phase 3 offering. Don't conflate them on the PDP.

### Chewy Autoship — the consumer UX gold standard

Cited purely for the cadence/skip/manage UX and one strategic split: a large first-order hook (~35% off, capped) then a modest ongoing discount (~5%). Management is a "Manage Autoship" surface with per-section Change links, a Skip Shipment button, an Order-Now (ship early) button, and Cancel at the bottom. The friction pattern to *avoid*: each subscription managed and cancelled individually. For B2B, predictable ongoing pricing beats a one-time teaser — so we take Chewy's management UX, not its onboarding-discount strategy.

> **The three-way affordance distinction to hold onto.** Shopping lists (saved templates, no automation), one-click reorder / Buy Again (manual repeat of a past order), and subscriptions / standing orders (automated recurring) are routinely confused. Zoro, Staples, and Amazon all keep "reorder from history" separate from "subscribe." On USA Clean's PDP the toggle must read as *automation* ("we ship every N days"), clearly differentiated from the Buy Again / order-history module (see [recently-purchased-concepts.md](recently-purchased-concepts.md)) and from saved carts ([saved-cart-concepts.md](saved-cart-concepts.md)).

### Cadence differs sharply by part class

Wear rates make per-category default frequencies smarter than one global default:

| Part class | Typical replacement interval | Subscribe fit |
|---|---|---|
| Floor pads | ~50–100 hrs (disc pads far shorter — weekly-to-monthly in heavy use) | Strong · 30–60 days |
| Scrub brushes | 30–75 hrs / 6–12 mo / at 25–50% bristle loss | Strong · 30–60 days (the demo SKU is a nylon disc brush) |
| Squeegee blades | flipped weekly, replaced every 3–6 mo (~300–600 hrs) | Good · ~90 days |
| Detergents | tracks usage volume | Good · usage-driven |
| Batteries | every 2–4 years | **Exclude** — not a subscribe candidate |

The prototype's 60-day default is a sensible middle for the brush/pad demo SKU, but the brief recommends **per-category default cadences** and, as a differentiator vs. generic retail subscribe, a possible **machine-runtime-hours** framing later.

### The reassurance triad

Across Amazon, Chewy, and Staples the "terms" burden is light and trust-oriented. The universal inline reassurance is **free/included shipping · skip-or-cancel-anytime, no penalty · price charged at each shipment**. Deeper mechanics sit one layer down in an expander. USA Clean's expandable panel is the right structure, but the top-line reassurance should be *visible inline under the toggle*, not hidden behind the expander — and for Net-30 accounts, add a line on how recurring shipments invoice (per-shipment vs. consolidated).

---

## What BC Stencil gives us

BigCommerce gives us every UI hook the affordance needs — and none of the billing/scheduling engine behind it.

- **Product Options / Modifier Options.** Products support checkbox / multiple-choice / drop-down modifiers, queryable and settable via the Catalog APIs and GraphQL. A "delivery frequency" selector can be modeled as a **product modifier** so the buyer's cadence is captured on the line item and flows into the order — the same native mechanism apps like Rebillia hook into ("built into the native variants and modifiers system"). This lets the prototype's frequency `<select>` be a real, order-persisted field even before any billing engine exists.
- **Customer accounts + GraphQL Storefront API.** Stencil themes can call the GraphQL Storefront API in-page via the `{{settings.storefront_api.token}}` Handlebars token + `fetch` (or from Script Manager). Customer accounts supply identity and persistence.
- **Webhooks + Script Manager.** Webhooks fire on real-time events (orders, product/customer changes) to a merchant-hosted URL. Together with GraphQL and the modifier field, these let a subscribe affordance *record intent* (customer + product + frequency) and let a custom or app-driven scheduler place a real order on cadence.
- **Saved lists / Buy Again as a "poor-man's reorder."** Stock BC has Wish Lists; B2B Edition adds Shared Shopping Lists, Buy Again, and a Quick Order Pad (SKU / CSV bulk entry). Subscribe & Save can be degraded to a **saved-list-based reorder reminder** — persist item + frequency to a list, then prompt the buyer to re-checkout on cadence (email reminder + one-click Buy Again) rather than auto-charging. This preserves the value prop for Net-30 buyers who can't or won't tokenize a card, and is buildable on native primitives alone.
- **Native checkout recurring — a constrained, per-app gateway set.** The set of gateways that support tokenized recurring charges is constrained and varies **by app** (Stripe / Braintree / Authorize.net are the common baseline; some apps support more — MINIBC lists ~15, Rebillia lists 7 incl. PayPal / Square / CyberSource / PayFabric). Confirm USA Clean's live gateway is on the chosen app's supported list — if it isn't, even the app path is constrained.

> **The honest framing:** native gives us the modifiers, customer accounts, GraphQL, webhooks, and saved-lists/Buy-Again to *capture intent and prototype scheduled reorder ourselves*. It does not give us the recurring charge — that still needs an app (billing) or custom middleware (scheduling).

---

## Stencil limitations

Per rule #2, exactly what native BC + the stock admin **cannot** do for this feature:

1. **No subscription / selling-plan data model** in the catalog — there is no admin object for a subscription, billing schedule, or auto-ship.
2. **No recurrence engine / cron** in the platform — nothing places the next order on a schedule.
3. **No off-session payment vault** for recurring charges outside the supported-gateway app path.
4. **No native subscription-discount pricing** — the 10% Subscribe & Save price must be app- or promotion-driven, not a native "subscription price."
5. **No subscription-management surface in the customer account** — pause / skip / change-frequency / cancel are provided by an app's own portal, not by stock Stencil.
6. **No native mixed one-time + subscription cart** — that's an app capability.
7. **B2B Edition adds *no* recurring or scheduled orders.** Its named features — Buyer Portal, Company Account Structure, User Management, Invoice Portal, Address Book, Masquerade, Quoting, Shared Shopping Lists, Buy Again, Quick Order Pad — are reorder *convenience* tools. Buy Again and Shopping Lists are one-click reorder, not auto-ship. B2B Edition does **not** close the subscription gap; it only makes manual reordering fast. (Enterprise-plan only, custom-priced.)

> **Net:** the prototype CTA is a faithful UI mock, but shipping real auto-ship requires either a subscription app (for billing) or custom middleware (for scheduling) on top of native GraphQL / webhooks / modifiers. For USA Clean's Net-30 national accounts specifically, card-tokenized recurring billing may be the *wrong model entirely* — a scheduled-order / reorder-reminder built on Shopping Lists + Buy Again may fit the actual payment reality better than a card-on-file subscription app.

---

## App marketplace shortlist

BigCommerce lists these under a dedicated "Recurring Billing & Subscriptions" category — the platform's stated philosophy is to delegate recurring billing to partner apps rather than ship it natively. All prices below are **as of 2026-07 — confirm on the listing**; the quote-only apps were reported inconsistently across third-party review sites, so treat dollar tiers as directional and get written quotes.

| App | What it does | Pricing (as of 2026-07 — confirm on listing) | Fit | Verdict |
|---|---|---|---|---|
| **[Rebillia](https://www.bigcommerce.com/apps/rebillia-platform-subscriptions-saved-credit-cards/)** | BC-native subscribe-and-save, boxes, usage-based, dynamic mid-lifecycle pricing, dunning. B2B net-terms is achievable as an **architecture** (app generates order → ERP / net-terms provider invoices on terms) — reported in third-party guidance, **NOT confirmed on Rebillia's own listing**; verify with a written quote / demo. Gateways: Stripe, PayPal, Authorize.net, PayFabric, Square, Braintree, CyberSource. | Quote-only; reported "from ~$100/mo" to "$450 setup + $100–200/mo + % + $0.30/txn + $950/yr" (conflicting sources — get a written quote) | **Best B2B / Net-30 fit** — the shortlisted app that most plausibly supports the Net-30 decouple pattern (to be verified). | **Worth it now** — lead pilot candidate; net-terms is to-be-verified, not proven |
| **[MINIBC Recurring Billing & Vaulting](https://www.bigcommerce.com/apps/recurring-billing-vaulting-minibc/)** | Injects subscriptions into BC's **native one-page checkout** (buyers never leave the site); ~15 gateways; PCI card vaulting bundled. Setup is a couple lines of theme code. | ~$500 one-time setup + usage-based monthly (reported $99–$249+, tier-dependent); vaulting included | Native-checkout integration is a plus for a Stencil store; card-on-file oriented | **Worth it now** — pilot if a proven native-checkout engine is the priority |
| **[PayWhirl](https://www.bigcommerce.com/apps/recurring-payments-invoicing-by-paywhirl/)** | Recurring payments/invoicing via its own widgets; integrates with BC native checkout. | Free tier up to ~$5k/mo subscription revenue; transaction fee 0.50%–3.00% (on widget purchases only); top tier ~$249/mo | Low floor, low risk; card-on-file oriented, less obviously suited to Net-30 than Rebillia | **Worth it now** — cheapest low-risk pilot |
| **[Recharge (Checkout on BC)](https://support.getrecharge.com/hc/en-us/articles/360055770514-Getting-started-with-the-Recharge-Checkout-on-BigCommerce)** | Proven card-subscription engine; works on BC but Shopify-first roadmap. | Reported ~$99/mo + ~1.25% + per-txn fee (Starter); a low-volume tier reported for new merchants; ~60-day fee-waived trial — **confirm current Recharge BC pricing on the listing** | Weaker B2B/Net-30 fit (card-on-file); BC is a secondary integration | **Secondary** — only if a battle-tested card engine outranks B2B terms |
| **[Ordergroove](https://www.bigcommerce.com/apps/ordergroove/)** | Fully-integrated-checkout enterprise subscription platform; large-DTC customers. | Quote-only / custom | **BC Enterprise only.** Overkill for an initial PDP affordance | **Hold** — enterprise-only; revisit in Phase 3 |
| **[Bold Subscriptions](https://apps.shopify.com/bold-subscriptions)** | Subscription engine — **Shopify / Shopify Plus only**, no supported BC integration | (Shopify only) from $24.99/mo + 2% | No BC path | **Exclude** |

### Custom vs. app — the amortization math

A custom build (Stencil PDP widget reusing the existing `.buy-mode` toggle + a processor's recurring-billing engine, webhooks, a self-serve manage-subscription surface, dunning, and an ERP order push) does **not** win on cost.

- **One-time build:** order-of-magnitude **$25k–$45k** of dev (confirm with USA Clean's dev estimate).
- **App base fee avoided:** ~**$1.2k–$3k/yr** (MINIBC ~$99–$249/mo; Recharge ~$99/mo; PayWhirl up to $249/mo) — and the floor is effectively **$0** on PayWhirl's free tier, which only strengthens the app-wins-on-cost conclusion.
- **Payback on base fee alone:** even at the high $3k/yr app base, a $30k build is a **~10-year** payback — far outside rule #3's 12–18-month window.
- **Variable cost is a wash.** Both paths still pay a recurring-transaction fee of similar magnitude. A custom Stripe Billing build pays **0.7% of recurring volume** (the 0.50% promo rose to 0.70% on 2025-06-30) *on top of* 2.9% + $0.30 card processing — comparable to PayWhirl / Recharge / Rebillia per-transaction cuts (**confirm the current Stripe Billing rate**).

> **Conclusion:** choose an app now. Custom's real advantages are **data ownership** (no app data-lock), a **native Caster-styled PDP widget** (the existing `.buy-mode` / `.sub-detail` toggle survives as-is instead of being replaced by an app's injected markup), and **B2B/Net-30 flexibility** (schedule + ERP-push instead of forcing a card charge). None of those is a *cost* argument. **Treat custom as a replatform-era decision (Phase 3)** — build custom only if (a) the move to Catalyst is committed and we want to own the subscription data model, or (b) no app can model Net-30 invoice subscriptions acceptably.

### One cross-cutting gateway caveat (2026)

As of **June 1, 2026**, BigCommerce charges an **Open Payment Provider Fee** on orders through gateways *not* on its approved Embedded Payment Providers list (Stripe, PayPal/Braintree, Adyen, Checkout.com, a few others) — plan transaction rates 2% Core / 1% Growth / 0.6% Scale / custom Performance. This is a live cost as of this brief's date, not a pending risk. Whichever tool is chosen, **route recurring charges through an Embedded provider (Stripe or Braintree)** to avoid the extra fee. This favors Rebillia+Stripe/Braintree, MINIBC+Stripe, or a custom Stripe Billing build. Confirm the current BC fee schedule.

---

## Caster impact

The Subscribe & Save block is the **first consumer** of its pattern, so per rule #7 all of its CSS lives inline in [`v2/pdp.html`](../v2/pdp.html). It consumes only existing `--caster-*` tokens (spacing, radius, font-size, font-weight, border, text, brand, accent, amber) with hardcoded hex fallbacks, and adds **no** rules to `design-system/components.css`. Because shared Caster CSS is byte-identical, **no cache-bust bump was needed**.

**On a second consumer, promote to Caster** as a composite component with a dedicated showcase page:

- **Candidate component:** `.buy-mode` (purchase-mode selector) with elements `.buy-mode__opt` / `__row` / `__radio` / `__title` / `__flag` / `__price`, plus the `.sub-detail` / `.sub-terms` sub-blocks.
- **Showcase path:** `design-system/components/composites/buy-mode.html` (composites tier).
- **Promotion work:** move the inline `<style>` into `components.css`, drop the hex fallbacks, formalize the custom radio-card as a reusable *selectable-card* primitive, then bump the cache-bust (`?v=`) since `components.css` changes.
- **Keep `.buy-mode__flag`** — it deliberately avoids Caster's `.badge` / `.pill` collision (project rule); preserve that on promotion.

> **The natural second consumer is the account-side "Manage subscriptions" surface** (per the Staples / Amazon precedent) — which makes Phase 2 the promotion trigger. **But hold the promotion until the app/custom decision lands.** If an app is chosen, its injected widget may replace or reskin the toggle entirely, so promoting now risks reskinning twice. A custom build is the only path that lets the existing Caster-styled toggle survive as-is.

---

## Phased recommendation

### Phase 1 — Ship the PDP affordance + pilot one app (pilot)

**Ship the Subscribe & Save affordance already built in [`v2/pdp.html`](../v2/pdp.html)** and wire it to **one** subscription app on a narrow set of high-repeat consumables (pads, brushes, squeegee blades, detergents, filters) — deliberately excluding equipment and batteries.

- **Recommended app:** **Rebillia**, as the shortlisted app that most plausibly supports the Net-30 decouple pattern (generate order → ERP / net-terms push on terms) — the pivotal filter for USA Clean's buyers. This net-terms fit is **to be verified with Rebillia directly** (written quote / demo) before committing; it is not stated on their public listing. **Cheaper low-risk alternative:** PayWhirl (free tier) or MINIBC (native checkout) as a card-on-file pilot if the first cohort tolerates card-on-file.
- **Enforce the discount rule** in the live pricing engine: **contract price wins, then greater-of (subscription 10% vs. volume tier), never naive stacking.** Show the correct effective price when a volume-tier buyer selects subscribe. The terms bullet must become a real rule.
- **Make the cadence real** via a product-modifier field so the choice persists on the line item, and **recompute price on cadence/qty change** (the mockup doesn't).
- **Surface the reassurance triad inline** under the toggle (free/included shipping · skip/cancel anytime · price at each shipment), plus a Net-30 invoicing line.
- **Route charges through an Embedded gateway** (Stripe or Braintree) to avoid the Open Payment Provider Fee.

**Trigger to graduate to Phase 2:** a live subscribe opt-in rate on piloted SKUs at or above the program's target (recommend tracking subscribe-ATC / total-ATC by category), **and** repeated requests to change or skip a shipment that the account has no self-serve way to satisfy — i.e., support tickets doing manually what a manage-subscription surface would do.

### Phase 2 — Manage-subscription + national-account standing orders (data-gated)

Once Phase 1 shows real opt-in and the management burden lands on support, build the account-side surfaces the terms already promise:

- **Manage-subscription in the account** — skip / reschedule / swap-SKU / change-frequency / cancel, tied into the National Account pages (`v2/account-*`), lifting Staples' and Chewy's management UX.
- **Standing orders for national accounts** — the Net-30 form of the feature: a pre-authorized recurring PO with start/end date bounding (Zoro's precedent), invoiced per-shipment or consolidated.
- **Per-category cadence tuning** — replace the single 60-day default with per-class defaults (pads/brushes ~30–60d, squeegee blades ~90d, detergents usage-driven, batteries excluded).
- **Multi-address / multi-schedule** (Staples precedent) for buyers running several sites.

**Trigger to graduate to Phase 3:** the program outgrows what Stencil + an app can express well — buyers asking for dynamic per-line price recompute across subscribe × volume × contract, rich stateful management that's clumsy in Stencil templates, or a national account asking for consumption-driven (not calendar) replenishment.

### Phase 3 — Enterprise / headless (future)

Hold until the program earns it:

- **Catalyst / headless subscription surfaces** for the manage-subscription and dynamic-pricing views that Stencil expresses awkwardly (see Catalyst section below).
- **Enterprise program** (Ordergroove-class) if USA Clean is on BC Enterprise and running a large subscription program.
- **Consumption / threshold VMI** (Grainger KeepStock-style) — the heavier, telemetry-driven replenishment program that is *not* a PDP calendar toggle. This is the "by machine runtime hours" differentiator taken to its conclusion, and overlaps with fleet/telematics integrations from the account brief.

**Decision of record:** (pending — no client decision yet; see [docs/decisions.md](decisions.md))

---

## Implementation notes

### Data sources

- **Subscription state lives in the app / processor, not BC core.** The PDP toggle captures intent (mode + cadence); the subscription contract, next-ship date, cadence changes, skip/cancel, and recurring charge are owned by the app + a saved/tokenized payment method (or, for Net-30, an ERP order-push).
- **Cadence field** as a native product **modifier** so it persists on the order line and flows through the order.
- **Intent capture** via the GraphQL Storefront API + webhooks if a scheduled-reorder path is prototyped ahead of the app.

### Auth + role gating

USA Clean buyers are facility managers / national accounts with **multiple users per account on Net-30**. A recurring commitment is a **standing financial obligation** — effectively a pre-authorized recurring PO — so subscription create / modify / cancel must be gated by BC customer-group / B2B Edition company role (admin vs. buyer). Decide at design time whether (a) only admins/approvers can create subscriptions, (b) each recurring shipment re-checks the approval rule, or (c) the subscription is approved once at setup. The prototype toggle currently implies any buyer can self-serve — **this is an open policy question for the client.** Net-30 also changes the charge model: "card charged when each order ships" (terms bullet 2) may instead need to post to the Net-30 account/invoice, which the terms copy should reflect per buyer type.

### The discount-precedence rule (the load-bearing decision)

This SKU shows both a Subscribe & Save 10% price and a volume-tier block that says "stacks across the cart line." Whichever engine computes price (BC price rules vs. the subscription app) must implement a **deterministic precedence: contract/negotiated price wins, then greater-of (promo vs. volume), never naive multiplication** — otherwise a 12+ subscriber compounds to ~23.5% off already-negotiated national-account pricing. The PDP must display the correct effective price when a volume-tier buyer selects subscribe. In the prototype price is static, so this is unenforced — it's a live implementation requirement, not just copy.

### Accessibility

Largely handled in the prototype: `role="radiogroup"` + `aria-label`; real native radios (visually hidden, not `display:none`, so still focusable and arrow-navigable); a `:focus-visible` ring on the faux radio; faux radio + flag marked `aria-hidden`; the terms button uses `aria-expanded` + `aria-controls` on a `hidden` panel. To verify on promotion: the strikethrough price and "Save 10%" flag are visual-only, so add an `aria-label` on the subscribe option summarizing "Subscribe and save 10 percent, $38.16"; and once price recompute is wired, ensure the frequency `<select>` announces the new effective price.

### Performance

The PDP itself is light. The cost is the app's injected widget and any live price-recompute call on cadence/qty/volume-tier change — keep that a single fast endpoint and render the static toggle instantly.

### Analytics

- **Opt-in rate** — subscribe ATC / total PDP ATC (the headline pilot metric).
- **Cadence distribution** — share choosing 30 / 60 / 90 / 6mo (validates the 60-day default).
- **Terms-panel open rate** — comprehension / friction signal.
- **Attach rate by category** — consumables should index far higher than equipment; decides where to surface the toggle.
- **Retention signals (owned by the app):** active-subscription count, skip rate, reschedule rate, churn/cancel rate + time-to-cancel.

---

## Catalyst / replatform candidacy

**Subscribe & Save is *not* by itself a forcing function for Catalyst.** The PDP toggle, cadence select, terms, and ATC relabel are all achievable in Stencil (Handlebars + Stencil JS or a small custom bundle) plus a subscription app for the recurring engine. The ceiling is UX richness, not capability.

Where Stencil's ceiling actually shows up:

- **Dynamic price recompute** on cadence / qty / volume-tier change — Stencil is server-rendered, so live client price math means bolt-on JS reaching an API.
- **Rich account-side subscription management** — skip / reschedule / swap-SKU UIs are clumsy in Stencil theme templates.
- **Stitching the subscription app's data into a personalized National Account home** (per the account brief).

**Catalyst (headless React) makes those richer, stateful surfaces natural — but it's a convenience/velocity gain, not a prerequisite.** What the user loses if we hold for the replatform: essentially nothing on the core buy-flow; only the polish on the management and dynamic-pricing surfaces. **Recommendation: build on Stencil + app now; treat the account-management + dynamic-pricing surfaces as the specific signals that would justify moving *those views* headless later** — and treat a fully custom subscription data model as a Phase 3 / replatform-era decision, per the amortization math above.

---

## Sources

- [BigCommerce — Recurring Billing & Subscriptions app category](https://www.bigcommerce.com/apps/categories/payments-security/recurring-billing-subscriptions/) — confirms no native recurring billing; BC delegates to partner apps
- [BigCommerce Developer — GraphQL Storefront API](https://developer.bigcommerce.com/docs/storefront/graphql) — in-theme intent capture
- [BigCommerce Developer — Product Modifier Options](https://developer.bigcommerce.com/docs/store-operations/catalog/graphql-admin/product-modifier-options) — cadence-as-modifier field
- [Anchor Group — BigCommerce B2B Edition overview](https://www.anchorgroup.tech/blog/bigcommerce-b2b-edition-overview-key-features-functionality) — B2B Edition adds no recurring/scheduled orders
- [BigCommerce — B2B Edition Buyer Functions help](https://support.bigcommerce.com/s/article/B2B-Edition-Buyer-Functions) — Buy Again / Shopping Lists are manual reorder, not auto-ship
- [Subbly — Best BigCommerce subscription apps](https://www.subbly.co/blog/best-bigcommerce-subscription-apps/) — supported-gateway constraint (Stripe / Braintree / Authorize.net)
- [Rebillia (BigCommerce listing)](https://www.bigcommerce.com/apps/rebillia-platform-subscriptions-saved-credit-cards/) · [Rebillia for BigCommerce](https://www.rebillia.com/bigcommerce) — B2B net-terms subscriptions
- [Optimum7 — Custom payment terms for B2B subscriptions](https://www.optimum7.com/blog/custom-payment-terms-for-b2b-subscriptions-in-shopify-and-bigcommerce-a-practical-guide.html) — decoupling recurring event from card charge
- [SoftwareSuggest — Rebillia](https://www.softwaresuggest.com/rebillia) · [SelectHub — Rebillia](https://www.selecthub.com/p/subscription-management-software/rebillia/) — conflicting pricing (get a quote)
- [MINIBC Recurring Billing & Vaulting (BigCommerce listing)](https://www.bigcommerce.com/apps/recurring-billing-vaulting-minibc/) · [MINIBC Recurring Billing & Vaulting](https://www.minibc.com/recurring-billing-vaulting/) · [MINIBC pricing](https://www.minibc.com/pricing)
- [PayWhirl (BigCommerce listing)](https://www.bigcommerce.com/apps/recurring-payments-invoicing-by-paywhirl/) · [PayWhirl — BigCommerce pricing](https://docs.paywhirl.com/apps-and-integrations/bigcommerce/how-does-pricing-work-for-bigcommerce-customers)
- [Recharge — Checkout on BigCommerce](https://support.getrecharge.com/hc/en-us/articles/360055770514-Getting-started-with-the-Recharge-Checkout-on-BigCommerce) · [Recharge billing & pricing](https://support.getrecharge.com/hc/en-us/articles/360008682914-Recharge-billing-and-pricing)
- [Ordergroove for BigCommerce](https://www.ordergroove.com/integrations/bigcommerce/) · [Ordergroove (BigCommerce listing)](https://www.bigcommerce.com/apps/ordergroove/) — BC Enterprise only, quote-only
- [Bold Subscriptions (Shopify App Store)](https://apps.shopify.com/bold-subscriptions) · [Bold Subscriptions pricing](https://boldcommerce.com/shopify/subscriptions-pricing) — Shopify-only, exclude
- [Stripe Billing pricing](https://stripe.com/billing/pricing) · [Stripe Billing fees 2026 — the 0.7% math](https://usagebox.com/articles/stripe-billing-fees-2026-the-07-percent-math) — custom-build variable cost
- [BigCommerce — 2026 plan & pricing updates](https://www.bigcommerce.com/dm/plan-pricing-updates-2026/) · [Netalico — BigCommerce 2026 pricing update](https://netalico.com/blogs/netalico-digest/bigcommerce-2026-pricing-update) — Open Payment Provider Fee
- [Staples AutoRestock](https://www.staples.com/deals/Auto-Restock/BI1498644) · [Staples — Shop Auto Restock](https://www.staples.com/deals/Shop-Auto-Restock/BI1500829) — closest PDP analog
- [Amazon Business Subscribe & Save](https://www.amazon.com/gp/help/customer/display.html?nodeId=201733120) · [Amazon — Manage Your Subscriptions](https://www.amazon.com/b?ie=UTF8&node=15283820011) — consolidation tiers + billing model
- [Zoro — Automatic Replenishment Service](https://www.aero-mag.com/zoro-breaks-new-ground-with-automatic-replenishment-service) · [Zoro — Reorder Items](https://www.zoro.com/my-account/reorder-items) — B2B gating + bounded runs
- [Grainger KeepStock](https://www.grainger.com/content/mc/services-and-solutions/keepstock) — VMI contrast case (Phase 3 reference)
- [Chewy Autoship](https://www.chewy.com/b/autoship-save-15682) — consumer management-UX gold standard
- [Adobe Commerce B2B — Purchase Order Flow](https://experienceleague.adobe.com/en/docs/commerce-admin/b2b/purchase-orders/purchase-order-flow) — approval/role governance for standing orders
- [Triad Service — Wearable parts on floor cleaners](https://www.triadservice.com/blog/view/1577/wearable-parts-on-floor-cleaners) — per-category cadence defaults
- [saved-cart-concepts.md](saved-cart-concepts.md) — this feature is that brief's Phase 3 ("schedule a recurring order")
- [recently-purchased-concepts.md](recently-purchased-concepts.md) — the reorder / Buy Again distinction Subscribe & Save must stay separate from
- [account-concepts.md](account-concepts.md) — the National Account pages where manage-subscription (Phase 2) lands
