Imported from olitreadwell/awesome-open-usa-data (
AGENTS.md). Install upstream withnpx skills add olitreadwell/awesome-open-usa-data. Copyright stays with the author.
AGENTS.md
Instructions for AI coding agents working in this repo. Read this before editing anything.
Where the rules live
docs/contributing/is the shared contributing standard for every change: principles, workflow, quality, testing, git, security, documentation, verification. Readdocs/contributing/00-index.mdfirst.- This file and
CLAUDE.mdhold stack-specific rules. Where they conflict with the generic guide, the stack-specific rules win. docs/style-guide.mdanddocs/llm-agent-optimization.mdare the writing rules that make this repo navigable by humans and agents alike.
What this is
An open-directory starter template: any "directory of {THING} in {PLACE}" project (op shops, DJs, festivals, quizzes). Everything exists so a new repo can be scaffolded with the dataset + scrapers + OpenAPI API + website + community loop already wired, on top of a production-quality baseline: tests, coverage, lint, format, typecheck, build, smoke, e2e, CI, Docker, docs.
Dataset-directory invariants (do not break these)
- Every listing carries a
sourceURL and alastVerifieddate (src/data/schema.ts);id===slug; no duplicate ids/names. - The dataset is the boundary: bad data must fail
pnpm run check, never fail silently at runtime. Snapshot mode (no DATABASE_URL) serves the committedsrc/data/snapshot.json; DB mode uses Postgres via the same repository functions insrc/lib/item-repository.ts. - Public data only. Scrapers respect robots.txt + a 500ms+ per-origin
delay (
src/lib/scrapers/http.ts); failures are logged, never fatal. - Opt-out is instant and permanent (DB mode), or PR-tracked (snapshot).
- Every new API route MUST be documented in
src/server/openapi.tsand covered byscripts/contract-test.mjs(the no-drift test enforces the doc; smoke runs the contract test against the built server). - Community feedback flows through prefilled GitHub issue links
(
src/lib/issue-builder.ts,NEXT_PUBLIC_GH_REPO), with dataset tests as the merge gate. - Site identity lives only in
src/lib/site-config.ts(regenerated bypnpm run setup). Never hardcode a site name, thing label or city in components, feeds, metadata or tests — read fromgetSiteConfig(). - Feeds (
/feed.xml,/calendar.ics,/sitemap.xml) derive from the dataset, never from hardcoded lists.
Non-negotiables
- The one-command contract is
pnpm run check= format:check + lint + typecheck + test:coverage + build + smoke + e2e + check:links. CI mirrors it exactly. A green CI must mean the same as a green localcheck. - Run
pnpm run checkbefore and after every change. - Pin exact dependency versions. No
^or~ranges. - No dead code, no commented-out code, no unused dependencies.
- Every exported symbol has a JSDoc comment good enough for IDE hover/peek: params and return value where useful.
- Comments explain WHY and HOW, never WHAT the code obviously does.
- Tests prove every behavior change; run them, do not eyeball.
- Input validation at the boundary (zod), structured logs (pino), centralized error handling (src/lib/errors.ts).
- Every internal markdown link must resolve;
npm run check:linksenforces it.
Contact, feedback, and help
docs/contact.mddocuments the contact/feedback contract: endpoints, proof-of-work spec, abuse protection, and how agents file issues.- Pages:
/help,/contact,/feedback,/docs(Swagger UI); APIs:/api/challenge,/api/contact,/api/feedback,/api/openapi.json; contract:/.well-known/feedback.json. - The API contract is OpenAPI 3.1 at
/api/openapi.json, generated from the zod schemas insrc/server/openapi.tsand enforced bysrc/server/openapi.test.ts(seedocs/api.md). Adding a route without documenting it fails the check. - Feedback creates labelled GitHub issues (
bug,enhancement,question) whenGH_TOKEN+GH_REPOare set; without them the form explains where to go instead.
Naming and discoverability
UI conventions (Radix-first)
- Prefer Radix UI primitives (
@radix-ui/react-*, wrapped insrc/components/ui/) over hand-rolled equivalents for label, select, dialog, accordion, and tooltip. They ship keyboard navigation, focus management, and ARIA attributes for free. - Only hand-roll a component when Radix has no primitive for it (native
inputs/textarea) — keep those in
src/components/uiso every form shares one style. - Radix Select is not a native form control: keep a hidden
<input type="hidden" name=... value=...>in the form so values submit. - Add new UI wrappers to
src/components/ui/with a doc comment on each export; never fork a page-local copy of a shared style.
Links
-
Every external link (
https://,//) getstarget="_blank"andrel="noopener noreferrer"— enforced bycheck:external-linksin thecheckchain. Internal navigation stays same-tab. -
2-3 word, domain-prefixed export names (
getUserProfileById, notget). -
One spelling per concept, everywhere.
-
No
any/ untyped escape hatches. -
Test files sit next to their source (
logger.test.tstestslogger.ts).
Workflow
- Read
docs/contributing/00-index.md, then this file,CLAUDE.md,docs/engineering.md,docs/style-guide.md. - Make the smallest change that does the job.
- Update docs in the same change as the behavior they describe.
- Commit with conventional messages (
feat:,fix:,docs:,ci:, ...). - Run
pnpm run check. Fix failures. Repeat until green.
Branch policy
- Feature work happens on short-lived branches; PRs merge into
development. development->mainis the single integration PR, kept up to date.- After merge, feature branches are deleted.
This is NOT the Next.js you know
This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in node_modules/next/dist/docs/ (resolved from this file's directory; in monorepos the next package may not be visible from the repo root) before writing any code. Heed deprecation notices.
This block is written and re-added by next dev — verify at node_modules/next/dist/server/lib/generate-agent-files.js. Removing it from a diff only re-creates the uncommitted change; committing it with your work keeps the tree clean.