Skip to main content

Local Development

Overview

This guide sets up a local development environment for iterating on backend and frontend code against deployed AWS infrastructure. By the end, the FastAPI backend is running on localhost:8000 with hot-reload, the React frontend is running on localhost:8080 with API requests proxied to the backend, and environment variables are configured to reach deployed Cognito, DynamoDB, and SQS resources.

When to Use This Guide

Use this guide when:

  • A successful /ipa.deploy has completed and it is time to start writing application code
  • A new developer is onboarding and needs a working local environment
  • Switching between deployed environments (for example, from dev to stage) and the local environment variables need updating
  • Troubleshooting backend or frontend code against live AWS infrastructure without redeploying

Before You Start

Before starting, confirm the following:

  • .env file exists with APP_NAMESPACE, APP_ENV, AWS_REGION, and AWS_ACCOUNT_ID set
  • At least one environment has been deployed with /ipa.deploy (the backend stack provides DynamoDB tables the local server connects to)
  • Python 3.12 is installed
  • uv is installed (Python package manager)
  • Node.js 22+ and npm are installed
  • AWS CLI is configured with credentials for the target account (via AWS_PROFILE or the default credential chain)

Before / Target State

BeforeAfter
Deployed AWS infrastructure (DynamoDB, Cognito, SQS). No local servers running. Code changes require redeployment to test.FastAPI backend on localhost:8000 with auto-reload. React frontend on localhost:8080 with Vite proxy forwarding API requests. Code changes are reflected immediately without redeployment.

Steps

1. Sync environment variables from deployed stacks

To populate .env with the latest outputs from deployed CloudFormation stacks (Cognito, ECR, SQS), run from the project root:

make -f scripts/env.mk update-env

The command queries each deployed stack and writes the output values to .env. The terminal displays confirmation messages for each stack:

Writing OIDC configuration to .env...
Writing ECR configuration to .env...
Writing SQS configuration to .env...

To sync a single stack, use the specific target:

make -f scripts/env.mk update-env-cognito
make -f scripts/env.mk update-env-ecr
make -f scripts/env.mk update-env-sqs
note

The scripts/env.mk file is generated by /ipa.compose. If the file does not exist, run /ipa.compose first.

2. Start the backend

To install Python dependencies, run from the project root:

cd app-lib && make sync

This runs uv sync --all-extras, installing all backend dependencies including FastAPI, uvicorn, PynamoDB, and boto3 into the local .venv.

To start the FastAPI development server with auto-reload, run from the project root:

make dev-backend

The backend starts on http://localhost:8000. The terminal displays:

INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process

To verify the backend is running, open a new terminal and run:

curl http://localhost:8000/health

Expected output:

{"status":"ok"}

The interactive API documentation is available at http://localhost:8000/docs.

3. Start the frontend

To install Node.js dependencies, run from the project root:

cd web-client && npm install

The postinstall script automatically copies the OIDC service worker to public/.

To start the Vite development server, run from the project root:

make dev-frontend

The frontend starts on http://localhost:8080. Vite is preconfigured to proxy /api, /health, and /version requests to the backend at http://localhost:8000. No additional proxy configuration is required.

Open http://localhost:8080 in a browser. The React application loads and API requests are forwarded to the local backend automatically.

4. Optional: Configure Cognito authentication locally

By default, authentication is enabled (AUTH_ENABLED=true). For local development without a deployed Cognito stack, disable it by setting the environment variable before starting the backend:

export AUTH_ENABLED=false

To test with Cognito authentication enabled locally:

a. Confirm the OIDC values are present in .env by running the sync from Step 1, or verify that OIDC_ISSUER and OIDC_CLIENT_ID are set.

b. Create web-client/public/config.local.js to override the frontend OIDC configuration:

window.__CONFIG__ = {
...window.__CONFIG__,
OIDC_AUTHORITY: "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXX",
OIDC_CLIENT_ID: "your-cognito-client-id",
OIDC_REDIRECT_URI: "http://localhost:8080/authentication/callback",
OIDC_END_SESSION_ENDPOINT: "https://your-domain.auth.us-east-1.amazoncognito.com/logout",
};

Replace the placeholder values with the actual OIDC values from .env. The config.local.js file is gitignored and loaded only on localhost.

warning

The Cognito User Pool must include http://localhost:8080/authentication/callback in its allowed callback URLs. If the callback URL is missing, add it to the Cognito stack parameters and redeploy with /ipa.deploy.

d. Restart both the backend and frontend for the changes to take effect.

Verification

To confirm the local environment is fully operational:

  1. Verify the backend health endpoint:

    curl http://localhost:8000/health

    Expected: {"status":"ok"}

  2. Verify the backend version endpoint:

    curl http://localhost:8000/version

    Expected: {"version":"1.0.0","build":"dev"}

  3. Open http://localhost:8080 in a browser and confirm the React application loads.

  4. Confirm a round-trip API call by navigating to a data page (for example, the Passengers page) and verifying that data loads from the deployed DynamoDB table through the local backend.

Troubleshooting

ProblemLikely CauseFix
curl: (7) Failed to connect to localhost port 8000Backend is not running or failed to startCheck the terminal for startup errors. Confirm Python 3.12 and uv are installed. Run cd app-lib && make sync to reinstall dependencies.
DynamoDB AccessDeniedException in backend logsAWS credentials are missing or the region does not match the deployed stacksConfirm AWS_REGION in .env matches the deployment region. Verify AWS CLI credentials with aws sts get-caller-identity.
CORS errors in the browser consoleFrontend is not using the Vite proxy (requests going directly to the backend)Confirm API_BASE_URL is empty in web-client/public/config.js. The Vite proxy handles routing when API_BASE_URL is not set.
Cognito redirects to an error page after loginlocalhost:8080 is not in the allowed callback URLs for the Cognito User PoolAdd http://localhost:8080/authentication/callback to the Cognito stack's CallbackURLs parameter and redeploy.
Port 8000 or 8080 already in useAnother process is listening on the required portIdentify the process with lsof -i :8000 or lsof -i :8080 and stop it before starting the development servers.

Next Steps

  • Notebook Development — Prototype and test with Jupyter notebooks connected to deployed resources
  • Regenerate API client — With the backend running, run cd web-client && npm run codegen to update the TypeScript API client from the OpenAPI schema
  • Backend developer docs — See the app-lib/ CLAUDE.md for backend architecture, feature structure, and testing conventions
  • Frontend developer docs — See the web-client/ CLAUDE.md for frontend architecture, component placement, and API layer conventions
  • Tear down the deployment — Run /ipa.destroy to remove deployed infrastructure when no longer needed