Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"permissions": {
"allow": [
"Bash(npx jest *)",
"Bash(yarn tsc *)",
"Bash(npm view *)"
],
"deny": [
"Read(**/.env)"
]
}
}
150 changes: 94 additions & 56 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -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`
Expand All @@ -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**
Expand All @@ -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.
File renamed without changes.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
3 changes: 3 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -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.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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).)
Expand Down
3 changes: 3 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -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.
Loading
Loading