Project Structure

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


Layout overview

While specifics can vary based on .projenrc.ts, the starter kit ships with the structure below:

.
├── .github/workflows/      # Generated CI/CD pipelines
├── .projenrc.ts            # Single source of truth for project config
├── docs/                   # Docusaurus docs (this site)
├── 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

  • src/main.ts: bootstraps the CDK app, wires in environment variables, and instantiates FoundationStack/StarterStack with environment-aware names. This is the file you update when adding or reordering stacks.
  • src/stacks/: holds deployable stacks. foundation-stack.ts provisions GitHub OIDC; starter-stack.ts is where you begin adding resources. Export them through src/stacks/index.ts.
  • src/constructs/: reusable building blocks that extend BaseConstruct for consistent naming and context.
  • src/bin/: helper utilities (env-helper.ts, cicd-helper.ts, git-helper.ts) consumed by .projenrc.ts to generate tasks and workflows. See Helpers reference.
  • src/aspects/: guardrails applied across stacks (permissions boundaries, S3 policies, VPC CIDR checks). Documented in Aspects reference.
  • src/assets/: sample Lambda and ECS code. Replace or expand this directory when shipping infrastructure + application code together.
  • docs/: edit these MDX files to keep project documentation in sync with the repo.

Key concepts

  • Constructs vs. stacks: Encapsulate resources in constructs under src/constructs and compose them in stacks under src/stacks.
  • Environment-aware naming: src/main.ts and createEnvResourceName suffix stack and resource IDs with the selected environment or branch for safe multi-account deployments.
  • Projen tasks everywhere: npm run <task> delegates to Projen-generated tasks so the same commands power local and CI workflows.

Add a new stack

  1. Create a new file in src/stacks/, e.g. src/stacks/app-stack.ts, and define your Stack class.
  2. Export the stack from src/stacks/index.ts.
  3. Instantiate the stack in src/main.ts, ideally with createEnvResourceName to keep names environment/branch aware.
  4. Run npm run <environment>:synth to validate CloudFormation output before deploying.
// 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
  }
}
 
// src/main.ts
import { AppStack } from './stacks';
 
new AppStack(app, createEnvResourceName('AppStack'), { env: awsAccountConfig });

Add a reusable construct

Place constructs under src/constructs/, export them from src/constructs/index.ts, and consume them inside stacks. Extending BaseConstruct gives you access to the 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 });
  }
}
 
// src/stacks/starter-stack.ts
import { StorageBucket } from '../constructs';
 
new StorageBucket(this, 'AssetsBucket');

Remember to run npx projen after updating .projenrc.ts so new directories or tasks are tracked, and keep related documentation under docs/ up to date.