尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Day plans and packing lists for the trips you take again.
You keep the trips you take again in one place — Thanksgiving at your parents', a conference in New York, Lisbon in March. Each one builds its own packing list from your dates and the weather where you're going that month, and shows how many bikes are free right now at the docks nearest the places you're staying. Afterwards you say what you didn't need and what you wished you'd brought, and the next time you take that trip, it all starts already corrected.
Built for Design, Build, Ship · MPCS 51238. Assignment 3 designed the flows and the interface; Assignment 4 (Full Stack App) put accounts, a database and one external API underneath them, which is what makes the list follow you from the laptop you planned on to the phone beside the suitcase. Assignment 5 (Live Data System) added a worker that runs around the clock and a page that updates itself.
Live: https://wanderlist2.vercel.app
A trip knows where you're going and when. That already drove the packing list, through fifteen years of weather normals for your dates. Now it drives two more things.
Where you're staying. You name the places that matter on this trip — the hotel's street, the neighbourhoods you're deciding between — and they're saved on the trip, so you say it once and they're there after you sign out and on your next device. It's a list, because comparing two neighbourhoods is half of what live counts are good for.
When you need things. Every inventory row can say always, or when it's cold /
hot / wet, or on weekends / long trips. Those aren't labels: buildPackingList reads
them, so tagging the umbrella "when it rains" once puts it on every wet trip without you
re-adding it. The vocabulary is closed because each tag has to be something the app can
decide from the dates and the climate normals it already has.
Live bikes. For each of those places, the nearest docks and how many bikes and empty spaces each has right now, arriving without a refresh.
There was briefly a generated day-by-day itinerary here, and it was cut. It needed a hand-written list of places per city, so it worked for six cities and silently did nothing everywhere else, and the only keyless way to generate places anywhere returns things like "Bombing of Barcelona". Naming where you're staying works in any city, and it is a better anchor than a city centre, which is nobody's hotel.
GBFS feed ──every 30s──▶ Edge Function ──only changed rows──▶ Postgres ──Realtime──▶ Page
Drawn before the worker was written, and it has held: every box is still one
hop and nothing in the chain can be skipped. Two dashed paths on the chart are
the parts that are easy to miss — station_follows is what decides which
systems get fetched at all, and worker_runs is the only thing that lets the
page tell stale from down.
Ambient data beats episodic data. Anything tied to one person's trip — their flight, their game — only moves while that trip is happening, and would be a still photograph when somebody looks at it. Bikes come and go in Chicago at 2am.
Measured before committing to it, not assumed: 2,078 Chicago stations, 72 of which
changed across two calls 120 seconds apart — 3.5%. The feed advertises ttl: 60.
bike_systems began as twelve rows typed into a migration, which meant coverage
was bounded by my typing rather than by what exists — a trip to Toronto was told
"no bikeshare here", which wasn't true.
The opposite also failed. Letting people type any city and looking it up on
demand sent someone to Pittsburgh and showed them "No docked bikeshare in
Pittsburgh" — false twice over, and the reason why is the interesting part
below. A destination now has to be a city where both halves of the app
work, and the list of those is derived rather than typed:
scripts/verify-systems.mjs probes all 1,277 systems in
MobilityData's registry,
end to end, and stamps the survivors. 242 cities, 34 countries.
The cost is stated rather than hidden: you can no longer make a trip to a village in the Alps, and that worked before. It is chosen because a packing list that works everywhere beside a live panel that works nowhere in particular is the worse thing to hand someone.
Six gates, every one of them added because a real system failed it in a way that reached the screen:
| Gate | Rejected | Found by |
|---|---|---|
Publishes station_information + station_status | 321 | Free-floating fleets publish neither |
| At least 20 located stations | 391 | Three painted parking squares is not a system |
| Some station reports free docks | 136 | Dott Paris: 12,667 stations, dock counts on none |
| Some station has a bike in it right now | 16 | Denver's system shut in 2020; its 119 docks still report sixteen empty spaces, permanently |
| City name geocodes within 100 km of its own stations | 40 | The weather half — see below |
| The name is a place, not a country | 8 | Switzerland's system has 12,563 stations and "Switzerland" is not a destination |
The weather gate is the one worth explaining. /api/climate geocodes the
destination string, so the test is whether that same call lands where the
stations are. It throws out registry rows that were never cities —
Mecklenburg-Vorpommern, a bare DE — and, less obviously, real cities whose
names resolve somewhere else entirely: Cornwall GB to Cornwall, Pennsylvania,
5,691 km away; Brest FR to Brest, Belarus. Losing Cornwall is a real cost,
taken because the alternative is packing someone for the wrong continent.
以上為 README 的開頭部分。其餘內容請閱讀原文。 檢視完整 README ↗