Usage Examples

Common tasks like adding stacks, composing constructs, and parameterizing deployments.


Add resources to the starter stack

The quickest way to begin is by extending StarterStack in src/stacks/starter-stack.ts.

// src/stacks/starter-stack.ts
import * as cdk from 'aws-cdk-lib';
import * as s3 from 'aws-cdk-lib/aws-s3';
import { Construct } from 'constructs';
 
export class StarterStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props: cdk.StackProps) {
    super(scope, id, props);
 
    new s3.Bucket(this, 'ArtifactsBucket', {
      blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
      versioned: true,
      encryption: s3.BucketEncryption.S3_MANAGED,
    });
  }
}

Tagging, naming, and branch-awareness are already handled in src/main.ts, so resources you add here inherit the environment tags configured in the app.

Add a new stack alongside the starter stack

  1. Create src/stacks/app-stack.ts with your new Stack implementation.
  2. Export it from src/stacks/index.ts.
  3. Instantiate it in src/main.ts using createEnvResourceName to keep names branch-aware.
// 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/stacks/index.ts
export { AppStack } from './app-stack';
 
// src/main.ts (imports above omitted for brevity)
import { AppStack } from './stacks';
 
new AppStack(app, createEnvResourceName('AppStack'), { env: awsAccountConfig });

Run npm run test:synth (or swap test for another environment) to confirm the new stack synthesizes cleanly before deploying.

Compose constructs for reuse

Create constructs under src/constructs/ and extend BaseConstruct to gain environment, account, region, and branch helpers.

// src/constructs/storage-bucket.ts
import * as s3 from 'aws-cdk-lib/aws-s3';
import { Construct } from 'constructs';
import { BaseConstruct } from './base-construct';
 
export class StorageBucket extends BaseConstruct {
  public readonly bucket: s3.Bucket;
 
  constructor(scope: Construct, id: string, props?: s3.BucketProps) {
    super(scope, id);
    this.bucket = new s3.Bucket(this, 'Bucket', {
      bucketName: this.unique('artifacts'),
      blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
      encryption: s3.BucketEncryption.S3_MANAGED,
      ...props,
    });
  }
}

Use the construct inside any stack:

import { StorageBucket } from '../constructs';
 
new StorageBucket(this, 'ArtifactsBucket', { versioned: true });

Bring in the opinionated VPC

NetworkConstruct provisions a three-tier VPC with environment-specific CIDRs, endpoints, and flow logs. Uncomment and customize it inside StarterStack or another stack:

import { NetworkConstruct } from '../constructs';
 
const network = new NetworkConstruct(this, 'Network');
// network.vpc is available for ECS clusters, RDS, etc.

Because NetworkConstruct inherits from BaseConstruct, VPC names and the flow-log bucket automatically include environment or branch suffixes, keeping parallel deployments isolated.

Use branch-specific stack actions locally

All environment tasks have branch variants. This makes it easy to preview infrastructure changes without affecting shared stacks:

git checkout -b feature/cost-reduction
npm run test:branch:deploy:stack StarterStack
npm run test:branch:destroy:stack StarterStack

Branch deploy tasks set GIT_BRANCH_REF, so stack names and resource tags include the cleaned branch suffix. The Environments guide covers the workflow end to end.