Forward is a fresh Next.js App Router storefront theme for Shopify, powered by Weaverse.
The storefront now has a hybrid production data source. With the approved
server-only Shopify environment, products, canonical collection structure,
Header main-menu, and the complete three-column footer navigation tree are
read from the Storefront API. Footer navigation has one Store-owned source: it
is not derived from main-menu, forward-footer, or theme-owned Support links.
Without that environment it remains a deterministic, network-independent
static storefront. Journal/page/policy bodies, theme copy, the browser-local
demo cart, and prototype account surfaces still use fixtures; checkout,
Customer Account OAuth, Weaverse Studio composition, and locale/market routing
remain deferred.
Requires Bun (package manager and script runner) and Node.js >= 22.18.0 (the route tooling executes TypeScript directly with Node's built-in type stripping; the app itself stays Node-compatible — Bun is a tooling decision, not a production runtime).
bun install
bun run devOpen http://localhost:3333. The development script
uses port 3333 by default.
The Hydrogen baseline was initialized in this existing Next.js app with:
npx @shopify/hydrogen@preview setupThat deterministic command installs the preview package and copies Shopify's
Hydrogen implementation skills into .agents/skills/. The server-owned
Storefront read client is wired; cart mutations, request-specific buyer
context, checkout, and Customer Account remain explicit future work.
| Command | What it does |
|---|---|
bun run dev |
Start the development server on http://localhost:3333. |
bun run build |
Create the production build. |
bun run start |
Serve the production build. |
bun run typecheck |
Strict TypeScript check (tsc --noEmit). |
bun run lint |
Biome lint (biome lint .). |
bun run format |
Format the repository with Biome (writes). |
bun run format:check |
Verify formatting without writing. |
bun test |
Unit tests (route contract, static data source, colorway/gallery helpers, demo-cart logic) via Bun's test runner. |
bun run check:routes |
Verify the route contract against actual build output (.next manifests). Requires a prior bun run build. |
bun run smoke:routes |
Start the production server, verify every contract path and redirect over HTTP, then stop the server. Requires a prior bun run build. |
bun run check |
Composed static gates: typecheck → lint → format:check → test → build → check:routes. Leaves no server running. |
Storefront data flows through a single replaceable seam:
static fixtures or server-only Shopify Storefront API reads
-> StaticStorefrontDataSource or ShopifyCatalogDataSource
-> normalized storefront view models (src/lib/storefront/types.ts)
-> route loaders / page composition (src/app/**)
-> visual components (src/components/**)
Pages and components never import fixture objects directly — everything goes
through the exported storefront instance. Unknown dynamic handles resolve to
null and routes answer with real notFound() 404s. The Shopify adapter
implements the same StorefrontDataSource interface one domain at a time
without touching page composition.
The cart is an honest browser-local demo (src/lib/demo-cart/): quantities,
removal, and totals work, state persists in the browser, and the UI labels it
as a demo with no real checkout.
The single source of truth is src/lib/routes/route-contract.ts. Shell UI, next.config.ts redirects, the build checker, the HTTP smoke, and the tests all read from it.
| Route | Surface |
|---|---|
/ |
Home |
/shop |
Full catalog |
/shop/[collectionHandle] |
Collection |
/products/[productHandle] |
Product |
/search |
Search |
/cart |
Cart |
/journal |
Journal index |
/journal/[articleHandle] |
Journal article |
/pages/[pageHandle] |
Store page |
/policies/[policyHandle] |
Store policy |
/account |
Account overview |
/account/orders |
Order history |
/account/orders/[orderId] |
Order detail |
/account/addresses |
Addresses |
/account/login |
Sign in |
/account/authorize and /account/logout are explicit placeholders that answer 501 Not Implemented. No authentication or credential handling exists in the static demo, and these handlers do not pretend otherwise. Account pages are polished prototype states rendered from demo fixtures and are labeled as not live.
/robots.txt and /sitemap.xml are generated by App Router metadata routes against a placeholder origin (https://forward.example); the production domain is a deferred deployment decision.
| From | To |
|---|---|
/collections/all |
/shop |
/collections/[collectionHandle] |
/shop/[collectionHandle] |
/blogs/journal |
/journal |
/blogs/journal/[articleHandle] |
/journal/[articleHandle] |
Dynamic routes are smoke-tested with approved fixture handles only
(weatherline-shell, ridge-30-field-pack, talus-trail-shoe for products;
field-gear, walking-the-long-light, about-forward, and
shipping-policy for the other resource classes). The smoke handles live in
src/lib/routes/route-contract.ts and resolve against the storefront
fixtures in src/lib/storefront/fixtures/; unknown handles return real 404s.
Shopify's shopify hydrogen check routes inspects the file-based routes of Shopify's React Router Hydrogen skeleton. Forward uses the Hydrogen preview package inside Next.js App Router, so that framework-specific route checker is not authoritative here. The equivalent is bun run check:routes, which validates generated App Router manifests in .next/ (not source filenames) against this repo's own route contract, plus bun run smoke:routes, which verifies live HTTP behavior — including permanent redirects — against a production server.
- Products, canonical collection structure, Header
main-menu, and Footerfooternavigation are live in Shopify mode. Without the complete approved server-only environment, the same normalized seam selects deterministic static fixtures without network access. - Shopify-mode product reads fail closed. Header, Footer, and collection structure have separate deterministic safeguards; one structure failure does not change the others or turn a live product failure into fixture success.
- No real cart mutations or checkout — the cart is browser-local demo state with an explicitly disabled checkout.
- No Customer Account OAuth — account surfaces are labeled prototype states.
- No Weaverse Studio bridge.
- No locale/market routing (markets are TBD in the shared contract).
- Vercel Production deployment is configured separately from repository data adapters; credentials remain outside Git and browser bundles.