Deploying Photos
The Photos product (images.theaccessible.org) has three deployable parts. The
frontend calls the shared API, so order matters and the API change is not
photos-specific.
| Part | Path | Deploy command | Serves |
|---|---|---|---|
| HTTP API (primary) | workers/api | npm run deploy:lambda | api-pdf.theaccessible.org via AWS Lambda + API Gateway |
| Node server | repo root | npm run rebuild | batch/async work on 10.1.1.4 (builds remotely from origin/main, zero-downtime) |
| Frontend | apps/photos | npm run deploy | images.theaccessible.org (Cloudflare Worker) |
β οΈ The one thing that bites: two API entry points
workers/api has two app compositions and they drift:
src/index-aws.tsβ bundled bysrc/lambda.tsβ AWS Lambda. This is the production HTTP API the frontends call.src/index.tsβ the Node server Docker image on10.1.1.4.
Any new API route module must be app.route()-mounted in BOTH files. A route
registered only in index.ts passes local tests but returns a generic
{code:"NOT_FOUND"} 404 on api-pdf.theaccessible.org β it was never live on the
serverless API. (This is exactly how the photos backend shipped dark until the
mount was added to index-aws.ts.) The smoke test below guards against it.
Prerequisites
- Run from the main checkout (
~/Projects/accessible), not a git worktree. Worktrees have partial deps; the Lambda build (build:lambda+ CDK synth) needs the full monorepo. If you must deploy from a worktree, first run:npm install(root),npm --prefix infra/cdk install, andnpm --prefix workers/email-intake run build(CDK synth validates every Lambda asset path, even when deploying only the API stack). - AWS credentials authed (
aws sts get-caller-identity). wranglerauthed (npx wrangler whoami).- SSH key for the Node server (
~/.ssh/nightly-auditβlarry@10.1.1.4).
Steps
-
Merge to
main. Production deploys build from the merged code (npm run rebuildliterallygit reset --hard origin/mainon the server). -
Deploy the API to Lambda (do this before the frontend, or new endpoints 404):
Terminal window cd workers/api && npm run deploy:lambdaDeploys
AccessiblePdfProd-Api(+ its dependency stacks). Acurrent credentials could not be used to assume β¦ Proceeding anywayline is a benign root-creds warning. -
Rebuild the Node server (only needed if
index.ts/batch code or migrations changed; safe/zero-downtime otherwise):Terminal window npm run rebuild # from repo root -
Smoke the API before shipping the frontend:
Terminal window npm --prefix apps/photos run smoke:prodAll checks must pass β especially
photos route mounted(assertsPHOTO_NOT_FOUND, proving the routes are on the Lambda). -
Deploy the frontend:
Terminal window cd apps/photos && npm run deploy -
Smoke again and do a quick manual e2e: sign in β upload (alt text required) β comment β follow β copy an embed code and confirm the iframe renders with alt text.
Migrations
No migration runs as part of these deploys. If a PR adds a non-additive
migration, apply it before the Node rebuild (see the general DB deploy notes);
new photos routes to date reuse existing tables (photo_comments, follows,
activity_events).
Rollback
- Lambda: redeploy the previous commit (
git checkout <sha>βnpm run deploy:lambda); CloudFormation updates the function in place. - Frontend:
wrangler rollbackon thetheaccessible-imagesworker, or redeploy a prior commit. - Node server:
npm run rebuildafter pointingorigin/mainback, or roll the branch back and rebuild.
Smoke checklist (what smoke:prod verifies)
GET /healthβ 200,status: healthyGET /api/photos/photo/<nonexistent>β 404PHOTO_NOT_FOUND(routes mounted on Lambda)GET /api/photos/meβ 401 (auth-gated route present)GET /api/photos/embed/photo/<nonexistent>β 404, HTML βPhoto unavailableβGET images.theaccessible.org/β 200