October 2, 2026
Neighborhood totals by the city's own label, rolling 24 months
Steiner example from the 200 block, plain sourcing, no 'complete record', owner's quotes
Correct stale and false numbers across the site before launch
CURB is built in the open — here's the whole thing, commit by commit, newest first. The complete history also lives on GitHub.
Three weeks, 213 commits — the same screen from June 8 to June 29, 2026.
Neighborhood totals by the city's own label, rolling 24 months
Steiner example from the 200 block, plain sourcing, no 'complete record', owner's quotes
Correct stale and false numbers across the site before launch
A failed monthly data refresh opens an alert and wakes the on-call routine
Retry a dropped Leaflet or time core, then say CURB didn't load
Precache the time core with the app shell
Name Meta's crawlers in the group, drop the broad Allow
A failed script or icon request fails cleanly, not with the app shell
Keep crawlers off the live map deep links
Skip reports from self-declared crawlers
One time core per city, SF is the default instance
Keep the logo on phones, still no white pill
Phones show just the ≡ button, no white nav pill
Key the sub-page top bar fix on the app class alone
The welcome card sits above the layers button and legend
Sub-page top bar no longer balloons into an empty white pill
Fall back to the plain write if the store ever refuses the compare-and-set
Throttle brand-new web push subscriptions per IP
Fail the monitor and healthchecks when pushes stop arriving
Block pages pass the shared curb side on to the live map
Shared block links open the side that was shared
Pin Sweep alerts and Calendar to the bottom of the phone sheet
Offer the free iPhone app when Safari users want alerts
A Turn off or block switch mid-write can no longer be undone by the cron
Show house-number ranges on block pages
Open the map on the neighborhood, not Civic Center
Say San Francisco on every neighborhood page
Redirect the curb-nu.vercel.app home page too
Time out a push service that never answers
Street search, deep-link overview race, stale caches, and sheet keyboard gaps (audit)
Keep the alert and calendar buttons while a block is being swept
A ready-made wait-for-verify script for the ship gate
Verify claude/ branches with tests and a real-browser walk before they ship
Wake an on-call Claude routine when an alert opens or changes
Retry a dropped connection once before "Couldn't load that area"
Watch App Store reviews and alert on unanswered low ones
Join cross streets with a slash in /b/ titles, not an ampersand
No dangling "&…" in clipped /b/ titles
Bump the sweep-core script version for sweepCountdown
Dash-free neighborhood pages
Dash-free /b/ pages and share cards
Write the map's UI copy without dashes
Drop dashes from every push title and body
Use the canonical fine and ticket-timing numbers
Say "tomorrow" only for the next SF calendar day
Keep visitors' error text out of public issues and logs
Vercel Cron as a second 15-minute sweep-alert timer (team is on Pro)
Don't send the iOS delivery test to watches turned off
Land the Turn off row above the home-indicator inset
Keep error-log text from running workflow commands in the Actions log
Ask for precise location at most once per launch; final 1.0.2 notes
List all 12,253 block pages and redirect the curb-nu.vercel.app duplicate
Treat a location denial after a timed-out first try as the visitor's choice
Drop the delivery-test input from the backup sender workflow
Word a night sweep's push for the morning after SF midnight
Leave /b/ block pages to the network and purge the v3 cache
Don't claim the backup is sending when QStash stops
Never re-arm a watch the user turned off during a run
Report a failed DataSF load with its HTTP status, not "0"
Don't let a stale sheet move a re-armed watch back
Report /b/ failures the way api/block.js fails now
Scroll the Turn off / Keep them on row into view at the peek
Stop the sender check flapping while only the GitHub backup runs
Keep the push de-dupe across turn off/on and re-arms
Alert only on real breakage, not visitors' own location choices
Report the last QStash run in the sender status
Read build 7's one-object push result so denials reach Settings guidance
Free the sender run lock after a fully successful run
Rate-limit error reports per client before the global cap
Never render error-log text as live Markdown in public alert issues
Underscore-prefix handler tests so Vercel never deploys them as functions
Pass the save error, not the operator note, to the page
A late fix no longer flies the map after the user panned
Make indexnow refuse a --since ref that doesn't exist
Bake only numeric cnns
Repair clipped cross streets toward the street's own name
Don't revive a months-old legacy alert on sheet open
A same-sweep re-save keeps the stored eve/morning anchors
Queue iOS test pushes behind in-flight saves
Don't time out an iOS arm while the permission prompt is up
Test push no longer previews a 5 AM morning-of that never fires
Pass the save-subscription status and reason through to the page
Native locate answers inside its deadline, reports real permission
First tap finds you; honest copy; coarse fixes shown as an area
Open the block only once data covering it is drawn
Link the neighborhood chart labels to their /n/ pages
Smooth the mobile block sheet and stop the iOS app rubber-banding
Link every neighborhood page from the home page's static HTML
Version the sweep-core script so the page never runs a stale core
Watch the real sender, let QStash drive the monitor
IndexNow key + `npm run indexnow` for changed URLs
Sheet shows the real alert state, with an off switch
Let crawlers fetch /api/og share-card images
Real lastmod in both sitemaps, /support listed, block sitemap from baked data
List every block on /n/ pages, nearby by border, retire stale pages
Serve /b/ pages from baked schedules; 404 unknown, 503 on failure
Label test pushes, keep only act-now pushes on screen
Bake every swept block's schedule into data/schedules.json
Server-side off switch + stop the iOS 60 s save throttle
QStash as the primary sweep-alert trigger, with a status record
Watch every rule of a multi-day curb side
One "move it tonight" push for night sweeps + timing hardening
Shared push-anchor rule + holiday table through 2028
Catch breakage before users do — smoke checks, browser walk, error log, heartbeat
Self-hosted parchment basemap, $0
Move DataSF calls to data.sf.gov
Block-page sitemap — ~10.5k long-tail /b/<cnn> landing pages
Real DPW sweeper routes — Truck Routes layer + block sheet
Drop build:enforcement from data-refresh (needs a local xlsx)
June 30 #26-5451 batch — denser export, 190 -> 227 blocks
Vercel Speed Insights via shared chrome + index head
More space below the timelapse + drop the stroke under it
Harden push-bridge re-tap + assert LocationBridge main-thread; build 6
Resolve first-launch locate timeout; bump to 1.0.1 (build 5)
Design timelapse + full history generated from git
Richer 'In the news' rows — publisher logos, specific dates, author
/support page + Support links in nav + footer
Add the evening June 29 #26-5451 batch — 184 -> 190 blocks
Real section separation + bigger gallery, scrollbar, download previews
More pronounced rounded corners + corner-shape on pseudo-elements
Changelog/privacy nav layout + press-kit section spacing
Force free CARTO basemap — stop all Google Maps Tiles calls (billing)
How-it-works as a secondary (ghost) button; drop footer bottom divider
Submenu icons, content-width pill, press tags, leaner ⓘ menu + onboarding
Full-width pill nav + button shadow, white dropdowns, light footer w/ logo
Floating pill nav + smooth (squircle) corners site-wide
Tighten the ⓘ info menu — prioritized hierarchy, ~half the length
Identical nav+footer on every page + reveal-on-scroll-up, borderless
One consistent nav + footer across every back-of-map page
Add the June 29 #26-5451 batch — coverage 118 -> 184 blocks
Add SFGate + The Dissent SF coverage to the In-the-news list
Make the surge caveat a clear asterisk callout
Commit the GPS hoods builder + warn that build:stats reverts per-hood totals
Docs+fix: correct README pipeline/numbers, footnote the surge baseline, validate sweeps.json
Regenerate neighborhood stats from GPS + correct stale numbers site-wide
Expand sweeper coverage, publish the SF GPS dataset, add a changelog
Label the sweeper-pass times as the city's REAL GPS (keep routes Beta)
Rainbow-outlined logo (30° gradient), drop modal rule, run through June
Festive Pride-weekend touch on the map (date-gated, auto-retires)
Real "when the sweeper passes" from SF Public Works AVL GPS (#26-5451)
Funding rails -- funding.json (FLOSS/fund manifest), FUNDING.yml, Code of Conduct
Correct ticket-timing stats from the complete GPS dataset
Rebuild enforcement.json from the complete GPS citation record (#26-5453)
Inline the Google logo with the attribution, drop the white box
Show the Google logo alongside the per-viewport attribution (Map Tiles policy)
Press kit page at /press (noindex), linked subtly in footers
Self-activating 'Get the iOS app' App Store link in the info menu
Configurable push-notification cadence, voice, and on-device self-test
Divider between pages and the rest, add Privacy, drop redundant Report-a-bug
Self-activating 'Rate CURB' — lights up via iTunes lookup once we're on the App Store
Wire Correct-a-Sign to the existing wrong-data form + add Share/Send-feedback menu items
Correct a Sign — report a wrong block straight to a pre-filled GitHub issue
Remember Google's daily quota outage per SF-day, skip straight to CARTO
Stop the attribution refresher from re-adding Google credit after CARTO fallback
Fall back to CARTO when Google tiles fail to load (not just on createSession failure)
Scope .src grid rules to .srcs so they stop clobbering the proof paragraph
Size up holiday-card icon to 30px for vertical balance
Use the gallery ICONS.cal glyph on the holiday card
Make the holiday note a card (green, Anton headline, calendar icon)
Add Juneteenth holiday + surface 'no sweeping — city holiday' note
Surface the 'park after the sweeper passes' rule
Phase 2 — per-neighborhood curb-mix + off-street garages
Enrich neighborhood pages — enforcement explainer + high-intent FAQs
Instrument the activation funnel
Add breathing room above the open-source card
Add 'The receipts' data-sources + methodology section
Refresh social-preview cards
App Store screenshot framer (iPhone captures → 1290x2796 marketing PNGs)
"22 Minutes" launch trailer generator
Match install icons to the padded native app icon
Un-cropped app icon — padded cube, flattened opaque
Preserve cold-start notification deep link + flag denied permission
Harden APNs delivery against transient + abuse failure modes
Authed ?test=ios delivery test + workflow_dispatch input
Accept APNS_KEY_P8_B64 (base64 PEM) — mangle-proof key input
Robust APNs key loader (recover from whitespace-collapsed .p8)
Isolate APNs failures from the cron + surface the error
One back button on internal pages + uncropped app icon
Report ios.configured + always count iOS watches
Cross-host APNs retry before pruning a token
Native push client — APNs registration bridge + deep links
Native iOS APNs transport alongside Web Push (ALE backend)
Native bridges for Share and the .ics calendar reminder
Service worker stale-while-revalidate (instant + fresh)
Switch to the WKWebView wrapper (matches the live site) + native-feel polish
Revive the native SwiftUI/MapKit app + fix it to compile
Continue WKWebView conversion on the native target
Unify the site footer across all internal pages
Neighborhood map snapshots, live-map embed, landing data points
?bbox + ?embed deep-link for neighborhood map embeds
Give the top bar breathing room from the screen edge
Make the "Back to map" button subtle
Drop the logo hover tooltip
Remove move-mode, "your car" strip, and smart-pin prompt
WKWebView wrapper on the native target (parallel pivot)
Guard the locate button with a loading failsafe
"Back to map" button + scroll fix on sub-pages
Make ticket bar charts render — fill was an inline span
Per-block dynamic Open Graph cards
"find a safe spot" move-mode + smart-pin prompt (ALE-164/168)
"your car" persistent status strip + pin=parked
Redesigned hood cards, unified nav/footer, about open-source CTA, logo tooltip
Logo hover scales instead of lifting
/api/parked auto-park endpoint + token auth, appsec-hardened
Server-side forever-watch — recurring sweep alerts (ALE-168/164)
Cooler grey streets + green parks in the basemap theme
Neighborhood street-cleaning pages
Perf(map)+test: overview recolor-not-rebuild + extract & test SF time core
Monthly data-refresh Action + shape validator
Wire 5 cookieless custom events
Outlined logo refresh + sheet/UX polish
New parking-meter icon for the Metered chip
Align the toolbar — clear the close button's stray top/right offsets
Toolbar tooltips drop down (not cropped) + cleaner permit chip
Preconnect to tile.googleapis.com (now the live basemap host)
Clear the launch-check punch list
Permit chip names the area + taps to outline it
Share & location buttons were dead — close button's hit-area blanketed the toolbar
Full day names in heads-up (Saturdays, not Sats)
Day-filter heads-up — contextualize the sparse weekend view
Redesign block card — no redundancy, block-accurate meters, cleaner
Bare-cube logo everywhere + unify red to logo #C1121F
New curb-cube logo across app, favicons, PWA icons & OG
Launch refresh — all five assets rebuilt, overview carries holidays
QA punch list — every finding from the 7-agent pre-launch sweep
Escalating two-push model — night-before + 30-min
SF-pinned time + SFMTA holiday suspensions (ALE-162 items 1-2)
Data-defense memo, legality FAQ, competitive reply arsenal
Llms.txt — agent-readable map of pages and data endpoints
De-dup the block card — every number appears once
Open-source presence everywhere — repo one tap away on every surface
Close the animation gaps — newer surfaces join the gated system
Vercel Web Analytics script on all pages (cookieless, free tier)
Legend bottom edge aligns with the zoom pill on both breakpoints
Mobile corner relayout + unified 48px top row + no default-blue links
Drop redundant tooltip from the sheet close button
Freshness date on /tickets, article timestamps, org sameAs
Dataset schema on /tickets + growth plan
Unmetered white zones — passenger loading incl. school zones
Weather icons in the app's duotone icon language, not emoji
Widen desktop top bar so the day row fits the weather chip
Live SF weather on the date chip
Permit-area dropdowns show each area's sign-disc color
Google-style layer tiles, dynamic legend, permit-area dropdowns
Shared footer across internal pages + icons in the hamburger menu
Restore side gutters — padding shorthand was zeroing .wrap
Top nav on /tickets and /about — inline links, hamburger under 680px
Phone-native chart layouts under 520px
Hover tooltips on every chart + clearer labels
Report-a-bug links (GitHub Issues) + bio card on /about
Neighborhood ticket-surge chart on /tickets, press links + maker note on /about
Truck-routes Beta explainer on /about + free 15-min alerts scheduler
Complete overview when a viewport exceeds the row cap + day rollover
Info menu hub for all pages + truck-route day label
Zoom-aware rendering so every layer holds up in/out
Truck routes independent of curb-color toggles
Basemap fallback DNS dead; locate back in the search field; desktop tooltips
Bottom-left legend, joined zoom pill, floating locate; routes flow fix
Legend-first rows — map symbols + eye toggles + Beta tag
/tickets — the SF parking ticket economy, visualized
Launch-hardening quick wins from verified deep research
Share-a-block — /b/<cnn> pages, Share button, deep link
Unhappy paths on search, filters, coverage, connectivity
Preconnects, chunked citywide draw, static zones asset
Purposeful micro-animations, reduced-motion gated
Trim /about title to 54 chars (was 61, over the ~60 truncation line)
Canonicals, robots, sitemap, structured data, FAQ content
Citywide overview — curb lines visible at every zoom
Uniform show/hide toggle UI; routes actually visible
Area boundary territory, status show/hide, truck routes v2
Google-style autocomplete
Mobile QA fixes, metered-parking layer, inferred truck routes (beta)
Google-Maps-style corner organization
Logo reopens the welcome explainer
Disc picker — colored circles exactly like the parking signs
Adopt the alevizio pop icon set; sign design inside the app; kill italics
Authentic SF sign stack on landing + permit-area browser in the app
Distill pass from design critique — peek, two actions, drawn glyphs
First-run welcome + first-verdict alerts toast
Curb.guide landing page — "an official notice you actually want to read"
AA status-text tokens, focus/ARIA/keyboard/targets; auto-locate on launch
Street-wide zoom-scaled ribbon instead of per-side offset bands
De-dupe enforcement, switchable sides, hover/press states
Desktop UX, hover previews, day filter, loading zones, enforcement & ticket-time overlay
Precompute real-world street-cleaning enforcement times
Branded 1200x630 social card + canonical curb.guide URLs
Fix curb side matching for address search
Deliver Google Maps key via gitignored config.js (local) + env-injected /config.js (Vercel)
Official Google Map Tiles basemap with CARTO fallback; open at street zoom
Initial commit: CURB — SF parking PWA with Web Push alerts
Built solo, in the open, on San Francisco's public data — see every commit on GitHub →