Skip to content

Storefront Overview

The storefront lives in storefront/ in the rCommerce repository. It is an Astro site with React islands, designed to serve multiple stores from one codebase: each store is a separate Cloudflare Pages project, and all store-specific differences are baked in at build time via PUBLIC_* environment variables.

Production example: the same codebase serves store-a.example.com (my-storefront Pages project) and store-b.example.com (store-b-pages Pages project).

Brand identity is resolved at build time in src/lib/brand/config.ts and inlined by Astro — there is no runtime switching.

VariablePurposeDefault
PUBLIC_BRAND_SLUGStore key (store-a, store-b) — selects per-brand page variantsstore-a
PUBLIC_BRAND_NAMEStore name shown in header, footer, emailsMy Shop
PUBLIC_BRAND_LOGOLogo path under public//images/store-a-logo.png
PUBLIC_BRAND_PRIMARYAccent color (Tailwind primary)#2563EB
PUBLIC_BRAND_MENUHeader/footer categories: comma-separated slug:Label pairsgear/apparel/accessories
PUBLIC_HERO_VIDEO_URLCloudflare Stream iframe src for the homepage herohero video
PUBLIC_BRAND_HERO_PRODUCT_SLUGProduct featured in the hero panelacme-ceramic-mug
PUBLIC_API_BASEBackend API base for client-side fetcheshttps://api.store-a.example.com/api/v1
RCOMMERCE_API_URLBackend origin for the runtime API proxy (no /api/v1 suffix)—
PUBLIC_AIRWALLEX_ENVFallback Airwallex environment for the checkout Drop-in (demo/prod)demo

Values fall back to the example store defaults when unset, so building with no environment produces the demo store.

Long-form, user-visible content (taglines, contact pages, footer links and columns, homepage copy, FAQ) lives in src/lib/brand/:

  • default.ts — the complete example store content. Every field of the BrandContent type is present.
  • store-b.ts — Store B overrides. Only fields that differ are set.
  • index.ts — deep-merges defaultContent with the override module selected by PUBLIC_BRAND_SLUG:
export const content: BrandContent = mergeContent(defaultContent, OVERRIDES[brand.slug]);

Unknown slugs fall back to the defaults unchanged. To onboard a new store, add a <slug>.ts override module and register it in the OVERRIDES map — no other code changes are required. Each store must provide its own logo at public/images/<store>-logo.png (do not reuse another store’s logo as a stand-in).

The brand content map also carries wooRedirects — legacy WooCommerce product slugs mapped to canonical product URLs. See SEO & Redirects for how these are served.

Client-side calls use PUBLIC_API_BASE directly, but cart, coupon, and checkout mutations go through a same-origin proxy at /api/v1/* (src/pages/api/v1/[...path].ts, a Pages Function). It forwards to RCOMMERCE_API_URL at runtime, which keeps credentials and CORS off the browser’s critical path and lets the storefront talk to its own origin.

  • Product catalog with category navigation and product detail pages
  • Guest cart with drawer, coupon support
  • Checkout with shipping selection and Airwallex Drop-in
  • Account pages: register, login, password reset, order history
  • Per-origin robots.txt, sitemap.xml, and Google shopping feed
  • Legacy WooCommerce URL redirects (301) for migrated stores