A tenant access application for the New Jersey Innovation Authority. This application provides secure access management and interfaces for tenants.
This is a modern React application built with Vite and TypeScript, organized as an npm workspace monorepo. The project emphasizes type safety, testing, and code quality through automated tooling.
- React 19 - UI library
- React Router 7 - Client-side routing
- TypeScript 7 - Type-safe JavaScript
- Vite 8 - Build tool and dev server
- Vitest 4 - Unit testing framework
- Testing Library - Component testing utilities
- Biome - Linting and formatting
- Husky - Git hooks
tenant-access/
├── app/ # Frontend application workspace (React + Vite)
│ ├── src/ # Application source code
│ ├── public/ # Static assets
│ └── package.json # App-specific dependencies
├── api/ # Backend workspace (AWS Lambda, TypeScript)
│ ├── src/ # Lambda handler source code
│ └── package.json # API-specific dependencies
├── .github/ # GitHub workflows and templates
├── .husky/ # Git hooks
└── package.json # Root workspace configuration
The api workspace is a minimal skeleton for the planned backend: a Lambda
that communicates with a PostgreSQL database. It is configured for a Node
runtime (its own tsconfig.json, separate from the frontend) with a
placeholder handler. Build tooling, database client, and deployment are not
yet chosen. Build/typecheck it with npm run build:api.
- Node.js (version specified in
.nvmrc) - npm (comes with Node.js)
# Clone this repository
git clone https://github.com/newjersey/tenant-access
# Go into the repository
cd tenant-access
# Install dependencies
npm installThis is an npm workspace monorepo: the root package.json owns the workspace configuration and the single package-lock.json, and dependencies are hoisted to the root node_modules. Always install from the repository root, targeting the app workspace:
# Runtime dependency for the app
npm install <package> --workspace=app
# Dev-only dependency for the app
npm install --save-dev <package> --workspace=appCommit the updated app/package.json and the root package-lock.json together in the same change. CI runs npm ci, which installs strictly from the committed lockfile and fails if it is out of sync with package.json.
This project uses the AWS CDK to deploy its infrastructure. To make updates, edit api/infrastructure/lib/tenant-access-stack.ts and then run npx cdk deploy with the proper AWS credentials in your environment variables.
# Create a new migration file with the date prefix
bash api/scripts/create_migration.sh <description>
# Example:
# bash api/scripts/create_migration.sh create_listings_table
# This creates the file:
# api/migrations/20260804110544_create_listings_table.sql
# Then edit your new migration file with SQL-
The Migration Lambda in the
tenant-access-stack.tsCDK config file is bundled with the wholeapi/migrationsdirectory. Even thought the Lambda's code itself will rarely change, we need to do a CDK deployment to include any new migration files. -
Run
npx cdk deployto package the Lambda with the updated directory of migrations. -
Note the
MigrationLambdaNamein the output ofnpx cdk deploy. For example,TenantAccessStack.MigrationLambdaName = TenantAccessStack-MigrationFunction1060F2E0-DfbZthsVWubo -
Run the lambda with its name and the filename for the new migration.
aws lambda invoke \
--function-name INSERT_LAMBDA_NAME \
--cli-binary-format raw-in-base64-out \
--payload '{"migrationFile":"INSERT_SQL_FILENAME"}' \
/tmp/out.json && cat /tmp/out.json
# For example:
aws lambda invoke \
--function-name TenantAccessStack-MigrationFunction1060F2E0-DfbZthsVWubo \
--cli-binary-format raw-in-base64-out \
--payload '{"migrationFile":"20260804110544_create_listings_table.sql"}' \
/tmp/out.json && cat /tmp/out.json
If you see a happy JSON like {"statusCode":200,"body":"{\"success\":true,\"migration\":\"20260804110544_create_listings_table.sql\",\"message\":\"Migration completed successfully\"}"}, it was a success. Otherwise, you can debug using CloudWatch.
Start the development server with hot module replacement:
npm run devThe application will be available at http://localhost:5173
Create a production build:
npm run buildPreview the production build locally:
npm run preview# Run tests in watch mode
npm test
# Run tests with UI
npm run test:ui
# Run tests with coverage report
npm run test:coverage# Check formatting
npm run format:check
# Fix formatting issues
npm run format
# Run linter
npm run lint
# Fix linting issues
npm run lint:fix
# Run both checks and fixes
npm run check:fixGit hooks are configured via Husky to automatically run code quality checks on commit.
- Test-driven development (TDD)
- YAGNI - build only what's needed now
- Accessibility (WCAG 2.2 AA compliance)
- Simple, maintainable solutions over clever complexity
This project is licensed under the MIT license. For more information, see LICENSE.
This project utilizes certain tools and technologies for development purposes. The inclusion of these tools does not imply endorsement or recommendation. Users are encouraged to evaluate the suitability of these tools for their own use.