Initial one-time setup. After this, all deploys are fully automated via GitHub Actions (OIDC).
- An AWS account with local AWS CLI authenticated (
aws sts get-caller-identitysucceeds) - Node.js 22 / pnpm 9 / aws-cdk@2 or later
- A Supabase project (free tier works)
- A GitHub Personal Access Token (PAT) for Amplify integration
[1] Configure environment variables
↓
[2] GitHub OIDC Provider setup (once per AWS account)
↓
[3] CDK Bootstrap (once per account × region)
↓
[4] First cdk deploy (local)
↓
[5] Set GitHub Repository Variables
↓
[6] All future deploys are automatic on push to main
Copy .env.example to .env.local and fill in your values:
cp .env.example .env.localKey values to set:
| Variable | Where to find it |
|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Supabase Dashboard → Project Settings → API |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
Supabase Dashboard → Project Settings → API |
SUPABASE_SERVICE_ROLE_KEY |
Supabase Dashboard → Project Settings → API |
DATABASE_URL |
Supabase Dashboard → Project Settings → Database → Connection string (Transaction mode) |
DIRECT_URL |
Supabase Dashboard → Project Settings → Database → Connection string (Session mode) |
AWS_ACCOUNT_ID |
aws sts get-caller-identity --query Account --output text |
AWS_REGION |
Your preferred AWS region (e.g. us-east-1) |
PARENT_DOMAIN |
Your root domain (e.g. example.com) — must be in Route 53 |
APP_SUBDOMAIN |
Your app subdomain (e.g. pm.example.com) |
Check if it already exists:
aws iam list-open-id-connect-providers \
--query "OpenIDConnectProviderList[?contains(Arn, 'token.actions.githubusercontent.com')]"If empty, create it:
aws iam create-open-id-connect-provider \
--url https://token.actions.githubusercontent.com \
--client-id-list sts.amazonaws.com \
--thumbprint-list 6938fd4d98bab03faadb97b34396831e3780aea1# Check if already bootstrapped
aws cloudformation describe-stacks --stack-name CDKToolkit \
--query "Stacks[0].StackStatus" --output text 2>/dev/nullIf not bootstrapped yet:
cd infra
pnpm install
npx cdk bootstrap aws://$(aws sts get-caller-identity --query Account --output text)/${AWS_REGION:-us-east-1}Run once locally before GitHub Actions takes over:
# Set environment
export AWS_REGION=us-east-1 # your region
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
export PARENT_DOMAIN=example.com # your root domain
export APP_SUBDOMAIN=pm.example.com # your app subdomain
# Preview changes
pnpm cdk:diff
# Deploy (IAM → DNS → Amplify)
pnpm cdk:deployThis creates:
WillinkStack-Iam— GitHub Actions OIDC role (willink-stack-github-actions)WillinkStack-Dns— Route 53 Hosted Zone referenceWillinkStack-Amplify— Amplify Hosting app + custom domain
Note the output values:
WillinkStack-Iam.GitHubActionsRoleArnOutput— needed for the next step
Allow 5–15 minutes for ACM certificate validation and initial Amplify build.
Go to: Repository Settings → Secrets and variables → Actions → Variables
Add these Repository variables:
| Variable | Value |
|---|---|
AWS_ACCOUNT_ID |
Your 12-digit AWS account ID |
AWS_REGION |
Your AWS region (e.g. us-east-1) |
PARENT_DOMAIN |
Your root domain (e.g. example.com) |
APP_SUBDOMAIN |
Your app subdomain (e.g. pm.example.com) |
ALERT_EMAIL |
Email for budget/ops alerts (optional) |
SUPABASE_PROJECT_REF |
Supabase project reference (from project URL) |
Add these Repository secrets:
| Secret | Value |
|---|---|
AMPLIFY_GITHUB_TOKEN |
GitHub PAT with repo + admin:repo_hook scopes |
NEXT_PUBLIC_SUPABASE_URL |
Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
Supabase anon key |
SUPABASE_SERVICE_ROLE_KEY |
Supabase service role key |
DATABASE_URL |
Postgres connection string (transaction mode) |
DIRECT_URL |
Postgres connection string (session mode) |
SUPABASE_ACCESS_TOKEN |
Supabase CLI access token (for migrations) |
SUPABASE_DB_PASSWORD |
Supabase database password |
# Trigger a manual deploy
gh workflow run deploy.yml --repo YOUR_ORG/willink-stack
gh run watch --repo YOUR_ORG/willink-stackOnce it passes, all future deploys are automatic on push to main.
Check your local AWS profile:
aws sts get-caller-identityThe amplify.yml build spec enables corepack + pnpm. Check the build logs in the Amplify console for details.
DNS propagation and ACM certificate issuance can take 15–30 minutes. Check the Domain management section in the Amplify console for status.