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 instantiatesFoundationStack
/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 throughsrc/stacks/index.ts
.src/constructs/
: reusable building blocks that extendBaseConstruct
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 undersrc/stacks
. - Environment-aware naming:
src/main.ts
andcreateEnvResourceName
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
- Create a new file in
src/stacks/
, e.g.src/stacks/app-stack.ts
, and define yourStack
class. - Export the stack from
src/stacks/index.ts
. - Instantiate the stack in
src/main.ts
, ideally withcreateEnvResourceName
to keep names environment/branch aware. - 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.