This file provides baseline guidance to all agentic coding assistants. Instructions here may be overridden by other files or specific instructions from the user.
Office of Head Start TTA Smart Hub — full-stack monorepo (Express API, React SPA, Bull/Redis worker) for managing Training and Technical Assistance activities across Head Start programs.
- Ask before starting work when acceptance criteria are missing, scope is ambiguous, or constraints are unclear.
- Pause and ask before making broad refactors or touching many files.
- When presenting choices, provide a recommended option with reasoning.
- Ensure changes pass lint checks after work is complete.
- Follow coding standards in
best_practices.md.
Backend:
yarn test— build then run backend tests (jest --runInBand)yarn test:ci— backend tests via CI script (./bin/test-backend-ci)yarn lint— Biome lint for backend (src/)yarn lint:fix— Biome autofix for backend
Frontend:
cd frontend && yarn test --watchAll=false— run frontend tests (Jest via craco, requiresTZ=America/New_York)cd frontend && yarn lint— Biome lint for frontendcd frontend && yarn lint:fix— Biome autofix for frontend
Database:
yarn db:migrate— run migrations (also runs logical data model update)yarn db:migrate:undo— revert last migrationyarn db:migrate:create -- --name verb_object_table— generate new migration fileyarn db:seed/yarn db:seed:undo— seed or unseed data
Docker (matches CI more closely):
yarn docker:start— full stackyarn docker:test:be— backend tests in Dockeryarn docker:db:migrate— migrations in Docker
Three entry points: backend (/src), frontend (/frontend/src), worker (/src/worker.ts).
Backend layered pattern: Routes → Services → Models.
routes/: API endpoints organized by domain. Call services, never contain business logic directly.services/: Business logic. Interact with models and handle associated-data updates.models/: Sequelize database models. Subdirectories for hooks and model validation schemaspolicies/: Authorization and access control. Routes check policies before proceeding.scopes/: Reusable Sequelize query filters.middleware/: Express middleware (auth, sessions, logging). Routes usetransactionWrapper.jswhen needed.migrations/,seeders/,lib/,tools/,widgets/,workers/: Supporting directories.
Frontend: pages/ → components/ with fetchers/ for API calls and hooks/ for shared logic. Uses React Hook Form and @trussworks/react-uswds.
Worker: Bull queues backed by Redis — Scan (ClamAV), Resource, S3, Notification, Maintenance. Uses throng for horizontal scaling.
Auth: OAuth2 via HSES, session management with express-session + Redis, authorization enforced by policies.
Database: Sequelize v6, config at .sequelizerc and config/config.js.
- Only worker instance 0 runs cron jobs — never duplicate cron registration.
yarn db:migratealso runs the logical data model CLI (yarn ldm) — don't skip this.- Frontend local dev uses Vite on port 3000 and proxies
/apirequests toBACKEND_PROXY(defaults tohttp://localhost:8080infrontend/.env).
Don't use them. Use a joined table instead — there is a Sequelize bug that intermittently returns the wrong data type from enum arrays.
Never do database writes in model hooks. Validation in hooks (e.g., beforeUpdate) is fine. For updating associated data, do it explicitly in services. Hooks that write obfuscate operations and lead to unexpected states.
Filters are derived from URLs. sequelize.escape alone is insufficient — independently validate expected types (e.g., confirm all region IDs are numbers) before using them in queries.
Disable autosave on forms containing React Draft WYSIWYG editors. Autosave triggers reset() which destroys cursor position and in-progress text. See frontend/src/utils/formRichTextEditorHelper.js for the guard pattern.
All tests run against the same database instance. Never rely on seed data — create and destroy test data within each test using beforeAll/afterAll. Use transactions where appropriate and Promise.all() for parallel async setup.
Use Sequelize scopes and models. Raw SQL should be a last resort.
- Create/update route handler in
src/routes/<domain>/ - Add business logic in
src/services/<domain>.js - Add authorization policy in
src/policies/if needed - Write tests alongside implementation
- Update OpenAPI spec in
docs/openapi/
- Run
yarn db:migrate:create -- --name add_new_field_to_table - Edit the generated file in
src/migrations/ - Run
yarn db:migrate
docs/guides/testing.md: Testing strategy and database state managementdocs/guides/dev-setup.md: Local development setupdocs/guides/infrastructure.md: Cloud.gov, CI/CD, deploymentdocs/adr/: Architecture Decision Recordsdocs/openapi/: OpenAPI specs (served via Redoc at localhost:5003)best_practices.md: Code authoring and review standards