> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tuturuuu.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Storefront

> Public and private inventory storefronts with Polar and Square Terminal checkout.

`apps/storefront` is the buyer-facing Inventory commerce app. Operators manage
catalog, stock, storefront visibility, and checkout-provider settings in
`apps/inventory`; buyers browse, cart, and start checkout from
`storefront.tuturuuu.com`.

## Hosts

* Production: `https://storefront.tuturuuu.com`
* Local Portless: `https://storefront.tuturuuu.localhost`
* Local fallback port: `7822`

The Storefront app rewrites `/api/*` to `apps/web`, matching other satellite
apps. It does not read Supabase directly from client code.

## Access

Published public storefronts are readable anonymously. Published private
storefronts require a Tuturuuu app session and workspace membership; guest-type
workspace members are accepted.

## Theme and lifecycle

The Inventory storefront editor offers a **Native** accent mode as the safe
default. Native mode leaves `accent_color` unset so Storefront inherits its
theme-aware primary, focus, and contrast tokens in both light and dark mode.
Choose **Custom** only when a fixed hexadecimal brand color must override those
tokens.

Removing a storefront is deliberately non-destructive. Inventory marks the
storefront as removed, releases its former public slug for reuse, invalidates
the old public cache entry, and hides it from operator and buyer discovery.
Checkout sessions, order history, stock movements, and audit references keep
their original storefront row. Archiving remains the reversible choice for a
storefront that may return later.

## Polar Checkout

Each workspace can save sandbox and production Polar organization tokens from
Inventory settings. Tokens are encrypted server-side and only masked metadata is
returned to clients.

Storefront checkout reserves inventory first, creates a Polar checkout session
with the workspace-owned private one-time product, and redirects the buyer to
Polar. If Polar checkout creation fails after reservation, the reservation is
released immediately.

## Square Terminal Checkout

Square Terminal checkout is a staff-only pay-at-terminal handoff. A signed-in
member needs the dedicated **Start POS checkout** permission (or Admin), then
selects the paired payment station that should receive the order. Storefront
validates the member, device, and selling location before creating a local
reservation and sending the Square request. Repeated dispatches are rate
limited before reservation.

Square POS App + Reader uses a different same-device handoff: it opens Square
POS on the compatible phone or tablet currently running the Storefront and
cannot target another reader remotely. The checkout UI states this distinction
instead of presenting phone installation IDs as routable Terminal devices.

Square payment success is accepted only from verified Square webhook or status
data. Cancellation, failure, or expiry releases the local reservation so stock
returns to availability. Abandoned reserved sessions are materialized as expired
by the Inventory sweeper as well as lazy checkout reconciliation. Catalog and
physical stock can be synchronized in either direction from Inventory settings;
Square-side updates are additive and never delete or archive Square objects.

## Cache and invalidation contract

Published storefront payloads use Next.js Cache Components with a cache tag per
storefront slug. The data cache has a long safety-net lifetime and is refreshed
by events rather than by polling. Any operation that changes shopper-visible
catalog data or availability must invalidate the affected tag before returning
success. This includes product and stock edits, reservations, reservation
release or expiry, completed sales, provider reconciliation, and inbound Square
catalog sync.

Checkout reservation code must continue to read fresh stock directly. A cached
browse response is only a presentation optimization and must never be used as
the source of truth for reserving or consuming inventory.

Storefront routes stream `loading.tsx` and explicit Suspense fallbacks while
request-specific buyer and access data resolves. Server data seeds the TanStack
Query cache, internal links use Next.js navigation, and the browser must not
repeat the initial storefront request on mount.

## Cache E2E test

Start local Supabase, then run the Inventory-owned cross-app Playwright suite:

```bash theme={null}
bun sb:start
bun --cwd apps/inventory test:e2e
```

The test creates a disposable public storefront, warms the cached API payload,
changes stock through the authenticated Inventory API, and verifies the next
public read sees the new quantity. It also confirms the product route streams a
skeleton, uses Next's `@next/playwright` `instant()` helper to prove that the
prefetched loading shell commits before dynamic data resumes, keeps Storefront
navigation client-side, and removes the entire fixture in cleanup. Keep both
Inventory (`7815`) and Storefront (`7822`) server entries in
`apps/inventory/playwright.config.ts` whenever either app's local host or
startup command changes. The `Inventory / Storefront cache contract` job in
`.github/workflows/e2e-tests.yaml` runs this suite in parallel with the broader
platform E2E matrix and uploads Playwright traces and the HTML report when it
fails.
