Changelog.

CURB is built in the open — here's the whole thing, commit by commit, newest first. The complete history also lives on GitHub.

CURB on June 8, 2026
From a windshield to this

Watch CURB
take shape.

Three weeks, 213 commits — the same screen from June 8 to June 29, 2026.

October 2, 2026

Fix

Neighborhood totals by the city's own label, rolling 24 months

Fix

Steiner example from the 200 block, plain sourcing, no 'complete record', owner's quotes

Fix

Correct stale and false numbers across the site before launch

October 1, 2026

New

A failed monthly data refresh opens an alert and wakes the on-call routine

New

Retry a dropped Leaflet or time core, then say CURB didn't load

Fix

Precache the time core with the app shell

Fix

Name Meta's crawlers in the group, drop the broad Allow

Fix

A failed script or icon request fails cleanly, not with the app shell

Fix

Keep crawlers off the live map deep links

Fix

Skip reports from self-declared crawlers

Design

One time core per city, SF is the default instance

September 30, 2026

New

Keep the logo on phones, still no white pill

New

Phones show just the ≡ button, no white nav pill

iOS

Key the sub-page top bar fix on the app class alone

Fix

The welcome card sits above the layers button and legend

iOS

Sub-page top bar no longer balloons into an empty white pill

Fix

Fall back to the plain write if the store ever refuses the compare-and-set

Fix

Throttle brand-new web push subscriptions per IP

New

Fail the monitor and healthchecks when pushes stop arriving

Fix

Block pages pass the shared curb side on to the live map

Fix

Shared block links open the side that was shared

New

Pin Sweep alerts and Calendar to the bottom of the phone sheet

iOS

Offer the free iPhone app when Safari users want alerts

Fix

A Turn off or block switch mid-write can no longer be undone by the cron

New

Show house-number ranges on block pages

Fix

Open the map on the neighborhood, not Civic Center

New

Say San Francisco on every neighborhood page

Fix

Redirect the curb-nu.vercel.app home page too

Fix

Time out a push service that never answers

Fix

Street search, deep-link overview race, stale caches, and sheet keyboard gaps (audit)

Fix

Keep the alert and calendar buttons while a block is being swept

New

A ready-made wait-for-verify script for the ship gate

New

Verify claude/ branches with tests and a real-browser walk before they ship

September 29, 2026

New

Wake an on-call Claude routine when an alert opens or changes

Fix

Retry a dropped connection once before "Couldn't load that area"

September 28, 2026

iOS

Watch App Store reviews and alert on unanswered low ones

September 27, 2026

Fix

Join cross streets with a slash in /b/ titles, not an ampersand

Fix

No dangling "&…" in clipped /b/ titles

Fix

Bump the sweep-core script version for sweepCountdown

Fix

Dash-free neighborhood pages

Fix

Dash-free /b/ pages and share cards

Fix

Write the map's UI copy without dashes

Fix

Drop dashes from every push title and body

Fix

Use the canonical fine and ticket-timing numbers

Fix

Say "tomorrow" only for the next SF calendar day

Fix

Keep visitors' error text out of public issues and logs

New

Vercel Cron as a second 15-minute sweep-alert timer (team is on Pro)

iOS

Don't send the iOS delivery test to watches turned off

Fix

Land the Turn off row above the home-indicator inset

Fix

Keep error-log text from running workflow commands in the Actions log

iOS

Ask for precise location at most once per launch; final 1.0.2 notes

New

List all 12,253 block pages and redirect the curb-nu.vercel.app duplicate

Fix

Treat a location denial after a timed-out first try as the visitor's choice

Fix

Drop the delivery-test input from the backup sender workflow

Fix

Word a night sweep's push for the morning after SF midnight

Fix

Leave /b/ block pages to the network and purge the v3 cache

Fix

Don't claim the backup is sending when QStash stops

Fix

Never re-arm a watch the user turned off during a run

Fix

Report a failed DataSF load with its HTTP status, not "0"

Fix

Don't let a stale sheet move a re-armed watch back

Fix

Report /b/ failures the way api/block.js fails now

Fix

Scroll the Turn off / Keep them on row into view at the peek

Fix

Stop the sender check flapping while only the GitHub backup runs

Fix

Keep the push de-dupe across turn off/on and re-arms

Fix

Alert only on real breakage, not visitors' own location choices

New

Report the last QStash run in the sender status

Fix

Read build 7's one-object push result so denials reach Settings guidance

Fix

Free the sender run lock after a fully successful run

Fix

Rate-limit error reports per client before the global cap

Fix

Never render error-log text as live Markdown in public alert issues

Fix

Underscore-prefix handler tests so Vercel never deploys them as functions

iOS

Pass the save error, not the operator note, to the page

Fix

A late fix no longer flies the map after the user panned

Fix

Make indexnow refuse a --since ref that doesn't exist

Fix

Bake only numeric cnns

Fix

Repair clipped cross streets toward the street's own name

Fix

Don't revive a months-old legacy alert on sheet open

Fix

A same-sweep re-save keeps the stored eve/morning anchors

iOS

Queue iOS test pushes behind in-flight saves

iOS

Don't time out an iOS arm while the permission prompt is up

Fix

Test push no longer previews a 5 AM morning-of that never fires

iOS

Pass the save-subscription status and reason through to the page

iOS

Native locate answers inside its deadline, reports real permission

Fix

First tap finds you; honest copy; coarse fixes shown as an area

Fix

Open the block only once data covering it is drawn

New

Link the neighborhood chart labels to their /n/ pages

iOS

Smooth the mobile block sheet and stop the iOS app rubber-banding

New

Link every neighborhood page from the home page's static HTML

Fix

Version the sweep-core script so the page never runs a stale core

New

Watch the real sender, let QStash drive the monitor

New

IndexNow key + `npm run indexnow` for changed URLs

Fix

Sheet shows the real alert state, with an off switch

Fix

Let crawlers fetch /api/og share-card images

New

Real lastmod in both sitemaps, /support listed, block sitemap from baked data

New

List every block on /n/ pages, nearby by border, retire stale pages

Fix

Serve /b/ pages from baked schedules; 404 unknown, 503 on failure

Fix

Label test pushes, keep only act-now pushes on screen

New

Bake every swept block's schedule into data/schedules.json

iOS

Server-side off switch + stop the iOS 60 s save throttle

New

QStash as the primary sweep-alert trigger, with a status record

Fix

Watch every rule of a multi-day curb side

New

One "move it tonight" push for night sweeps + timing hardening

New

Shared push-anchor rule + holiday table through 2028

New

Catch breakage before users do — smoke checks, browser walk, error log, heartbeat

New

Self-hosted parchment basemap, $0

Fix

Move DataSF calls to data.sf.gov

July 4, 2026

New

Block-page sitemap — ~10.5k long-tail /b/<cnn> landing pages

July 1, 2026

New

Real DPW sweeper routes — Truck Routes layer + block sheet

Fix

Drop build:enforcement from data-refresh (needs a local xlsx)

June 30, 2026

Data

June 30 #26-5451 batch — denser export, 190 -> 227 blocks

New

Vercel Speed Insights via shared chrome + index head

June 29, 2026

Design

More space below the timelapse + drop the stroke under it

iOS

Harden push-bridge re-tap + assert LocationBridge main-thread; build 6

iOS

Resolve first-launch locate timeout; bump to 1.0.1 (build 5)

New

Design timelapse + full history generated from git

New

Richer 'In the news' rows — publisher logos, specific dates, author

New

/support page + Support links in nav + footer

Data

Add the evening June 29 #26-5451 batch — 184 -> 190 blocks

Fix

Real section separation + bigger gallery, scrollbar, download previews

New

More pronounced rounded corners + corner-shape on pseudo-elements

Fix

Changelog/privacy nav layout + press-kit section spacing

Fix

Force free CARTO basemap — stop all Google Maps Tiles calls (billing)

New

How-it-works as a secondary (ghost) button; drop footer bottom divider

New

Submenu icons, content-width pill, press tags, leaner ⓘ menu + onboarding

New

Full-width pill nav + button shadow, white dropdowns, light footer w/ logo

New

Floating pill nav + smooth (squircle) corners site-wide

New

Tighten the ⓘ info menu — prioritized hierarchy, ~half the length

Fix

Identical nav+footer on every page + reveal-on-scroll-up, borderless

New

One consistent nav + footer across every back-of-map page

Data

Add the June 29 #26-5451 batch — coverage 118 -> 184 blocks

New

Add SFGate + The Dissent SF coverage to the In-the-news list

New

Make the surge caveat a clear asterisk callout

Fix

Commit the GPS hoods builder + warn that build:stats reverts per-hood totals

New

Docs+fix: correct README pipeline/numbers, footnote the surge baseline, validate sweeps.json

Fix

Regenerate neighborhood stats from GPS + correct stale numbers site-wide

New

Expand sweeper coverage, publish the SF GPS dataset, add a changelog

New

Label the sweeper-pass times as the city's REAL GPS (keep routes Beta)

June 28, 2026

New

Rainbow-outlined logo (30° gradient), drop modal rule, run through June

New

Festive Pride-weekend touch on the map (date-gated, auto-retires)

June 26, 2026

New

Real "when the sweeper passes" from SF Public Works AVL GPS (#26-5451)

June 25, 2026

New

Funding rails -- funding.json (FLOSS/fund manifest), FUNDING.yml, Code of Conduct

New

Correct ticket-timing stats from the complete GPS dataset

Data

Rebuild enforcement.json from the complete GPS citation record (#26-5453)

June 23, 2026

New

Inline the Google logo with the attribution, drop the white box

Fix

Show the Google logo alongside the per-viewport attribution (Map Tiles policy)

June 22, 2026

New

Press kit page at /press (noindex), linked subtly in footers

iOS

Self-activating 'Get the iOS app' App Store link in the info menu

New

Configurable push-notification cadence, voice, and on-device self-test

June 19, 2026

New

Divider between pages and the rest, add Privacy, drop redundant Report-a-bug

iOS

Self-activating 'Rate CURB' — lights up via iTunes lookup once we're on the App Store

New

Wire Correct-a-Sign to the existing wrong-data form + add Share/Send-feedback menu items

New

Correct a Sign — report a wrong block straight to a pre-filled GitHub issue

June 18, 2026

Fix

Remember Google's daily quota outage per SF-day, skip straight to CARTO

Fix

Stop the attribution refresher from re-adding Google credit after CARTO fallback

Fix

Fall back to CARTO when Google tiles fail to load (not just on createSession failure)

Fix

Scope .src grid rules to .srcs so they stop clobbering the proof paragraph

Design

Size up holiday-card icon to 30px for vertical balance

Design

Use the gallery ICONS.cal glyph on the holiday card

New

Make the holiday note a card (green, Anton headline, calendar icon)

New

Add Juneteenth holiday + surface 'no sweeping — city holiday' note

New

Surface the 'park after the sweeper passes' rule

June 17, 2026

New

Phase 2 — per-neighborhood curb-mix + off-street garages

New

Enrich neighborhood pages — enforcement explainer + high-intent FAQs

New

Instrument the activation funnel

Fix

Add breathing room above the open-source card

New

Add 'The receipts' data-sources + methodology section

New

Refresh social-preview cards

June 16, 2026

iOS

App Store screenshot framer (iPhone captures → 1290x2796 marketing PNGs)

New

"22 Minutes" launch trailer generator

Fix

Match install icons to the padded native app icon

iOS

Un-cropped app icon — padded cube, flattened opaque

iOS

Preserve cold-start notification deep link + flag denied permission

iOS

Harden APNs delivery against transient + abuse failure modes

iOS

Authed ?test=ios delivery test + workflow_dispatch input

Fix

Accept APNS_KEY_P8_B64 (base64 PEM) — mangle-proof key input

iOS

Robust APNs key loader (recover from whitespace-collapsed .p8)

iOS

Isolate APNs failures from the cron + surface the error

iOS

One back button on internal pages + uncropped app icon

iOS

Report ios.configured + always count iOS watches

iOS

Cross-host APNs retry before pruning a token

iOS

Native push client — APNs registration bridge + deep links

iOS

Native iOS APNs transport alongside Web Push (ALE backend)

June 15, 2026

iOS

Native bridges for Share and the .ics calendar reminder

Fix

Service worker stale-while-revalidate (instant + fresh)

iOS

Switch to the WKWebView wrapper (matches the live site) + native-feel polish

iOS

Revive the native SwiftUI/MapKit app + fix it to compile

iOS

Continue WKWebView conversion on the native target

Design

Unify the site footer across all internal pages

New

Neighborhood map snapshots, live-map embed, landing data points

New

?bbox + ?embed deep-link for neighborhood map embeds

Fix

Give the top bar breathing room from the screen edge

Design

Make the "Back to map" button subtle

Design

Drop the logo hover tooltip

New

Remove move-mode, "your car" strip, and smart-pin prompt

iOS

WKWebView wrapper on the native target (parallel pivot)

Fix

Guard the locate button with a loading failsafe

New

"Back to map" button + scroll fix on sub-pages

Fix

Make ticket bar charts render — fill was an inline span

June 13, 2026

New

Per-block dynamic Open Graph cards

New

"find a safe spot" move-mode + smart-pin prompt (ALE-164/168)

New

"your car" persistent status strip + pin=parked

New

Redesigned hood cards, unified nav/footer, about open-source CTA, logo tooltip

Fix

Logo hover scales instead of lifting

New

/api/parked auto-park endpoint + token auth, appsec-hardened

New

Server-side forever-watch — recurring sweep alerts (ALE-168/164)

New

Cooler grey streets + green parks in the basemap theme

New

Neighborhood street-cleaning pages

New

Perf(map)+test: overview recolor-not-rebuild + extract & test SF time core

New

Monthly data-refresh Action + shape validator

New

Wire 5 cookieless custom events

New

Outlined logo refresh + sheet/UX polish

New

New parking-meter icon for the Metered chip

Fix

Align the toolbar — clear the close button's stray top/right offsets

Fix

Toolbar tooltips drop down (not cropped) + cleaner permit chip

Fix

Preconnect to tile.googleapis.com (now the live basemap host)

June 12, 2026

Fix

Clear the launch-check punch list

New

Permit chip names the area + taps to outline it

Fix

Share & location buttons were dead — close button's hit-area blanketed the toolbar

Fix

Full day names in heads-up (Saturdays, not Sats)

New

Day-filter heads-up — contextualize the sparse weekend view

New

Redesign block card — no redundancy, block-accurate meters, cleaner

New

Bare-cube logo everywhere + unify red to logo #C1121F

New

New curb-cube logo across app, favicons, PWA icons & OG

Data

Launch refresh — all five assets rebuilt, overview carries holidays

Fix

QA punch list — every finding from the 7-agent pre-launch sweep

New

Escalating two-push model — night-before + 30-min

New

SF-pinned time + SFMTA holiday suspensions (ALE-162 items 1-2)

New

Data-defense memo, legality FAQ, competitive reply arsenal

New

Llms.txt — agent-readable map of pages and data endpoints

New

De-dup the block card — every number appears once

New

Open-source presence everywhere — repo one tap away on every surface

New

Close the animation gaps — newer surfaces join the gated system

New

Vercel Web Analytics script on all pages (cookieless, free tier)

Fix

Legend bottom edge aligns with the zoom pill on both breakpoints

New

Mobile corner relayout + unified 48px top row + no default-blue links

Fix

Drop redundant tooltip from the sheet close button

New

Freshness date on /tickets, article timestamps, org sameAs

New

Dataset schema on /tickets + growth plan

New

Unmetered white zones — passenger loading incl. school zones

New

Weather icons in the app's duotone icon language, not emoji

Fix

Widen desktop top bar so the day row fits the weather chip

New

Live SF weather on the date chip

New

Permit-area dropdowns show each area's sign-disc color

New

Google-style layer tiles, dynamic legend, permit-area dropdowns

New

Shared footer across internal pages + icons in the hamburger menu

Fix

Restore side gutters — padding shorthand was zeroing .wrap

New

Top nav on /tickets and /about — inline links, hamburger under 680px

New

Phone-native chart layouts under 520px

New

Hover tooltips on every chart + clearer labels

New

Report-a-bug links (GitHub Issues) + bio card on /about

New

Neighborhood ticket-surge chart on /tickets, press links + maker note on /about

New

Truck-routes Beta explainer on /about + free 15-min alerts scheduler

Fix

Complete overview when a viewport exceeds the row cap + day rollover

June 11, 2026

New

Info menu hub for all pages + truck-route day label

Fix

Zoom-aware rendering so every layer holds up in/out

Fix

Truck routes independent of curb-color toggles

Fix

Basemap fallback DNS dead; locate back in the search field; desktop tooltips

New

Bottom-left legend, joined zoom pill, floating locate; routes flow fix

Design

Legend-first rows — map symbols + eye toggles + Beta tag

June 10, 2026

New

/tickets — the SF parking ticket economy, visualized

Fix

Launch-hardening quick wins from verified deep research

New

Share-a-block — /b/<cnn> pages, Share button, deep link

Fix

Unhappy paths on search, filters, coverage, connectivity

Fix

Preconnects, chunked citywide draw, static zones asset

New

Purposeful micro-animations, reduced-motion gated

Fix

Trim /about title to 54 chars (was 61, over the ~60 truncation line)

New

Canonicals, robots, sitemap, structured data, FAQ content

New

Citywide overview — curb lines visible at every zoom

Fix

Uniform show/hide toggle UI; routes actually visible

New

Area boundary territory, status show/hide, truck routes v2

New

Google-style autocomplete

New

Mobile QA fixes, metered-parking layer, inferred truck routes (beta)

Design

Google-Maps-style corner organization

New

Logo reopens the welcome explainer

New

Disc picker — colored circles exactly like the parking signs

New

Adopt the alevizio pop icon set; sign design inside the app; kill italics

New

Authentic SF sign stack on landing + permit-area browser in the app

Design

Distill pass from design critique — peek, two actions, drawn glyphs

June 9, 2026

New

First-run welcome + first-verdict alerts toast

New

Curb.guide landing page — "an official notice you actually want to read"

Fix

AA status-text tokens, focus/ARIA/keyboard/targets; auto-locate on launch

Fix

Street-wide zoom-scaled ribbon instead of per-side offset bands

New

De-dupe enforcement, switchable sides, hover/press states

New

Desktop UX, hover previews, day filter, loading zones, enforcement & ticket-time overlay

New

Precompute real-world street-cleaning enforcement times

New

Branded 1200x630 social card + canonical curb.guide URLs

New

Fix curb side matching for address search

June 8, 2026

New

Deliver Google Maps key via gitignored config.js (local) + env-injected /config.js (Vercel)

New

Official Google Map Tiles basemap with CARTO fallback; open at street zoom

New

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 →