← Build · all briefsBrief 4 · after "Connect the market" · demo next class
Brief 4

Saved on the server

The ♥ moves from localStorage to the server, so it no longer lives in one browser. (The course server keeps one list per market, so per student; a real one would keep one per signed-in user.) A click must feel instant even on a slow server, so the page updates first and asks second: optimistic UI. When the server says no, the page puts things back and says so. ★★☆

“I saved four stalls on my laptop. My phone says I saved none.”

You'll demo (next class): with chaos on, click ♥ five times quickly on different stalls: each turns on at once. One of them fails: it turns back off and a message says which one. Reload: the server's list is what you see.

The core (start in class if you've connected, the minimum for the demo)

Four things, on top of your connected market. They count when they work with chaos on (control page).

The full feature (finish at home)

What has to work for the demo next class, not how. The core above is part of it.

Requests

  • On start, GET /api/saved fills state.saved (together with the stalls).
  • ♥ on: PUT /api/saved/:id. ♥ off: DELETE /api/saved/:id. Both 204, no body.
  • localStorage no longer stores the saved ids.

States

  • The ♥ changes on click, before the response (optimistic).
  • A ♥ with a request in flight looks pending (dimmed), and can still be clicked: the last click decides.
  • "♥ 3 saved" counts what the page believes; after a reload, what the server knows.

Errors

  • A failed PUT or DELETE rolls that one stall back, and only that one.
  • A short message names the stall: "Couldn't save Mezcal Moon. Try again."
  • If GET /api/saved fails, the stalls still render; the ♥s are disabled with a note.

The endpoints you need

MethodPathAnswers
GET/api/saved200 · array of stall ids
PUT/api/saved/:id204 · 404 unknown stall · idempotent
DELETE/api/saved/:id204 · idempotent

Test in two browsers (or a normal and a private window): save in one, reload the other.

Edge cases (with chaos on, minutes 38–43)

Stretch, if you're done early

Stuck? One hint at a time

Network panel first: is the request sent, with what, and what came back? Then a hint.

Hint 1

To roll back, you need to know the value before the click. Where is it at the moment of the click?

Hint 2

On, off, on, quickly: three requests. Which response should decide what the ♥ shows?

Hint 3

PUT and DELETE are idempotent. What does that let you do when one fails?

Traps

Open when something behaves strangely

Before you start

This brief assumes Connect the market is done: api.js works, the stalls come from the API, loading and errors are handled. Then: A ♥ click sends PUT /api/saved/:id (204), and GET /api/saved in the Network panel lists that id after a reload.

Demo · next class, 3 minutes

Your 3 minutes
  1. The happy path, with the Network panel open next to the page.
  2. Chaos on: the loading state, one failure, and how the page recovers.
  3. One request in code: the call, the status codes you handle, where the state changes.
  4. One bug you hit, and the panel or the message that showed it to you.