Skip to main content
The Public Portal is the reference implementation of the Bloom Housing applicant-facing site. It runs as a Next.js application on port 3000 and provides housing seekers with everything they need to discover affordable housing opportunities, apply through a multi-step Common Application, and track submitted applications.

Features

Browse listings

View open and closed listings with filtering. Closed listings are capped at a configurable maximum via MAX_BROWSE_LISTINGS.

Common Application

Multi-step application flow covering contact, household, financial, community types, preferences, programs, and review.

Account management

Create an account, sign in, and access a dashboard showing all submitted applications and saved favorites.

Finder tool

Guided questionnaire that matches housing seekers to relevant listings based on their situation.

Get assistance

Connects applicants with local housing counselor services configured via HOUSING_COUNSELOR_SERVICE_URL.

FAQ

Frequently asked questions page, shown when the SHOW_PUBLIC_LOTTERY feature flag is enabled.

Page structure

All pages live under sites/public/src/pages/.
FileRouteDescription
index.tsx/Homepage with featured listings
listings.tsx/listingsAll open listings
listings-closed.tsx/listings-closedClosed/waitlisted listings
finder.tsx/finderListing finder questionnaire
get-assistance.tsx/get-assistanceHousing counselor service
faq.tsx/faqFAQ (feature-flagged)
create-account.tsx/create-accountNew account registration
sign-in.tsx/sign-inSign-in page
forgot-password.tsx/forgot-passwordPassword reset request
reset-password.tsx/reset-passwordPassword reset confirmation
verify.tsx/verifyEmail verification
disclaimer.tsx/disclaimerSite disclaimer
privacy.tsx/privacyPrivacy policy
additional-resources.tsx/additional-resourcesAdditional housing resources
create-advocate-account.tsx/create-advocate-accountAdvocate account registration
FileRouteDescription
listing/[id].tsx/listing/[id]Listing detail page
listing/[id]//listing/[id]/...Nested listing subpages
The Common Application is a multi-step flow. Each step is a separate page under applications/:
DirectoryStep
applications/start/Eligibility screening and application entry
applications/contact/Applicant contact information
applications/household/Household members and details
applications/financial/Income and financial information
applications/community-types/Community type preferences
applications/preferences/Local preference selections
applications/programs/Program eligibility
applications/review/Final review and submission
applications/view.tsxView a submitted application
FileRouteDescription
account/dashboard.tsx/account/dashboardOverview of submitted applications
account/edit.tsx/account/editEdit account profile
account/application/[id]//account/application/[id]View a specific submitted application
account/applications//account/applicationsList of all submitted applications
account/favorites//account/favoritesSaved/favorited listings

Running locally

1

Install dependencies

From the monorepo root:
yarn install
2

Configure environment variables

Copy the template and set values for your local environment:
cp sites/public/.env.template sites/public/.env
Edit sites/public/.env as needed. See the environment variables section below for details on each variable.
3

Start the backend and public app

From the monorepo root, this starts the backend on port 3100 and the public portal on port 3000:
yarn dev:all
Alternatively, start only the public portal from within sites/public:
yarn dev
4

Open the app

Navigate to http://localhost:3000 in your browser.
The backend must be running on port 3100 before starting the public portal. The app will fail to load listings if the API is unreachable.

Environment variables

Copy .env.template to .env inside sites/public/. The following variables control the app’s behavior:
VariableDefaultDescription
BACKEND_API_BASEhttp://127.0.0.1:3100Base URL for the backend API
BACKEND_API_BASE_NEWhttp://127.0.0.1:3100Alternate base URL (used for new API paths)
BACKEND_PROXY_BASE(empty)If set, routes API calls through this proxy instead
LISTINGS_QUERY/listingsPath appended to backend base to query listings
API_PASS_KEYsome-key-hereShared passkey; must match the backend’s configured value
VariableDefaultDescription
NEXTJS_PORT3000Port the Next.js app listens on
JURISDICTION_NAMEBloomingtonDisplay name for the jurisdiction
LANGUAGESen,es,zh,vi,tl,bn,ar,ko,hy,faComma-separated list of supported locales
IDLE_TIMEOUT5Minutes of inactivity before session timeout
HOUSING_COUNSELOR_SERVICE_URL/get-assistanceURL for housing counselor service page
MAX_BROWSE_LISTINGS10Maximum number of closed listings shown on the closed listings page
CACHE_REVALIDATE30Seconds to cache listing detail pages server-side (ISR revalidation interval)
MAINTENANCE_WINDOW(empty)Date range (YYYY-MM-DD HH:mm Z,YYYY-MM-DD HH:mm Z) for maintenance mode banner
SITE_MESSAGE_WINDOW(empty)Date range for displaying a site-wide message banner
VariableDefaultDescription
MAPBOX_TOKEN(empty)Mapbox API token for listing map views
CLOUDINARY_CLOUD_NAMEexygyCloudinary cloud name for listing images
GA_KEYG-2WQMFT5BESGoogle Analytics measurement ID
GTM_KEYGTM-KF22FJPGoogle Tag Manager container ID
NEW_RELIC_APP_NAMEBloom PublicNew Relic application name
NEW_RELIC_LICENSE_KEY(empty)New Relic license key
SENTRY_ORG(empty)Sentry organization slug; when set, enables Sentry error tracking
RECAPTCHA_KEY(empty)Google reCAPTCHA site key
AXE_DEVELOPER_HUB_API_KEY(empty)Axe DevHub API key for automated accessibility reporting
VariableDefaultDescription
SHOW_PUBLIC_LOTTERYTRUEEnables lottery-related UI and the FAQ page
SHOW_MANDATED_ACCOUNTSFALSERequires applicants to create an account before applying
SHOW_PWDLESSFALSEEnables passwordless (magic link) authentication
SHOW_NEW_SEEDS_DESIGNSFALSEEnables updated UI using the latest ui-seeds design tokens
ALLOW_SEO_INDEXINGFALSESet to TRUE in production only; enables search engine indexing
RUN_ACCESSIBILITY_E2E_TESTSFALSEEnables accessibility checks in the Cypress E2E suite

Testing

The public portal has two test suites.
Run the full end-to-end test suite against a running instance of the app:
yarn test
Run from within sites/public/ with the app already running on port 3000.
Set RUN_ACCESSIBILITY_E2E_TESTS=TRUE in .env to also run axe-based accessibility checks during the Cypress suite.

Styling

The public portal uses Tailwind CSS for utility classes combined with ui-seeds CSS custom properties for design tokens (colors, spacing, typography). SASS is used for component-level styles.
If you use VSCode, install the CSS Variable Autocomplete extension to get autocompletion for all ui-seeds CSS variables. After installing, add the following to your user settings JSON:
{
  "cssVariables.lookupFiles": [
    "**/*.css",
    "**/*.scss",
    "**/*.sass",
    "**/*.less",
    "node_modules/@bloom-housing/ui-seeds/src/**/*.scss"
  ],
  "cssVariables.blacklistFolders": [
    "**/.git",
    "**/node_modules/^(?!@bloom-housing).*/m"
  ]
}

Build docs developers (and LLMs) love