diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000000..fbf0652462 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,12 @@ +{ + "permissions": { + "allow": [ + "Bash(npx jest *)", + "Bash(yarn tsc *)", + "Bash(npm view *)" + ], + "deny": [ + "Read(**/.env)" + ] + } +} diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index a47369537a..ee7cfc4df9 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,35 +1,20 @@ # Copilot Cloud Agent Instructions for `bloom-housing/bloom` - ## Application overview -Bloom is an affordable housing platform. There are two separate applications in this monorepo: a public-facing app for housing seekers, and a partners app for developers and property managers. The public app includes a listing search and application portal, while the partners app includes listing management, application review, and reporting tools. +Bloom is an affordable housing platform. There are two separate applications in this monorepo: a public-facing app for housing seekers, and a partners app for developers and property managers. The public app includes a listing search and application portal; the partners app includes listing management, application review, and reporting tools. -## Fork model +## Repository layout -This repository is called "core". The model for Bloom is to have one generic core codebase that is forked by each housing jurisdiction. The applications are designed to be customizable through feature flags, translation keys, and CSS overrides, but otherwise the best practice is to have no customizations. +Monorepo with four main areas: -## Repository at a glance -- Monorepo with four main areas: - - `api` (NestJS + Prisma backend) - - `sites/public` (Next.js public app) - - `sites/partners` (Next.js partners app) - - `shared-helpers` (shared TS/React helpers, types, views, scripts) -- Root `package.json` is the main entrypoint for common commands. -- Node version in CI is **22**. +- `api` — NestJS + Prisma backend +- `sites/public` — Next.js public app +- `sites/partners` — Next.js partners app +- `shared-helpers` — shared TS/React helpers, types, views, scripts -## First-time setup workflow -1. Start in repo root: `/home/runner/work/bloom/bloom` -2. Install dependencies: - - Normal: `yarn install` - - In restricted-network sandboxes: `SENTRYCLI_SKIP_DOWNLOAD=1 CYPRESS_INSTALL_BINARY=0 yarn install` -3. Copy env templates before app builds/runs: - - `cp /home/runner/work/bloom/bloom/api/.env.template /home/runner/work/bloom/bloom/api/.env` - - `cp /home/runner/work/bloom/bloom/sites/public/.env.template /home/runner/work/bloom/bloom/sites/public/.env` - - `cp /home/runner/work/bloom/bloom/sites/partners/.env.template /home/runner/work/bloom/bloom/sites/partners/.env` -4. For API-focused work, ensure test env values are present (notably `TIME_ZONE=America/Los_Angeles` and `CLOUDINARY_CLOUD_NAME=exygy`; see `api/README.md`). +Fast navigation: -## Fast navigation and ownership hints - Backend business logic: `api/src/services` - Backend endpoints: `api/src/controllers` - Backend unit tests: `api/test/unit` @@ -38,25 +23,34 @@ This repository is called "core". The model for Bloom is to have one generic cor - Shared cross-app logic/components/types/tests: `shared-helpers/src`, `shared-helpers/__tests__` - CI behavior and canonical command patterns: `.github/workflows/*.yml` -## Validation commands (prefer smallest relevant scope) -- Root lint (includes API lint): - `cd /home/runner/work/bloom/bloom && yarn lint` -- Public unit tests: - `cd /home/runner/work/bloom/bloom && yarn test:app:public:unit` -- Partners unit tests: - `cd /home/runner/work/bloom/bloom && yarn test:app:partners:unit` -- Shared helpers tests: - `cd /home/runner/work/bloom/bloom && yarn test:shared-helpers` -- API build/tests: - - Build: `cd /home/runner/work/bloom/bloom/api && yarn build` - - Unit tests: `cd /home/runner/work/bloom/bloom/api && yarn test` - -When changing one area, run that area’s tests first, then run broader checks only as needed. - -## Implementation conventions that help avoid regressions -- Follow existing file patterns in each package (NestJS patterns in `api`, Next.js patterns in `sites/*`). -- Keep changes focused; avoid broad refactors in this monorepo unless required. -- Reuse existing shared helpers/types instead of duplicating interfaces or utilities. +Root `package.json` is the main entrypoint for common commands. Node version in CI is **22**. + +## Setup +1. Start in repo root: `/home/runner/work/bloom/bloom` +2. Install dependencies: `yarn install` + - In restricted-network sandboxes: `SENTRYCLI_SKIP_DOWNLOAD=1 CYPRESS_INSTALL_BINARY=0 yarn install` +3. Copy env templates before building/running: + - `cp api/.env.template api/.env` + - `cp sites/public/.env.template sites/public/.env` + - `cp sites/partners/.env.template sites/partners/.env` +4. For API-focused work, ensure test env values are present (notably `TIME_ZONE=America/Los_Angeles` and `CLOUDINARY_CLOUD_NAME=exygy`; see [api/README.md](../api/README.md)). + +## Common commands + +- Dev (all): `yarn dev:all` (backend + both frontends) +- Dev (frontend only): `yarn dev:frontend` +- Dev (backend only): `yarn dev:backend` +- Dev (public + backend): `yarn dev:public` +- Dev (partners + backend): `yarn dev:partners` +- Lint (root, includes API): `yarn lint` +- Public unit tests: `yarn test:app:public:unit` +- Partners unit tests: `yarn test:app:partners:unit` +- Shared helpers tests: `yarn test:shared-helpers` +- API build: `cd api && yarn build` +- API unit tests: `cd api && yarn test` +- API e2e tests: `yarn test:backend:new:e2e` + +Prefer the smallest relevant scope: when changing one area, run that area's tests first, then broaden only as needed. ## Errors encountered in this cloud sandbox and workarounds 1. **`yarn install` failed downloading `@sentry/cli` binary** @@ -80,17 +74,61 @@ When changing one area, run that area’s tests first, then run broader checks o - Prefer targeted tests for touched files/packages; avoid full e2e/Cypress unless task requires it. - If build/test failures look unrelated, capture logs clearly and proceed with scoped validation for changed code. -## Project guidelines -- Always use the conventional commit format for commit messages and PR titles. -- Pull requests should link to an issue if one exists. If no issue exists, the PR description should include a clear summary of the change and its motivation. -- Use the prettier configuration in the repo root for consistent formatting. -- Unit tests are required for new features and bug fixes; aim for good coverage of new logic and edge cases, but avoid over-testing implementation details. -- Unit/Integration tests should be written with Jest and React Testing Library; avoid Cypress for new tests unless the happy path of new end-to-end behavior is being validated. -- Always follow good security practices, especially when handling user data or authentication flows. If you identify a potential security issue, report it immediately and follow responsible disclosure guidelines. -- Accessibility is a key focus. We aim to meet WCAG 2.2 AA standards. Additional guidelines can be found in [a11y-guidelines.md](a11y-guidelines.md). If you identify an accessibility issue, please report it and consider how to fix it in a way that improves the experience for all users. -- Follow existing patterns and prefer `ui-seeds` and CSS/SCSS variables over `ui-components` and Tailwind for consistent styling (though both component libraries are owned by the team, so bugs in either can be reported and fixed). -- Use scripts and utilities in `shared-helpers` when possible to avoid duplication and maintain consistency across the public and partners apps. If you find a gap in shared functionality, consider adding to `shared-helpers` rather than creating new utilities in each app. -- Translation keys used only in partners should be added to the partners translation file `sites/partners/page_content/locales/general.json`. Translation keys used only in partners that we anticipate will be overridden in a fork should be added to the partners translation overrides file `sites/partners/page_content/overrides/general.json`. -- Translation keys used anywhere in public, even if also used in partners, should be added to the shared translation files, with the English file at `shared-helpers/src/locales/general.json`. All strings added to this file need translations in all non-English languages, which can be generated with `ts-node get-machine-translations.ts` from the `shared-helpers` directory given the environment variables are added. -- Use `tIfExists` only for translation keys that may not exist in all forks, as a method of adding custom content without having to use a feature flag. We should use generic content for these keys, added to the `sites/public/page_content/locale_overrides/general.json` file for the public site and `sites/partners/page_content/overrides/general.json` for the partners site, and then allow forks to override or remove those keys as needed. -- Make no references to real, specific jurisdictions or projects in the core codebase. If jurisdiction-specific content is needed, use generic language in translation keys in core so that they can be overridden or removed as needed by forks. If jurisdiction-specific logic is needed, use feature flags to gate that logic and add the feature flag to the partners app so that it can be enabled or disabled as needed by forks. Additional documentation on features flags is found in [feature-flags.md](../docs/feature-flags.md). We have generic jurisdictions that are placeholders for real jurisdictions, such as "Bloomington", that can be used in translation keys and content when jurisdiction-specific language is needed. If you find that you need to add new generic jurisdiction names, please use similarly generic language and avoid referencing real places. +## Conventions + +### Fork model + +This repository is called "core". Bloom's model is one generic core codebase forked by each housing jurisdiction. Applications are customized through feature flags, translation keys, and CSS overrides — otherwise the practice is **no jurisdiction-specific customizations or references** in core. + +- Make no references to real, specific jurisdictions or projects. Use generic placeholder jurisdictions (e.g. "Bloomington") when jurisdiction-specific language is needed in examples/content. If a new generic jurisdiction name is needed, keep it similarly generic — never a real place. +- Jurisdiction-specific *logic* must be gated behind a feature flag (displayed in the partners app so forks can toggle it). See [docs/feature-flags.md](../docs/feature-flags.md). +- Jurisdiction-specific *content* should use overridable translation keys, not hardcoded strings. + +### General + +- Before starting implementation on a ticket, flag anything ambiguous in the requirements or any assumption being made, rather than silently picking an interpretation. +- Follow existing file patterns in each package (NestJS patterns in `api`, Next.js patterns in `sites/*`). +- Keep changes focused; avoid broad refactors in this monorepo unless required. +- Reuse existing shared helpers/types instead of duplicating interfaces or utilities. If there's a gap in shared functionality, prefer adding to `shared-helpers` over duplicating logic per app. +- Run `yarn lint` before finishing any change — ESLint enforces Prettier formatting, and the warning budget is tight (root allows only 40 warnings, `api` only 2), so most new lint or formatting issues will fail rather than pass as warnings. Run `yarn prettier` to auto-fix formatting first if `yarn lint` reports style issues. + +### Contribution format + +- Prefer small, independently reviewable and testable changes over broad multi-concern PRs, even when a ticket could technically be completed in one larger pass. +- Always use conventional commit format for commit messages and PR titles. +- PRs should link to an issue if one exists; otherwise the description should clearly summarize the change and its motivation. Follow the structure in [docs/pull_request_template.md](../docs/pull_request_template.md). +- `CHANGELOG.md` is archived and no longer maintained — don't update it as part of a change. + +### Testing + +- Unit tests are required for new features and bug fixes. Aim for good coverage of new logic and edge cases, but avoid over-testing implementation details. +- Write unit/integration tests with Jest and React Testing Library. Avoid Cypress for new tests unless validating the happy path of new end-to-end behavior. + +### Translations + +- Translation keys used only in partners: `sites/partners/page_content/locales/general.json`. +- Translation keys used only in partners but anticipated to be overridden in a fork: `sites/partners/page_content/overrides/general.json`. +- Translation keys used anywhere in public (even if also used in partners): shared file at `shared-helpers/src/locales/general.json`. Every string added here needs translations in all non-English languages — generate with `ts-node get-machine-translations.ts` from `shared-helpers` (requires env vars). +- Use `tIfExists` only for translation keys that may not exist in all forks, as a lightweight alternative to a feature flag for optional custom content. Add generic content for these keys to `sites/public/page_content/locale_overrides/general.json` (public) or `sites/partners/page_content/overrides/general.json` (partners), so forks can override or remove them while keeping main translation files identical. +- Migration-only translation keys can survive seed merges in forked repos and cause email content mismatches — be careful with `upsertTranslation`-style changes that touch both migrations and seeds. + +### Feature flags + +- Source of truth: [api/src/enums/feature-flags/feature-flags-enum.ts](../api/src/enums/feature-flags/feature-flags-enum.ts), shared across API and both frontends. +- Flags are boolean-only and not auto-added to the database — add to `featureFlagMap` and call the `featureFlags/addAllNew` API endpoint. +- Manage jurisdiction assignment via the hidden `/admin` page on the partners site (super admin only). +- Full docs: [docs/feature-flags.md](../docs/feature-flags.md). The flag table in that file is generated from `featureFlagMap` by `api/scripts/generate-markdown.ts` — after adding or changing a flag, regenerate it with `cd api && npx ts-node scripts/generate-markdown.ts` (also runs as part of `yarn generate:client`). + +### Accessibility + +WCAG 2.2 AA is a hard requirement. See [instructions/a11y.instructions.md](instructions/a11y.instructions.md) for anti-patterns, severity levels, and framework-specific fixes. If you spot an accessibility issue, report it and consider fixing it in a way that improves the experience broadly, not just for the one case at hand. + +### Security + +Follow good security practices, especially around user data and authentication flows. Report any potential security issue immediately and follow responsible disclosure rather than silently patching around it. + +### Frontend / UI guidance + +- Prefer `ui-seeds` and CSS/SCSS variables over `ui-components` and Tailwind for consistent styling. Both component libraries are owned by the team, so bugs in either can be reported and fixed. +- Prefer smaller, incremental changes over large speculative UI implementations. +- Before building a new UI pattern, check `ui-seeds` and existing components in `sites/public/src` or `sites/partners/src` for something similar to extend rather than inventing a new pattern from scratch. \ No newline at end of file diff --git a/.github/a11y-guidelines.md b/.github/instructions/a11y.instructions.md similarity index 100% rename from .github/a11y-guidelines.md rename to .github/instructions/a11y.instructions.md diff --git a/.gitignore b/.gitignore index 8c4dfbf332..5663aa7ca2 100644 --- a/.gitignore +++ b/.gitignore @@ -84,6 +84,9 @@ yarn-error.log .vscode *.code-workspace +# Personal Claude Code settings (shared config lives in .claude/settings.json) +.claude/settings.local.json + # VS code debugger config launch.json diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000..464cbcc035 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,3 @@ +# AGENTS.md + +The full instruction set for working in this repository lives in [.github/copilot-instructions.md](.github/copilot-instructions.md) — read it before making changes. It's shared across coding agents (GitHub Copilot, Claude Code, and AGENTS.md-aware tools), so update it (not this file) when guidance changes. diff --git a/CHANGELOG.md b/CHANGELOG.md index dcdb8667bb..1728274e07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +**Archived.** This file was last updated in 2021 and is no longer maintained — it does not reflect changes since then. Consult git/PR history for current change information. Kept for historical reference only. + +--- + All notable changes to this project will be documented in this file. The format is loosely based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). (_Note:_ it our intention to improve our release process going forward by using [Semantic Versioning](https://semver.org/spec/v2.0.0.html).) diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000000..275d6a3b30 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,3 @@ +# CLAUDE.md + +The full instruction set for working in this repository lives in [.github/copilot-instructions.md](.github/copilot-instructions.md) — read it before making changes. It's shared across coding agents (GitHub Copilot, Claude Code, and AGENTS.md-aware tools), so update it (not this file) when guidance changes. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index aa0a6773a3..9d0dd43569 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,18 +12,20 @@ Please note that implementation-specific issues with individual Bloom sites shou Pull requests (PRs) are the most effective way to make a contribution to Bloom, and can range from small one-line fixes to major feature additions. Here are some suggestions for having your pull requests quickly accepted: -- Clearly document the issue your pull request is meant to address in the initial comment, and make sure the PR title summarizes the work in a useful way. If your PR addresses an issue in the issue tracker, make sure to link it. You do not need to have a corresponding issue before submitting a PR, but it's usually a good method of getting feedback on your approach before starting major work. +- Clearly document the issue your pull request is meant to address in the initial comment, and make sure the PR title summarizes the work in a useful way. If your PR addresses a ticketed issue, make sure to link it. You do not need to have a corresponding issue before submitting a PR, but it's usually a good method of getting feedback on your approach before starting major work. -- Make sure that all files touched by your PR still pass all lint and style rules (see below). If you're adding any meaningful functionality to the system, please add matching tests -- the team will be happy to provide guidance on the most time-efficient method for helping with test coverage. +- Make sure that all files touched by your PR still pass all lint and style rules (see below). If you're adding any meaningful functionality to the system, please add matching tests -- the team will be happy to provide guidance on the most time-efficient method for test coverage. - Since we typically will have a number of PRs open in various states of progress, please label your PR appropriately in GitHub when it's ready for review, and one or more core team members will take a look at it. ## Continuous Integration -Bloom uses the Circle CI system to automatically run tests on any pull requests. No contribututions that introduce errors in existing tests will be accepted, so please make sure you see the confidence-inspiring green checkmark next to your commits before marking your PR ready for review. +Bloom uses GitHub Actions to automatically run tests on any pull requests. No contributions that introduce errors in existing tests will be accepted, so please make sure you see the confidence-inspiring green checkmark next to your commits before marking your PR ready for review and applying the `2 reviews needed` label. -## Code Style +## Linting -We use the ESlint linting system and the automatic code formatter Prettier (which the linter also enforces). **All** pull requests must pass linting to be accepted, so they don't create fix work for future contributors. If you're not using an IDE that integrates with these tools, please run eslint + prettier from the cli on all added or changed code before you submit a pull request. +We use the ESlint linting system and the automatic code formatter Prettier (which the linter also enforces). **All** pull requests must pass linting to be accepted, so they don't create fix work for future contributors. If you're not using an IDE that integrates with these tools, please run eslint + prettier from the cli on all added or changed code before you submit a pull request. As much as we'll try to keep current, the linting rules can become out of date, and in this case you should file an issue with the adjustments you're looking for. -As much as we'll try to keep current, the linting rules can become out of date, and in this case you should file an issue with the adjustments you're looking for. We'll be looking for a resulting PR with a minimum of two commits - one to adjust the rules or tooling, and another that updates the codebase to match. If the latter changes are complex, please discuss in advance and break up the work into reasonably reviewable commits. +## Additional Conventions + +Bloom is built as a "core" codebase forked by individual housing jurisdictions, which shapes several project-specific conventions beyond general OSS practice — how jurisdiction-specific content is handled, where translation keys live, how feature flags gate custom logic, and our accessibility bar. See the [Conventions](.github/copilot-instructions.md#conventions) section of `.github/copilot-instructions.md`, which also covers testing, translations, feature flags, and accessibility further down the same file. That file is written primarily for AI coding agents, so you can skip its setup and cloud-sandbox sections — those are specific to automated agents.