Skip to content

Commit 6cfb70e

Browse files
hfurkanbozkurtH. Furkan Bozkurt
andauthored
feat: update aws-amplify plugin (#156)
* feat: update aws-amplify skill with comprehensive Gen2 content * fix: resolve build validation error --------- Co-authored-by: H. Furkan Bozkurt <bozkurh@amazon.com>
1 parent 399a001 commit 6cfb70e

21 files changed

Lines changed: 3493 additions & 382 deletions

plugins/aws-amplify/skills/amplify-workflow/SKILL.md

Lines changed: 192 additions & 185 deletions
Large diffs are not rendered by default.
Lines changed: 277 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,277 @@
1+
# Advanced Features
2+
3+
## Geo (Location) — Backend + Frontend
4+
5+
Add map display and location search using CDK constructs in
6+
`amplify/backend.ts`:
7+
8+
```typescript
9+
import { defineBackend } from '@aws-amplify/backend';
10+
import * as geo from 'aws-cdk-lib/aws-location';
11+
12+
const backend = defineBackend({ auth });
13+
const geoStack = backend.createStack('GeoStack');
14+
15+
const placeIndex = new geo.CfnPlaceIndex(geoStack, 'PlaceIndex', {
16+
dataSource: 'Esri',
17+
indexName: 'myPlaceIndex',
18+
});
19+
20+
const map = new geo.CfnMap(geoStack, 'Map', {
21+
mapName: 'myMap',
22+
configuration: { style: 'VectorEsriNavigation' },
23+
});
24+
25+
backend.addOutput({
26+
geo: {
27+
aws_region: geoStack.region,
28+
maps: { items: { [map.mapName]: { style: 'VectorEsriNavigation' } } },
29+
search_indices: { items: [placeIndex.indexName] },
30+
},
31+
});
32+
```
33+
34+
Grant authenticated users access via IAM policy on the geo resources.
35+
36+
**Frontend:** Install `@aws-amplify/geo` and `maplibre-gl-js-amplify`.
37+
Use `Amplify.Geo.searchByText()` for search and `AmplifyMapLibreRequest`
38+
for rendering maps. See
39+
[AWS Amplify Geo docs](https://docs.amplify.aws/react/build-a-backend/add-aws-services/geo/)
40+
for full client setup.
41+
42+
## PubSub — Backend + Frontend
43+
44+
Real-time messaging via AWS IoT Core. Configure an IoT endpoint and
45+
attach an IAM policy for authenticated users in `amplify/backend.ts`:
46+
47+
```typescript
48+
import * as iam from 'aws-cdk-lib/aws-iam';
49+
50+
const pubsubStack = backend.createStack('PubSubStack');
51+
52+
backend.auth.resources.authenticatedUserIamRole.addToPrincipalPolicy(
53+
new iam.PolicyStatement({
54+
actions: ['iot:Connect', 'iot:Publish', 'iot:Subscribe', 'iot:Receive'],
55+
resources: [
56+
`arn:aws:iot:*:*:client/\${cognito-identity.amazonaws.com:sub}`,
57+
`arn:aws:iot:*:*:topic/amplify/*`,
58+
`arn:aws:iot:*:*:topicfilter/amplify/*`,
59+
],
60+
})
61+
);
62+
63+
backend.addOutput({
64+
custom: { iotEndpoint: 'your-iot-endpoint.iot.region.amazonaws.com' },
65+
});
66+
```
67+
68+
**Frontend** — subscribe and publish:
69+
70+
```typescript
71+
import { PubSub } from '@aws-amplify/pubsub';
72+
73+
const sub = PubSub.subscribe({ topics: ['myTopic'] }).subscribe({
74+
next: (data) => console.log('Message:', data),
75+
error: (err) => console.error(err),
76+
});
77+
78+
await PubSub.publish({ topics: ['myTopic'], message: { msg: 'hello' } });
79+
sub.unsubscribe(); // MUST unsubscribe to prevent leaks
80+
```
81+
82+
When using subscriptions in React, **MUST** wrap in `useEffect` and return
83+
cleanup function to call `.unsubscribe()`.
84+
85+
Retrieve the IoT endpoint programmatically:
86+
`aws iot describe-endpoint --endpoint-type iot:Data-ATS`.
87+
See [AWS Amplify PubSub docs](https://docs.amplify.aws/react/build-a-backend/add-aws-services/pubsub/)
88+
for connection configuration.
89+
90+
## Custom CDK Stacks — Backend Only
91+
92+
Create additional CloudFormation stacks for resources not natively
93+
supported by Amplify:
94+
95+
```typescript
96+
const backend = defineBackend({ auth, data });
97+
const customStack = backend.createStack('AnalyticsStack');
98+
99+
// Use any CDK construct in the custom stack
100+
import * as sns from 'aws-cdk-lib/aws-sns';
101+
const topic = new sns.Topic(customStack, 'NotificationTopic');
102+
103+
// Access Amplify resources from custom stack
104+
const userPool = backend.auth.resources.userPool;
105+
```
106+
107+
Stack names **MUST** be unique within the backend — duplicate names cause
108+
deployment failures. Use descriptive names like `'EmailStack'`,
109+
`'AnalyticsStack'`.
110+
111+
## Backend Overrides — Backend Only
112+
113+
Access and modify underlying CloudFormation resources when Amplify's
114+
high-level API does not expose a needed property:
115+
116+
```typescript
117+
const backend = defineBackend({ auth, data });
118+
119+
// Auth override: Access the underlying CFN user pool resource
120+
const cfnUserPool = backend.auth.resources.cfnResources.cfnUserPool;
121+
cfnUserPool.policies = {
122+
passwordPolicy: {
123+
minimumLength: 12,
124+
requireLowercase: true,
125+
requireUppercase: true,
126+
requireNumbers: true,
127+
requireSymbols: true,
128+
},
129+
};
130+
131+
// DynamoDB override: Access underlying CFN resources
132+
const { cfnResources } = backend.data.resources;
133+
134+
// Enable point-in-time recovery
135+
cfnResources.amplifyDynamoDbTables['Todo'].pointInTimeRecoveryEnabled = true;
136+
137+
// Change billing mode
138+
cfnResources.amplifyDynamoDbTables['Todo'].billingMode = 'PAY_PER_REQUEST';
139+
140+
// Set TTL
141+
cfnResources.amplifyDynamoDbTables['Todo'].timeToLiveAttribute = {
142+
attributeName: 'ttl',
143+
enabled: true,
144+
};
145+
```
146+
147+
The entry point for DynamoDB table overrides is
148+
`backend.data.resources.cfnResources.amplifyDynamoDbTables['ModelName']`,
149+
which exposes L1 CFN properties directly.
150+
151+
To add a **Global Secondary Index**, use `.secondaryIndexes()` in the
152+
schema definition (the Amplify-native approach) rather than CDK overrides:
153+
154+
```typescript
155+
const schema = a.schema({
156+
Todo: a.model({
157+
content: a.string(),
158+
status: a.string(),
159+
createdAt: a.datetime(),
160+
})
161+
.secondaryIndexes(index => [
162+
index('status').sortKeys(['createdAt']),
163+
])
164+
.authorization(allow => [allow.owner()]),
165+
});
166+
```
167+
168+
See
169+
[AWS Amplify Override docs](https://docs.amplify.aws/react/build-a-backend/add-aws-services/overriding-resources/)
170+
for the full override API.
171+
172+
## Custom Outputs — Backend Only
173+
174+
Expose custom resource values to the frontend via `amplify_outputs.json`:
175+
176+
```typescript
177+
backend.addOutput({
178+
custom: {
179+
analyticsTopicArn: topic.topicArn,
180+
apiEndpoint: 'https://api.example.com',
181+
},
182+
});
183+
```
184+
185+
Values appear under the `custom` key in `amplify_outputs.json`. Frontend
186+
reads them from the Amplify configuration after `Amplify.configure()`.
187+
188+
## Face Liveness — Backend + Frontend
189+
190+
Verify user identity with Amazon Rekognition Face Liveness. Add IAM
191+
permissions in `amplify/backend.ts`:
192+
193+
```typescript
194+
import * as iam from 'aws-cdk-lib/aws-iam';
195+
196+
backend.auth.resources.authenticatedUserIamRole.addToPrincipalPolicy(
197+
new iam.PolicyStatement({
198+
actions: [
199+
'rekognition:CreateFaceLivenessSession',
200+
'rekognition:StartFaceLivenessSession',
201+
'rekognition:GetFaceLivenessSessionResults',
202+
],
203+
resources: ['*'], // Rekognition session ARNs are generated at runtime — scope with conditions if needed
204+
})
205+
);
206+
```
207+
208+
**Frontend (React):**
209+
210+
```bash
211+
npm install @aws-amplify/ui-react-liveness
212+
```
213+
214+
```tsx
215+
import { FaceLivenessDetector } from '@aws-amplify/ui-react-liveness';
216+
217+
<FaceLivenessDetector
218+
sessionId={sessionId}
219+
region="us-east-1"
220+
onAnalysisComplete={async () => { /* fetch results */ }}
221+
/>
222+
```
223+
224+
Create the session server-side via Rekognition SDK or a Lambda function,
225+
then pass the `sessionId` to the component. See
226+
[AWS Amplify Liveness docs](https://ui.docs.amplify.aws/react/connected-components/liveness)
227+
for the full integration guide.
228+
229+
**Frontend (Swift — iOS 14+):**
230+
231+
Requires the `amplify-ui-swift-liveness` package and camera permission
232+
(`NSCameraUsageDescription` in `Info.plist`). Add the package via Xcode SPM:
233+
`https://github.com/aws-amplify/amplify-ui-swift-liveness`.
234+
235+
The backend must include a Cognito Identity Pool with an IAM role that
236+
grants `rekognition:StartFaceLivenessSession` and
237+
`rekognition:GetFaceLivenessSessionResults`.
238+
239+
See [Swift Liveness docs](https://ui.docs.amplify.aws/swift/connected-components/liveness)
240+
for the full SwiftUI integration guide.
241+
242+
**Frontend (Android — API 24+):**
243+
244+
Add the dependency to `app/build.gradle.kts`:
245+
246+
```kotlin
247+
dependencies {
248+
implementation("com.amplifyframework.ui:liveness:1.+")
249+
}
250+
```
251+
252+
Requires Jetpack Compose. The backend must include a Cognito Identity Pool
253+
with an IAM role that grants `rekognition:StartFaceLivenessSession` and
254+
`rekognition:GetFaceLivenessSessionResults`.
255+
256+
See [Android Liveness docs](https://ui.docs.amplify.aws/android/connected-components/liveness)
257+
for the full Compose integration guide.
258+
259+
## Pitfalls
260+
261+
- **Duplicate stack names:** `backend.createStack()` names **MUST** be
262+
unique across the entire backend — reusing a name causes deployment failures.
263+
- **Missing IAM permissions:** Geo, PubSub, and Face Liveness all require
264+
explicit IAM policies — Amplify does not auto-grant access to these
265+
services.
266+
- **Geo CDK setup:** Geo (maps, place search, geofencing) requires CDK
267+
constructs — there is no `defineGeo()` in Amplify Gen2. Use
268+
`aws-cdk-lib/aws-location` directly as shown above.
269+
- **PubSub endpoint:** You **MUST** configure the correct IoT endpoint for
270+
your region; using the wrong endpoint type causes silent connection
271+
failures.
272+
273+
## Links
274+
275+
- [Add AWS Services](https://docs.amplify.aws/react/build-a-backend/add-aws-services/)
276+
- [Custom Resources](https://docs.amplify.aws/react/build-a-backend/add-aws-services/custom-resources/)
277+
- [Overriding Resources](https://docs.amplify.aws/react/build-a-backend/add-aws-services/overriding-resources/)

0 commit comments

Comments
 (0)