Getting Started

This guide walks you through setting up your local development environment and covers the most common developer workflows.

Prerequisites

  • Node.js 22+ (download)
  • pnpm package manager (npm i -g pnpm)
  • AWS CLI configured with access to the development account (730335631880)
  • An AWS profile for that account in ~/.aws/credentials or ~/.aws/config — scripts auto-select the profile matching the target account, with AWS_PROFILE as a fallback

Initial Setup

  1. Clone the repository:

    GITHUB_AUTH_HEADER="$(
      aws secretsmanager get-secret-value \
        --region us-east-1 \
        --secret-id gamecraft/backend/integration/secrets \
        --query SecretString \
        --output text |
        node -e 'const fs = require("node:fs"); const secret = JSON.parse(fs.readFileSync(0, "utf8")); const token = secret.GITHUB_TOKEN?.trim(); if (!token) process.exit(1); process.stdout.write(`Authorization: Basic ${Buffer.from(`x-access-token:${token}`).toString("base64")}`)'
    )" || { echo "Integration secret has no GITHUB_TOKEN" >&2; exit 1; }
    GIT_TERMINAL_PROMPT=0 \
    GIT_CONFIG_COUNT=3 \
    GIT_CONFIG_KEY_0=credential.helper \
    GIT_CONFIG_VALUE_0= \
    GIT_CONFIG_KEY_1=credential.interactive \
    GIT_CONFIG_VALUE_1=false \
    GIT_CONFIG_KEY_2=http.https://github.com/.extraHeader \
    GIT_CONFIG_VALUE_2="$GITHUB_AUTH_HEADER" \
    git clone https://github.com/trilogy-group/gamecraft.git
    unset GITHUB_AUTH_HEADER
    cd gamecraft
    
  2. Install dependencies (from root):

    pnpm install
    
  3. Populate your .env from a deployed environment:

    # Sync from the integration environment
    pnpm script update-env integration
    
    # Or sync from a specific PR environment
    pnpm script update-env 20
    

    This reads CloudFormation stack outputs + Secrets Manager values and writes them into the root .env file. All workspaces (backend, frontend, infra) share this single .env.

Local Development — Full Stack

To run both frontend and backend locally:

Step 1: Configure .env for localhost

After running update-env, override these two variables in your .env:

ENVIRONMENT=localhost
API_BASE_URL=http://localhost:3001

Step 2: Start the backend

cd apps/backend/
pnpm run dev          # Starts on http://localhost:3001
# or
pnpm run dev:watch    # Starts with auto-reload on file changes

The backend dev server serves all API routes on port 3001, including Scalar docs at /docs/viewer and OpenAPI spec at /docs/openapi.json. It resolves AWS credentials from your AWS_PROFILE.

Step 3: Start the frontend

cd apps/frontend/
pnpm run dev          # Starts on http://localhost:3000

Step 4: Open the app

Navigate to: http://localhost:3000?setEnv=localhost

The ?setEnv=localhost query parameter tells the frontend to use http://localhost:3001 as the API backend. This setting is persisted in browser storage, so you only need the query parameter once.

Hot-Connecting to Remote Backends

You can run the frontend locally (pnpm run dev in apps/frontend/) and point it at any deployed backend using the ?setEnv query parameter. No backend changes needed.

http://localhost:3000?setEnv=integration    # Points to integration backend
http://localhost:3000?setEnv=production     # Points to production backend
http://localhost:3000?setEnv=pr0020         # Points to a specific PR environment
http://localhost:3000?setEnv=localhost       # Switch back to local

The setting is persisted in browser storage. To switch, just navigate with a different ?setEnv value — the page reloads with the new config.

API Contracts

The monorepo is oRPC contract-first. Shared contracts live under packages/shared/api/<module>/contracts/, with request/response models under packages/shared/api/<module>/models/.

Backend module routers implement those contracts with *.orpc-router.ts files and mount them under their Lambda path prefixes. The frontend builds typed oRPC clients from the same contracts via ApiClientService, and hooks use getApiQueryUtils() with TanStack Query for server state.

Typical Workflow: Add a Backend Endpoint and Use it in Frontend

  1. Add or update the contract in packages/shared/api/<module>/contracts/.
  2. Implement the backend router in apps/backend/app/<module>/routers/<module>.orpc-router.ts.
  3. Mount the module in its container under the existing /module/v1 prefix.
  4. Use in frontend hooks via getApiQueryUtils().<module>.<procedure>.queryOptions() or .mutationOptions().
  5. Regenerate API tests with pnpm generate:api-tests if the API surface changed.
  6. Commit the shared contract, backend implementation, frontend usage, and regenerated test artifacts.

API Tests

The packages/api-tests/ package contains auto-generated integration tests that run against a deployed backend. Tests validate that each endpoint returns successful responses with the expected schema.

Generated tests live in packages/api-tests/generated/ (overwritten on regeneration). Put custom tests in packages/api-tests/shared/ (committed) or packages/api-tests/private/ (gitignored).

Prerequisites

Before running API tests, ensure:

  1. Your .env has API_BASE_URL pointing to the target backend
  2. Your .env has API_USERNAME and API_PASSWORD set (populated automatically by pnpm script update-env from SSM after a deploy)
  3. Your .env has USER_POOL_CLIENT_ID set

Running Tests

cd packages/api-tests/

# Run all tests
pnpm run test

# Run only generated tests
pnpm run test:generated

# Run only shared (hand-written) tests
pnpm run test:shared

Tests run sequentially (no concurrency) with a 30-second timeout. Authentication is handled automatically — the test setup fetches and caches a Cognito token before all tests.

Regenerating Tests

When contract-backed backend endpoints change, regenerate the API test files:

# From the repo root
pnpm generate:api-tests

This reads /docs/openapi.json for operation discovery and generates .test.ts and .fixture.ts files that call typed oRPC clients. Use pnpm generate:api-tests -- --offline --no-seed to regenerate from the local mock app without touching a deployed environment.

Testing Against Different Environments

# Test against integration
pnpm script update-env integration
cd packages/api-tests && pnpm run test

# Test against a PR environment
pnpm script update-env 20
cd packages/api-tests && pnpm run test

# Test against local backend
# (update .env: API_BASE_URL=http://localhost:3001)
cd packages/api-tests && pnpm run test

Quality Checks

From the repo root:

pnpm run check   # Lint + type-check across all workspaces
pnpm run fix     # Auto-fix lint and formatting issues

From the backend directory:

cd apps/backend/
pnpm run test         # Run unit tests once
pnpm run test:watch   # Run unit tests in watch mode

Troubleshooting

Login button doesn't work

  1. Open browser console — look for 🔧 Localhost configuration: log
  2. Verify USER_POOL_ID, USER_POOL_CLIENT_ID, USER_POOL_DOMAIN are set in .env
  3. Restart the Vite dev server after .env changes
  4. Navigate to http://localhost:3000?setEnv=localhost to force-reset

AWS credential errors

The backend dev server resolves credentials from AWS_PROFILE on startup and refreshes every 45 minutes. If your SAML session expires:

  1. Re-authenticate with saml2aws login
  2. Restart the backend dev server

Environment not found

If update-env fails, ensure:

  • The CloudFormation stack for the target environment exists
  • A profile for the target account (730335631880) exists in ~/.aws/credentials or ~/.aws/config — the script auto-selects it and reports which profile it picked
  • Use --wait flag if the stack is still deploying: pnpm script update-env integration --wait