Project Structure

Understand how the AWS CDK Starter Kit organizes constructs, stacks, configuration, and automation.


Overview

The starter kit follows an opinionated structure designed for maintainability and scalability. Everything flows from .projenrc.ts, which generates configuration files, scripts, and workflows.

Directory layout

.
├── .github/workflows/      # Generated CI/CD pipelines
├── .projenrc.ts            # Single source of truth for project config
├── src/
│   ├── aspects/            # Governance aspects applied across stacks
│   ├── assets/             # Lambda/ECS sample source packaged with stacks
│   ├── bin/                # Projen helpers for tasks and workflows
│   ├── constructs/         # Reusable L2/L3 patterns built on BaseConstruct
│   ├── main.ts             # CDK app entry point and stack instantiation
│   └── stacks/             # Deployable stacks (Foundation, Starter, etc.)
├── test/                   # Jest unit tests and snapshots
├── package.json            # npm scripts (delegating to Projen tasks)
└── README.md

Key directories

DirectoryPurpose
src/main.tsCDK app entry point. Wires environment variables and instantiates stacks with environment-aware names.
src/stacks/Deployable stacks. foundation-stack.ts provisions GitHub OIDC; starter-stack.ts is your starting point.
src/constructs/Reusable building blocks extending BaseConstruct.
src/bin/Helper utilities (env-helper.ts, cicd-helper.ts) consumed by .projenrc.ts. See Helpers reference.
src/aspects/Guardrails applied across stacks. See Aspects reference.
src/assets/Sample Lambda and ECS code. Replace when shipping infrastructure + application together.

Key concepts

Constructs vs. stacks

  • Constructs - Encapsulate resources in reusable units under src/constructs/. See our guide on CDK constructs.
  • Stacks - Compose constructs into deployable units under src/stacks/. See our guide on CDK stacks.

Environment-aware naming

src/main.ts and createEnvResourceName suffix stack and resource IDs with the environment or branch name. This enables safe multi-account and multi-branch deployments.

Projen tasks everywhere

npm run <task> delegates to Projen-generated tasks. The same commands power local and CI workflows. See Projen reference.

For a deeper dive, see our guide on optimizing your AWS CDK project structure.

Add a new stack

  1. Create the file in src/stacks/:
// src/stacks/app-stack.ts
import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class AppStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
    // Add resources here
  }
}
  1. Export from src/stacks/index.ts:
export { AppStack } from './app-stack';
  1. Instantiate in src/main.ts:
import { AppStack } from './stacks';

new AppStack(app, createEnvResourceName('AppStack'), { env: awsAccountConfig });
  1. Validate:
npm run test:synth

Add a reusable construct

Place constructs under src/constructs/ and extend BaseConstruct for environment, account, region, and branch helpers.

// src/constructs/storage-bucket.ts
import { Bucket, BucketProps } from 'aws-cdk-lib/aws-s3';
import { Construct } from 'constructs';
import { BaseConstruct } from './base-construct';

export class StorageBucket extends BaseConstruct {
  public readonly bucket: Bucket;

  constructor(scope: Construct, id: string, props?: BucketProps) {
    super(scope, id);
    this.bucket = new Bucket(this, 'Bucket', { versioned: true, ...props });
  }
}

Use in stacks:

import { StorageBucket } from '../constructs';

new StorageBucket(this, 'AssetsBucket');

Important: Run npx projen after updating .projenrc.ts so new directories or tasks are tracked.

Next steps