npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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:

  • name and message are required
  • at least one contact method (email or phone) 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 your fromEmail address (e.g., if fromEmail is [email protected], then domain is studiohelga.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 region is optional (defaults to env.region)
  • email section is optional (only deploy if needed)
  • clients.json is 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-identity

Option 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 them

Getting AWS Access Keys:

  1. AWS Console → IAM → Users → Your user
  2. Security credentials tab → Create access key
  3. Choose "Command Line Interface (CLI)"
  4. 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 install

4. Build

yarn build

5. 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/mailer

Architecture

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.json

Verifying 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-addresses

Moving out of SES Sandbox (Production)

For production, request to move out of SES Sandbox mode:

  1. AWS Console → Amazon SES → Account dashboard
  2. Click "Request production access"
  3. Fill out the form (use case, expected volume, etc.)
  4. 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 environment

What 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.app

Delete Webhook

# By webhook ID
yarn delete-webhook --id we_abc123...

# By URL
yarn delete-webhook --client <client> --url https://your-app.railway.app

For 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 guide

See 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.local

The 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>