All skills
aws avatar

/aws-amplify

@7898a91

Build and deploy full-stack web and mobile apps with AWS Amplify Gen2 (TypeScript code-first). Covers auth (Cognito), data (AppSync/DynamoDB), storage (S3), functions, APIs, and AI (Amplify AI Kit with Bedrock). Supports React, Next.js, Vue, Angular, React Native, Flutter, Swift, and Android. Always use this skill for Amplify Gen2 topics — even for questions you think you know — it contains validated, version-specific patterns that prevent common mistakes. TRIGGER when: user mentions Amplify Gen2; project has amplify/ directory or amplify_outputs; code imports @aws-amplify packages; user asks about defineBackend, defineAuth, defineData, defineStorage, defineFunction, or npx ampx. SKIP: Amplify Gen1 (amplify CLI v6), standalone SAM/CDK without Amplify (use aws-serverless), direct Bedrock without Amplify AI Kit (use bedrock).

Use this Skill: https://skilld.dev/gh/aws/agent-toolkit-for-aws/aws-amplify

This session only. Nothing lands on disk.

referencesgeo-pubsub-cdk.md

≈2.5k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Advanced Features

Prerequisites: Backend defined in amplify/backend.ts with defineBackend({ auth, data }).

Geo (Location) — Backend + Frontend

Add map display and location search using CDK constructs in amplify/backend.ts:

import { defineBackend } from '@aws-amplify/backend';
import * as geo from 'aws-cdk-lib/aws-location';

const backend = defineBackend({ auth });
const geoStack = backend.createStack('GeoStack');

const placeIndex = new geo.CfnPlaceIndex(geoStack, 'PlaceIndex', {
  dataSource: 'Esri',
  indexName: 'myPlaceIndex',
});

const map = new geo.CfnMap(geoStack, 'Map', {
  mapName: 'myMap',
  configuration: { style: 'VectorEsriNavigation' },
});

backend.addOutput({
  geo: {
    aws_region: geoStack.region,
    maps: { items: { [map.mapName]: { style: 'VectorEsriNavigation' } } },
    search_indices: { items: [placeIndex.indexName] },
  },
});

Grant authenticated users access via IAM policy on the geo resources.

Geo / Location (Frontend)

Install: npm install @aws-amplify/geo

import { Geo } from '@aws-amplify/geo';

const results = await Geo.searchByText('Seattle');

Note: Gen2 uses import { Geo } from '@aws-amplify/geo' — NOT Amplify.Geo.* (that namespace doesn't exist).

Constraint: Location Service resource names have a 100-character limit. Use short static names — avoid dynamic names like ${stack.stackName}-index.

For rendering maps, also install maplibre-gl-js-amplify. See AWS Amplify Geo docs for full client setup.

PubSub — Backend + Frontend

Install required: npm install @aws-amplify/pubsub — not included in the base aws-amplify package.

Real-time messaging via AWS IoT Core. Configure an IoT endpoint and attach an IAM policy for authenticated users in amplify/backend.ts:

import * as iam from 'aws-cdk-lib/aws-iam';

const pubsubStack = backend.createStack('PubSubStack');

backend.auth.resources.authenticatedUserIamRole.addToPrincipalPolicy(
  new iam.PolicyStatement({
    actions: ['iot:Connect', 'iot:Publish', 'iot:Subscribe', 'iot:Receive'],
    resources: [
      `arn:aws:iot:*:*:client/\${cognito-identity.amazonaws.com:sub}`,
      `arn:aws:iot:*:*:topic/amplify/*`,
      `arn:aws:iot:*:*:topicfilter/amplify/*`,
    ],
  })
);

backend.addOutput({
  custom: { iotEndpoint: 'your-iot-endpoint.iot.region.amazonaws.com' },
});

Frontend — subscribe and publish:

import { PubSub } from '@aws-amplify/pubsub';

const sub = PubSub.subscribe({ topics: ['myTopic'] }).subscribe({
  next: (data) => console.log('Message:', data),
  error: (err) => console.error(err),
});

await PubSub.publish({ topics: ['myTopic'], message: { msg: 'hello' } });
sub.unsubscribe();  // Always unsubscribe to prevent leaks

When using subscriptions in React, wrap in useEffect and return cleanup function to call .unsubscribe().

Retrieve the IoT endpoint programmatically: aws iot describe-endpoint --endpoint-type iot:Data-ATS.

Custom CDK Stacks — Backend Only

Create additional CloudFormation stacks for resources not natively supported by Amplify:

const backend = defineBackend({ auth, data });
const customStack = backend.createStack('AnalyticsStack');

// Use any CDK construct in the custom stack
import * as sns from 'aws-cdk-lib/aws-sns';
const topic = new sns.Topic(customStack, 'NotificationTopic');

// Access Amplify resources from custom stack
const userPool = backend.auth.resources.userPool;

Stack names must be unique within the backend — duplicate names cause deployment failures. Use descriptive names like 'EmailStack', 'AnalyticsStack'.

Backend Overrides — Backend Only

Access and modify underlying CloudFormation resources when Amplify's high-level API does not expose a needed property:

const backend = defineBackend({ auth, data });

// Auth override: Access the underlying CFN user pool resource
const cfnUserPool = backend.auth.resources.cfnResources.cfnUserPool;
cfnUserPool.policies = {
  passwordPolicy: {
    minimumLength: 12,
    requireLowercase: true,
    requireUppercase: true,
    requireNumbers: true,
    requireSymbols: true,
  },
};

// DynamoDB override: Access underlying CFN resources
const { cfnResources } = backend.data.resources;

// Enable point-in-time recovery
cfnResources.amplifyDynamoDbTables['Todo'].pointInTimeRecoveryEnabled = true;

// Change billing mode
cfnResources.amplifyDynamoDbTables['Todo'].billingMode = 'PAY_PER_REQUEST';

// Set TTL
cfnResources.amplifyDynamoDbTables['Todo'].timeToLiveAttribute = {
  attributeName: 'ttl',
  enabled: true,
};

The entry point for DynamoDB table overrides is backend.data.resources.cfnResources.amplifyDynamoDbTables['ModelName'], which exposes L1 CFN properties directly.

To add a Global Secondary Index, use .secondaryIndexes() in the schema definition (the Amplify-native approach) rather than CDK overrides:

const schema = a.schema({
  Todo: a.model({
    content: a.string(),
    status: a.string(),
    createdAt: a.datetime(),
  })
  .secondaryIndexes(index => [
    index('status').sortKeys(['createdAt']),
  ])
  .authorization(allow => [allow.owner()]),
});

See AWS Amplify Override docs for the full override API.

Custom Outputs — Backend Only

Expose custom resource values to the frontend via amplify_outputs.json:

backend.addOutput({
  custom: {
    analyticsTopicArn: topic.topicArn,
    apiEndpoint: 'https://api.example.com',
  },
});

Values appear under the custom key in amplify_outputs.json. Frontend reads them from the Amplify configuration after Amplify.configure().

Face Liveness — Backend + Frontend

Verify user identity with Amazon Rekognition Face Liveness. Add IAM permissions in amplify/backend.ts:

import * as iam from 'aws-cdk-lib/aws-iam';

backend.auth.resources.authenticatedUserIamRole.addToPrincipalPolicy(
  new iam.PolicyStatement({
    actions: [
      'rekognition:CreateFaceLivenessSession',
      'rekognition:StartFaceLivenessSession',
      'rekognition:GetFaceLivenessSessionResults',
    ],
    resources: ['*'], // Rekognition session ARNs are generated at runtime — scope with conditions if needed
  })
);

Frontend (React):

npm install @aws-amplify/ui-react-liveness
import { FaceLivenessDetector } from '@aws-amplify/ui-react-liveness';

<FaceLivenessDetector
  sessionId={sessionId}
  region="us-east-1"
  onAnalysisComplete={async () => { /* fetch results */ }}
/>

Create the session server-side via Rekognition SDK or a Lambda function, then pass the sessionId to the component. See AWS Amplify Liveness docs for the full integration guide.

Frontend (Swift — iOS 14+):

Requires the amplify-ui-swift-liveness package and camera permission (NSCameraUsageDescription in Info.plist). Add the package via Xcode SPM: https://github.com/aws-amplify/amplify-ui-swift-liveness.

The backend must include a Cognito Identity Pool with an IAM role that grants rekognition:StartFaceLivenessSession and rekognition:GetFaceLivenessSessionResults.

See Swift Liveness docs for the full SwiftUI integration guide.

Frontend (Android — API 24+):

Add the dependency to app/build.gradle.kts:

dependencies {
    implementation("com.amplifyframework.ui:liveness:1.+")
}

Requires Jetpack Compose. The backend must include a Cognito Identity Pool with an IAM role that grants rekognition:StartFaceLivenessSession and rekognition:GetFaceLivenessSessionResults.

See Android Liveness docs for the full Compose integration guide.

Avoiding Circular Dependencies

Complex apps with storage triggers + auth groups + data models can create circular CloudFormation dependencies. Solutions:

  1. Incremental deployment: Deploy auth + data first, then add storage triggers in a subsequent deployment
  2. Separate stacks: Use backend.createStack('storage-triggers') to isolate trigger resources
  3. Avoid .handler() + manual grants: When using a.query().handler(fn), don't also call grantReadData() — .handler() auto-grants access

See: Troubleshoot circular dependencies

Storage Triggers Writing to Data Tables — BLOCKED

Storage triggers that need to write to DynamoDB tables in the data stack create a circular dependency that CANNOT be resolved with resourceGroupName.

Workarounds:

  1. Have the trigger write to a separate DynamoDB table (created via CDK, not defineData)
  2. Use EventBridge to decouple: trigger → EventBridge → Lambda → DynamoDB
  3. Handle metadata creation client-side after upload completes

Pitfalls

  • Duplicate stack names: backend.createStack() names must be unique across the entire backend — reusing a name silently overwrites.
  • Missing IAM permissions: Geo, PubSub, and Face Liveness all require explicit IAM policies — Amplify does not auto-grant access to these services.
  • Geo CDK setup: Geo (maps, place search, geofencing) requires CDK constructs — there is no defineGeo() in Amplify Gen2. Use aws-cdk-lib/aws-location directly as shown above.
  • PubSub endpoint: Configure the correct IoT endpoint for your region — using the wrong endpoint type causes silent connection failures.

Links

Source: SKILL.md on GitHub

No alerts16d3 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    This skill provides comprehensive instructions for building applications with AWS Amplify Gen2. It includes security considerations such as the use of command-line tools for cloud resource management and the ingestion of user-provided data for infrastructure generation. These patterns are standard for developer assistant tools and are supported by best-practice recommendations within the skill, such as secure secret management.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

Signed by skilld at 7898a91. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 3 months ago

README badge

README badge for aws/agent-toolkit-for-aws/aws-amplify