Build flow — from /build to deep-link¶
What this answers: what happens, in order, when a Visitor opens the build page, picks components, and clicks through to a retailer.
Sequence¶
sequenceDiagram
participant V as Visitor
participant B as Browser (/build)
participant S as Next.js server
participant DB as Postgres
participant R as Retailer Site
V->>B: open /build
B->>S: GET /build (with build_session cookie if present)
S->>DB: SELECT Products by current slot ids (URL params + cookie)
DB-->>S: rows
S-->>B: render — shows current build, slot pickers, compat panel
V->>B: pick CPU
B->>B: update URL params (?cpu=...)
B->>S: GET /build (new URL state)
S->>DB: SELECT Products + Listings for new slots
DB-->>S: rows
S->>S: computeCompatibility(slots)
S-->>B: render — updated build, compat annotations, price total
Note over V,B: User repeats picks until satisfied
V->>B: click "Buy" on a listing in the per-retailer cart
B->>S: GET /api/go/r/[retailerId]/p/[listingId]
S->>DB: INSERT Click (clickToken, source: 'build-cart')
DB-->>S: ok
S-->>B: 302 redirect to retailer URL
B->>R: navigate to retailer URL
R-->>V: retailer product page
Notes¶
- Build state lives in URL params during interaction (
?cpu=ryzen-7&gpu=...). This makes builds shareable as URLs and survives reload. The optional cookie holds the saved state on top of that — see Build lifecycle. - Compat re-evaluates on every change.
computeCompatibilityis a synchronous pure function over the slots; cheap enough to run server-side on every request. - Per-retailer cart is a derived view: for each Retailer that has Listings for components in the Build, group them. The cart shows totals per Retailer.
- The Click row is written before the 302 — if the retailer redirect fails the click is still recorded, which is what we want for affiliate accounting.
- No payment processing is in our path. UC-2 is "Buy via deep-link" — we hand the user to the retailer and they take it from there. Affiliate attribution is reconciled out-of-band via S2S postback (#17).
Cart split optimisation¶
If the Build has components from multiple retailers, the user can engage UC-12 Cart aggregator to compute the cheapest combination. That sequence is documented separately.
Save and share¶
When the user clicks "Save," the flow forks:
- Anonymous save — server signs the slot map and writes a
build_sessioncookie. State machine: see Build lifecycle. - Account save (after Auth.js #11 lands) — server writes a
Buildrow owned by the User.
Either way, "Share" generates an unlisted slug. See ADR-0003 for the reasoning.