What changed on CROL-List, newest first.
Recent updates
- — Open any agency page and you now see who runs the agency, its website, and its budget — pulled straight from the City's own data, not typed in by hand. A small label shows exactly which public dataset each fact came from, so you can check it yourself. If an agency is not in the City's roster, the page simply shows its City Record name and moves on. It is fast because the match is prepared ahead of time, so nothing is fetched while you wait.
- — You can download the agency-name reconciliation instead of rebuilding it. The crosswalk keeps each source spelling visible and shows which names this site connects. Anyone, including the City, can adopt or improve the same connection. It is not a competing registry.
- — Some agencies don't file their awards in the City Record — they post them elsewhere. CROL-List now checks those outside sources for you: it shows what it finds, links to the source, and says so honestly when nothing has turned up yet. If a notice has no award on file, you can ask to be emailed the moment one appears — click "Email me when the award registers," confirm your email once, and you're done. No extra emails until there's real news.
Screen recordingFind a covered notice, choose the award watch, enter reader@example.com, and reach the email confirmation step. - — Click a link in a CROL-List digest email. You used to land on a bare notice page. Now you see why it matched. The matching word is highlighted. You also see a plain summary of your watch.
- — Has a saved alert gone quiet? If it finds nothing new for a couple of months, its next email says so. That email links back to the alerts page. Your exact search is already loaded there. You can broaden it in one step.
- — Notice pages now show whether a recurring bid was awarded before, and to whom — not just its own paper trail. When there's no confirmed match, you can choose "Show possible earlier rounds" to see looser, clearly-marked possibilities instead of a dead end.
- — The stats page's "all time" numbers, topic/lens breakdowns, and day-by-day history now say exactly how far back they can honestly account for — no more numbers that quietly undercount, and no more "since launch" where that isn't true. Digests, searches, and now active watches are also easier to read at a glance, with the technical plumbing (feed fetches, API checks) moved to its own clearly-labeled section at the bottom.
- — Typing a full sentence like "education contracts over $200K due in 3 months" into an alert now matches the category, amount, and deadline together — wherever you type it: the 60-second quiz, the "Ask" box, or Build an alert. You'll see the real, interpreted results before you subscribe. A single word or a quoted phrase still searches literally as before.
Screen recordingPick the "City contracts and RFPs" topic, type a full sentence, and preview the real, interpreted results. - — Alert emails and the "Preview my digest" tool now show exactly which word matched and where — no more guessing why an unrelated-looking notice showed up in your search results.
- — Opening the Land or Staffing tab for the first time now shows a real, current example — a live rezoning application, or the city's most common job title with its salary band and career ladder — instead of an empty panel waiting for you to search. Your own searches and shared links work exactly as before.
- — The stats page now shows day-by-day history of digests sent and searches asked, with recovered and live-counted days honestly labeled.
- — You can now build an alert that watches one agency, or only awards, or only open solicitations, not just an amount or a deadline.
- — The stats page now uses plain-language labels, shows all-time totals, and breaks down digest matches by topic.
- — The Money tab is now called Contracts, and a notice page now leads with that notice's own facts before agency-wide totals.
- — The homepage now says how many notices came in today, digest email titles are clickable, and a new tagline explains what the site does.
- — You can now read every page in Arabic and Urdu, right to left.
- — You can now read the site in Bengali, Haitian Creole, Korean, French, and Polish.
- — You can now read the site in Chinese (Simplified) and Russian.
- — Closed the last known accessibility gaps: every control now has a visible focus ring, an accurate label, and enough color contrast to read.
- — Every page, not just the homepage, now translates into Español, and your language choice is remembered across visits.
Earlier releases
The detailed technical notes below each release (bullet lists, incident reports) remain in English for now.
2026.07.10 · Espanol coverage: the whole interface, not just the chrome
Para usted — Phase 2 of Spanish support: the entire visible interface
now translates when you switch to Espanol. Phase 1 covered tabs, buttons, and short labels (98 keys).
Phase 2 adds the empty states, search placeholders, panel headings, the Today's Edition strip,
alert builder labels and parameters, loading messages, and all control labels across every lens
(Money, People, Land, Property, Rules, Meetings, Alerts) -- growing the dictionary from 98 to
over 200 keys. A new residual-English coverage gate in the test suite verifies 15 high-visibility
sentinel strings are absent in Espanol mode.
- Dictionary grows from 98 to 200+ keys; all new keys carry full en + es translations.
- Static HTML:
data-i18nattributes on all translatable labels, options, buttons, and headings. Newdata-i18n-placeholderattribute pattern for search inputs. - JavaScript: hardcoded English strings in
renderToday, loading states, empty states, and dynamic label assignments replaced witht()calls. - Test spec
12_language.pyextended with a residual-English sentinel gate: 15 high-visibility phrases must be absent in Espanol mode. - Machine-translated; pending native review through community partners.
2026.07.10 · Spanish support + style-guide copy pass
For you — A language switcher now appears in the header (English
/ Espanol). Choosing Spanish translates all tabs, chips, and messages in the UI. Notices
themselves stay in English, which is the official language of the City Record. Your preference
is remembered across visits. Separately, time chips, deadline chips, and the feedback-category
selector were updated to follow the NYC Web Content Style Guide: "9 a.m." (not "9 AM"), spelled-out
numbers ("closes in two days"), and acronym expansions on first use (RFP, M/WBE, ZAP).
City Record content is now marked
translate="no" so machine-translation tools
leave it intact.- Language switcher (English / Espanol) with USWDS-pattern native-language labels, stored
in localStorage, and
aria-pressedfor keyboard users. - Runtime dictionary (
i18n.js) with 98 keys in English and Spanish — no build step, plain script tag. Spanish is machine-translated and pending native review through community partners. - Confirmation and digest emails deliver in the subscriber's chosen language.
translate="no"on all notice-data containers;langattribute on all language-labeled spans and UI chrome.- Key parity lint added to CI: a missing translation key fails the build.
2026.07.10 · Accessibility: an enforced floor, not a promise
For you — If you use a keyboard or a screen reader, the rough edges
are getting fixed for real: the feedback form's category picker now works without a mouse, the
plain-English search box announces itself properly, low-contrast text is corrected site-wide,
and the "minimum award" filter genuinely disables when it doesn't apply instead of just fading.
From now on, an automated accessibility check (axe) runs against every page in our test
harness — a change that breaks accessibility fails the build. CONTRIBUTING and SECURITY were
also rewritten to describe how the project is actually governed and defended.
- The gate immediately earned its keep: it caught a third contrast violation (chip count badges at 55% opacity, ratio 3.2:1) that two human passes had missed. All six public pages now pass with zero critical/serious violations.
- Per the NYC Web Content Style Guide we're aligning to (WCAG 2.2 + plain language) — more of that standard becomes automated checks next.
2026.07.10 · Three new front doors: email-in, MCP, and The Data
For you — Three new ways in. Subscribe by email: write to
subscribe@crol-list.org in plain English
("construction awards over $500k") and you'll get a confirmation link back — no form, no
CAPTCHA, just your words. For AI assistants: point any MCP client at
api.crol-list.org/mcp to search notices and set up watches programmatically
(double opt-in still applies — nothing sends without the address confirming).
The Data: a new page showing the City Record at a glance —
what's actually in it, publication volume, procurement mix, top agencies and vendors by
cleaned dollars — computed live in your browser from NYC Open Data.- Inbound email → LLM-parsed watch with the same double-opt-in confirm flow as the site; hard daily ceilings and per-sender limits on every model-backed path, failing closed.
- MCP tools:
search_notices,get_notice(the daily-refreshed mirror),preview_watch,create_watch— documented on the API page. - Plain-English money searches understand more: amount ceilings ("under $500k") and procurement categories ("construction", "human services").
- Digest delivery moved to a queue: each subscriber's digest retries independently, so one bad address can't block a run; daily send caps unchanged. (Groundwork from Dev Doshi's crol-alert.)
2026.07.10 · Honest data rules + a faster backbone (with Dev Doshi)
For you — Money filters and digests can no longer be hijacked by
the dataset's data-entry errors: amounts of $10 billion or more (there's a $96 trillion typo in the
official record) are excluded, while real multi-billion awards now correctly appear — the old
cutoff silently dropped everything above $5 billion, including the largest legitimate award (about $6.68 billion).
Pre-qualified-list notices with placeholder year-2090 dates now say "no fixed deadline
(rolling)" instead of a date no one should calendar. The About
page documents the dataset's quirks — what the City Record actually contains and how we
correct for it.
- Data-honesty rules grounded in Dev Doshi's exploratory analysis of the full 1.09M-row dataset (87.5% personnel-change skew, a data-entry-error amount tail, rolling-deadline placeholders, dual agency-name conventions) — thanks Dev.
- New server-side mirror of recent notices (Cloudflare D1), refreshed by the daily cron from NYC Open Data — the source of truth is unchanged and site searches still query it live; the mirror makes alert matching and upcoming features fast, and stores each raw source row so upstream schema changes are recoverable.
- Groundwork from the same analysis: a shared notice-search engine over the mirror (AND-of-ORs keyword matching with the honesty rules enforced in SQL), powering the next round of subscription features.
- Continuous integration now runs both unit-test layers on every change (previous entry's multi-watch regression suite included).
2026.07.09 · Predictive Procurement: Checkbook Expirations, MOCS Plans, & Early-Warning Timelines
For you — CROL-List now alerts you 6 months before contracts expire or new RFPs are published. Agency and vendor profiles show a new "Procurement Forecast" tab with a vertical chronological timeline, uniting predicted contract renewals (from Checkbook NYC) and official agency-planned solicitations (from Charter §112 MOCS datasets). Digests now deliver early-warning notifications for upcoming forecasts matching your watches.
- Checkbook NYC contract end-date calculations to estimate renewal timelines; 180-day early warning triggers with single-send de-duplication.
- Ingestion pipeline for annual Charter §112 MOCS agency procurement plans, normalizing value bands and expected RFP release quarters.
- New unified
GET /forecastAPI search endpoint and extendedGET /inv/:iddetails, grouping future timeline milestones chronologically. - A visual vertical timeline component on vendor/agency profiles showing estimated renewals and planned solicitations, complete with direct alert subscriptions.
2026.07.02 · Fix: vendors with punctuated names resolve again
For you — Vendor pages and vendor watches now work for names like
"Leon D. Dematteis Construction Corp." Before this fix, clicking such a vendor showed "no awards
on record" and a watch on them matched nothing — despite their awards being right there.
- Root cause: entity resolution normalizes a name to a punctuation-free stem, but the server-side lookup prefix-matched that stem against the raw
vendor_namecolumn — so any vendor with mid-name punctuation could never match its own stem. Fixed by switching the lookup to Socrata full-text$q(punctuation-insensitive on both sides); the exact-stem filter still guarantees precision. Same fix in the site, the worker's entity watches, and the batch cross-reference tool. - Caught by functional spec 05; a new unit test pins the invariant (a vendor's own row must satisfy the compiled query).
2026.07.02 · Snap + crisp: the round-four speed-and-declutter pass
For you — The site looks calmer and feels immediate. Lists show
content-shaped placeholders instead of spinners. Filtering keeps your place instead of blanking
the list. Going back to a tab you already loaded is instant. Clicking a notice paints its detail
at once (the paper trail fills in a beat later). Search runs as you type — the Filter buttons
are gone because you no longer need them.
- ~150KB of map code (Leaflet) no longer blocks first paint — it loads only when the Land lens needs it. Unused font weight dropped; the browser now pre-connects to the data APIs.
- A read-side query cache (5-minute TTL) with request coalescing: revisiting a tab, filter, or notice renders from memory.
- Today's Edition renders instantly from your last visit's copy and refreshes behind itself — no more masthead reflow.
- Declutter, per decision 005 (internal design log): one accent color (urgency and red flags keep theirs), ~40 decorative emoji removed, shadows off, the stage-legend strip retired. The design is now formally anchored to citymeetings.nyc/craigslist restraint and Tufte's data-ink rule.
2026.07.02 · Enablement: public stats, honest click counts, this page
For you — You can now see the project's own usage numbers at
/stats (aggregate counts only — no accounts, no cookies, nobody tracked). Email-digest
links now pass through a count-only redirect so we can tell digests are useful. It counts clicks per day,
never who clicked, and every digest footer says so.
- Public
/statsendpoint + this site's stats page: active subscriptions (a count, not a list), digests sent, digest links followed, feed/batch/share activity, plain-English-search calls.a5dbc18(worker) - Count-only digest click-through
/r/<kind>/<id>— validated ids only, cannot redirect off-site, junk paths fall to the homepage uncounted.a5dbc18 - This changelog; the maintenance rule now includes it (every shipped change lands an entry in the same session).
- The backend went open source: the worker's code now lives in this repo's
worker/(fresh tree; secrets were never in git — see decision 004 (internal design log)). One clone is the whole system; SECURITY.md documents the threat model. - Governance files landed: MISSION.md, CONTRIBUTING.md, and a decision log.
2026.07.02 · Follow the dollars, matter timelines, follows, workspace, API
For you — Awards now show what was actually paid (live from Checkbook NYC),
any procurement matter reads as one timeline, you can follow a vendor or agency and get emailed when they
reappear, pin anything into a citable investigation workspace, and use every view as an API.
- Checkbook NYC join, deterministic by PIN: committed vs. paid-to-date with a progress bar, amended-from, M/WBE, vendor-mismatch warning;
#matter/<pin>timelines.943a858 - Follow-an-entity alerts (name-stem matched) + Follow buttons on entity pages; investigation workspace — pin · annotate · export CSV/JSON · print dossier · 90-day share links;
api.htmldocs + live batch cross-reference (POST /batch).c794015(site) ·3176ec2(worker) - All user-visible worker URLs now read
api.crol-list.org.03ed286 - Test coverage across all twenty features; fixed a case-sensitivity bug it caught in junk-PIN filtering.
dc8499e
Incident — Adding the custom domain silently disabled the
workers.dev
fallback alias (Cloudflare error 1042): cached pages and in-flight email-confirm links would have broken. Caught
by live probes minutes after deploy; fixed by keeping the alias explicitly enabled, and the site now fails over
between the two hostnames automatically. d75626e2026.07.01 · Entity pages, red flags in context — and the first ten, all in one day
For you — Every vendor and agency became a page (with totals, top partners, and open
RFPs), procurement notices carry statistical context instead of bare text, and the whole
search-and-subscribe layer landed: watch any search, get a morning email digest, grab any view as RSS/calendar,
share any notice by URL, and see deadlines as countdowns instead of dates.
- Entity pages:
#vendor/<name>(name variants resolved — "Sinergia Inc" and "Sinergia Incorporated" are one profile) and#agency/<name>; every name on the site became a link.d0db6c1·ad43b56 - Red-flag badges (non-competitive method, short ad window, repeat vendor) + benchmarks ("larger than 94% of this agency's awards"), with the formulas and false-positive modes published on About.
6708c33 - Round one, all ten: watch-this-search on every lens + 60-second onboarding quiz
b217895; RSS/Atom/JSON/calendar feeds27e8b1e(worker); permalinks everywhereef8c3b6; deadline countdown chips55087c6; the who/what/when/act glance box74de73e; Today's Edition front paged28b7d4; the People lens's instant examples2c0f72b; the Property asset-type explorer2ed20ee; the accessibility & mobile passa46c2fa. - The daily digest cron went live; cookieless Cloudflare Web Analytics beacon installed.
aec7673
Incident — The new vendor pages' full-text mentions query initially ran unbounded
over the 1M-row archive (slow, expensive). Caught by the browser test harness before it shipped; the query is
now scoped to recent editions with a hard timeout.
7fbe7262026.06.30 · Real subscriptions
For you — Email alerts became real: double opt-in (nothing is stored until you click
the confirmation link), one-click unsubscribe, and your address is only ever used to send you your own digest.
- Turnstile-gated
/subscribe→ signed confirm link → KV; RFC-8058 one-click unsubscribe.6b2b30d
2026.06.26 · crol-list.org
For you — The site got its own domain and a real "ask in plain English" box on every
lens (with an on-device fallback, so search works even if the helper is down).
- Domain cutover to
crol-list.orgcc8192a; plain-English search wired to the workere32f3fa; interface declutter827fb9b.
2026.06.24–25 · The seven lenses
For you — The tool took its shape: Money, People, Land, Property, Rules, Meetings, and
Alerts, in the letterpress design, over live open data with nothing cached.
- Money/People/Land deep lenses; Property, Rules, Meetings feed lenses
d0670b7; real rezoned tax-lot polygons on the Land map38b648e; the "Still standing?" demolition check7cd5a96; the City Record letterpress redesignf2c4033.



