@studio-helga/infrastructure-cdk
v1.0.1
Published
Modular AWS CDK infrastructure for client deployments
Downloads
43
Readme
Infrastructure CDK
Modular AWS CDK infrastructure for client deployments. Deploy only what each client needs.
For teams consuming the published package, see CONSUMING.md.
Features
- S3 Image Buckets - For Strapi image uploads
- Email/SES - Contact form functionality
- Config-driven - Specify what to deploy per client
- Reusable - One package, multiple deployments
- Email API types - Published as
@studio-helga/email-api-types(also re-exported from this package)
Frontend Types (Email API)
Recommended:
import type { EmailApiRequest } from "@studio-helga/email-api-types";Or via this package:
import type { EmailApiRequest } from "@studio-helga/infrastructure-cdk";
const payload: EmailApiRequest = {
name: "Charlotte",
email: "[email protected]",
message: "I want help with my website",
businessName: "My Business",
formSource: "small-business-websites",
additionalPoints: [{ label: "Budget", value: "£99/month" }],
};EmailApiRequest enforces:
nameandmessageare required- at least one contact method (
emailorphone) is required - optional metadata fields must match the backend contract
For publishing steps, see PUBLISHING.md.
Usage
1. Configure for your client
Copy config/clients.template.json to config/clients.json (gitignored) before deploy. Edit config/clients.json and add your clients:
{
"example": {
"clientName": "example",
"env": {
"region": "eu-west-1"
},
"s3Images": {
"publicRead": true,
"versioning": true,
"cors": true
}
},
"my-client": {
"clientName": "my-client",
"env": {
"region": "eu-west-2"
},
"s3Images": {
"publicRead": true,
"versioning": true,
"cors": true
},
"email": {
"fromEmail": "[email protected]",
"toEmail": "[email protected]",
"domain": "studio-domain.com",
"allowedOrigins": ["https://example.com", "http://localhost:3000"]
}
}
}Email Configuration Explained:
fromEmail- The email address that sends the contact form emails (must be verified in AWS SES)- Use the Studio Helga email address (already verified and can send to any address)
toEmail- The email address that receives the contact form submissions (your client's email)domain- The domain part of yourfromEmailaddress (e.g., iffromEmailis[email protected], thendomainisstudiohelga.co.uk)allowedOrigins(optional) - CORS allowlist for the email API. Defaults to["*"]if omitted.- Important: This is NOT the client's website domain - it's the domain of YOUR email address
Example: Sending contact forms for a client's website at example.com:
"email": {
"fromEmail": "[email protected]",
"toEmail": "[email protected]",
"domain": "studiohelga.co.uk"
}- ✉️ Emails are sent FROM
[email protected](your email) - 📬 Emails are received BY
[email protected](client's email) - 🌐 Domain is
studiohelga.co.uk(matches the sender's email domain, not the client's website)
Notes:
- ✅ S3
regionis optional (defaults toenv.region) - ✅
emailsection is optional (only deploy if needed) - ✅
clients.jsonis gitignored - ⚠️ Important: Email addresses must be verified in AWS SES
fromEmail(the Studio Helga email) - Already verified ✅toEmail(recipient emails) - Must be verified in SES Sandbox mode- For production: Request to move out of SES Sandbox to send to any address
- See "Verifying Email Addresses" section below
2. Configure AWS Credentials
Option A: AWS CLI (Recommended)
# Configure AWS CLI with your credentials
aws configure
# Enter:
# AWS Access Key ID: your-access-key-id
# AWS Secret Access Key: your-secret-access-key
# Default region: eu-west-1
# Default output format: json
# Verify it works
aws sts get-caller-identityOption B: Environment Variables (Good for multiple AWS accounts)
# Copy the example file
cp env.example .env
# Edit .env and add your credentials
# The scripts will automatically load .env when you run themGetting AWS Access Keys:
- AWS Console → IAM → Users → Your user
- Security credentials tab → Create access key
- Choose "Command Line Interface (CLI)"
- Save the Access Key ID and Secret Access Key
Required Permissions:
- S3 (create/manage buckets)
- SES (send emails, if deploying email)
- Lambda + API Gateway (if deploying email)
- CloudFormation (deploy stacks)
- IAM (create roles)
3. Install dependencies
cd packages/infrastructure-cdk
yarn install4. Build
yarn build5. Deploy
# Bootstrap CDK (first time only, per account/region)
yarn cdk bootstrap
# Preview changes (synth generates CloudFormation)
yarn synth <client>
# See what will change
yarn diff <client>
# Deploy (same key as in clients.json; no extra `--` needed)
yarn deploy <client>The deploy / synth / diff scripts run node ./dist/cli.js …, so yarn deploy <client> passes the client reliably (the CLI also loads .env and .env.local from this directory). After pulling dependency changes, run yarn install from the monorepo root, then yarn build here.
Note: yarn deploy, yarn synth, and yarn diff load .env and .env.local via the CLI. yarn cdk (and the webhook scripts) still use dotenv-cli the same way as before. You do not need to source .env manually for those flows.
Outputs
After deployment, the stack outputs will include:
- S3BucketName / S3BucketRegion / S3PublicBaseUrl - For your Strapi
.env - EmailMailerEndpoint - Full contact form endpoint for frontend apps
Environment Variables
The deployed resources will provide these values for your apps:
Strapi (from S3 bucket output)
AWS_S3_BUCKET=my-client-strapi-images
AWS_REGION=eu-west-2
# You'll need to add your IAM credentials separately
AWS_ACCESS_KEY_ID=...
AWS_ACCESS_SECRET=...Frontend (from Email API output)
CONTACT_FORM_API=https://...execute-api.eu-west-2.amazonaws.com/mailerArchitecture
infrastructure-cdk/
├── src/
│ ├── config/
│ │ └── types.ts # Configuration interfaces
│ ├── constructs/
│ │ ├── s3-bucket.ts # S3 image bucket construct
│ │ └── email.ts # Email/SES construct
│ ├── stacks/
│ │ └── infrastructure-stack.ts # Main stack
│ ├── lambdas/
│ │ └── sendEmail.ts # Email lambda function
│ └── app.ts # CDK app entry point
└── cdk.jsonVerifying Email Addresses in SES
When in SES Sandbox mode (default for new AWS accounts), you can only send emails TO verified addresses. This is a security measure by AWS.
Verify a recipient email address
# Verify a client's email address
yarn aws ses verify-email-identity --email-address [email protected]
# Or verify your own email for testing
yarn aws ses verify-email-identity --email-address [email protected]This sends a verification email to that address. The recipient must click the link to verify.
Verify the sender email (if using a different one)
If you want to use a different sender email (not the Studio Helga email):
# Verify the new sender email
yarn aws ses verify-email-identity --email-address [email protected]
# Update clients.json with the new fromEmail
# Redeploy: yarn deploy <client>Check verified emails
# List all verified email addresses
yarn aws ses list-verified-email-addressesMoving out of SES Sandbox (Production)
For production, request to move out of SES Sandbox mode:
- AWS Console → Amazon SES → Account dashboard
- Click "Request production access"
- Fill out the form (use case, expected volume, etc.)
- Once approved, you can send to ANY email without verification
Note: In sandbox mode, emails may be slower to deliver. Production access provides faster, more reliable delivery.
Stripe Webhook Registration
Automatically register Stripe webhooks for production deployments.
Register Webhook
After deploying your Next.js app:
# Register webhook for your deployed app
yarn register-webhook --client <client> --url https://your-app.railway.app
# Output will include the webhook secret to add to your environmentWhat it does:
- Creates webhook endpoint in Stripe Dashboard
- Configures events:
checkout.session.completed,payment_intent.succeeded,charge.succeeded - Outputs webhook secret for your production environment
Add Stripe key to clients.json (locally only):
{
"example": {
"clientName": "example",
"stripeSecretKey": "sk_live_..."
}
}Or use environment variable:
export STRIPE_SECRET_KEY=sk_live_...
yarn register-webhook --client <client> --url https://your-app.railway.appDelete Webhook
# By webhook ID
yarn delete-webhook --id we_abc123...
# By URL
yarn delete-webhook --client <client> --url https://your-app.railway.appFor local development: Use Stripe CLI instead (see WebhookSetup.md)
Deploying Strapi to Railway
After deploying your infrastructure, you can deploy Strapi to Railway using the S3 bucket and other resources:
# 1. Deploy infrastructure first
yarn deploy <client>
# 2. Get environment variables for Railway
./scripts/get-strapi-env.sh <client>
# 3. Follow the Railway deployment guideSee RAILWAY_DEPLOYMENT.md for complete instructions.
The helper script automatically extracts:
- ✅ S3 bucket name
- ✅ AWS region
- ✅ Email mailer endpoint (if deployed)
- ✅ Templates for Strapi secrets
Configuring Next.js Client App
After deploying infrastructure and Strapi, configure your Next.js app:
# Get environment variables for your client app
./scripts/get-client-env.sh <client> https://your-strapi-app.railway.app
# Copy output to apps/<client>/.env.localThe helper script provides:
- ✅ Strapi URL and API token placeholder
- ✅ Email mailer endpoint (from CDK deployment)
- ✅ Stripe keys placeholders
- ✅ Site configuration templates
Multiple Clients
To deploy for multiple clients:
const clients = [
{ name: "client-a", ... },
{ name: "client-b", ... },
];
clients.forEach(config => {
new InfrastructureStack(app, `${config.name}-infrastructure`, {
config,
// ...
});
});Then deploy per clients.json key:
yarn deploy <client>