CDK app scaffolded with StorageStack, ApiStack, and ConversionStack; stack split separates concerns

dropthejase built the infra foundation as a CDK app with a stage helper and three independently deployable stacks. The stack split is the most reusable design decision here - each stack owns one concern with cross-stack values passed via CDK outputs or constructor props, not direct construct references.

infrastructure

StorageStack provisions two S3 buckets (docs, private + CORS; frontend, private) and a CloudFront distribution with OAC pointing at the frontend bucket, with a 404→200 SPA fallback. The CORS allowedOrigins starts as ['*'] and is later locked to the CloudFront domain.

ApiStack creates a Secrets Manager secret for Supabase credentials, an API Lambda IAM role with S3 read/write and scoped Bedrock model ARNs, a REST API Gateway with a Lambda Token authorizer on all routes, and Lambda + Gateway CORS wiring. The initial Lambda is an inline placeholder, replaced in a subsequent commit by the backend Dockerfile.lambda container.

ConversionStack uses DockerImageFunction for the LibreOffice Lambda and wires S3 event notifications for .docx and .doc uploads to the documents/ prefix. The bucket is imported by ARN rather than passed as a construct to avoid a cross-stack notification dependency cycle.

A notable 08884d4 sets RemovalPolicy.DESTROY with autoDeleteObjects: true on all buckets for clean POC teardown. This is a deliberate POC choice; it needs to be reversed before production use.

The Lambda Token authorizer is a pre-Cognito stub. It is replaced by a native Cognito User Pool authorizer in a later commit not covered in this topic.

So what Worth a look if you are setting up CDK for a similar stack. The Storage/Api/Conversion split is a reasonable blast-radius boundary. Do not copy the `RemovalPolicy.DESTROY` bucket setting or the early Lambda authorizer stub - both are explicitly temporary.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

11 commits from dropthejase/louis, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
1d051296 feat(infra): scaffold CDK app with stage helper Jason Lee 2026-05-06 ↗ GitHub
2883c4d4 feat(infra): add StorageStack with docs bucket, frontend bucket, CloudFront Jason Lee 2026-05-06 ↗ GitHub
8002cb79 feat(infra): add ApiStack with REST API Gateway, Lambda, Secrets Manager Jason Lee 2026-05-06 ↗ GitHub
39ec1eaf feat(infra): add ConversionStack with LibreOffice Lambda container placeholder Jason Lee 2026-05-06 ↗ GitHub
commit body
Adds ConversionStack (DockerImageFunction + S3 event notifications for .docx/.doc).
Uses bucket ARN/name strings instead of the bucket construct to break the cross-stack
dependency cycle that S3 event notifications would otherwise cause. Also fixes
Lambda authorizer import to use fromFunctionAttributes with sameEnvironment=true.

c948bc3e chore(infra): add env example for downstream plans Jason Lee 2026-05-06 ↗ GitHub
69bd0507 feat(infra): wire Supabase secret into ConversionStack Lambda Jason Lee 2026-05-06 ↗ GitHub
d62d2a00 feat(infra): ApiStack - wire Lambda to backend Dockerfile.lambda, add Bedrock IAM Jason Lee 2026-05-06 ↗ GitHub
7f6592d8 fix(infra): AuthStack - use NodejsFunction+esbuild for authorizer (no pre-build needed) Jason Lee 2026-05-06 ↗ GitHub
01909358 Merge feature/infra-cdk: CDK stacks (Storage, Auth, Api, Conversion) Jason Lee 2026-05-06 ↗ GitHub
a24c896b Merge feature/conversion: LibreOffice Lambda container Jason Lee 2026-05-06 ↗ GitHub
08884d4e fix(infra): set RemovalPolicy.DESTROY on all buckets for clean POC teardown Jason Lee 2026-05-08 ↗ GitHub

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-330.md from inside the repo you want the changes in.

⬇ Download capture-thread-330.md