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.

referencesdata-web.md

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

Data — Web

Prerequisites: Project initialized, amplify_outputs.json exists (from npx ampx sandbox), and Amplify.configure(outputs) called in app entry point.

Backend required: Data must be defined in amplify/data/resource.ts using defineData — see data-backend.md.

Client Setup

Call generateClient<Schema>() at module scope (outside any component). Calling it inside a component creates a new client on every render, breaking subscriptions, caching, and causing memory leaks.

import { generateClient } from 'aws-amplify/data';
import type { Schema } from '../amplify/data/resource';

// Module scope — called once
const client = generateClient<Schema>();

The <Schema> generic gives full type inference on all model operations.

CRUD Operations

All operations return { data, errors }. You SHOULD check errors before using data.

const { data, errors } = await client.models.Todo.create({ content: 'Ship feature', priority: 'high' });

Same shape for .list(), .get({ id }), .update({ id, done: true }), .delete({ id }). .list() accepts an optional filter: { filter: { done: { eq: false } } }.

Error Handling

You SHOULD handle both GraphQL-level errors and network failures:

try {
  const { data, errors } = await client.models.Todo.create({ content: 'New todo' });
  if (errors) { /* handle GraphQL field/validation errors */ }
} catch (err) {
  /* handle network or unexpected errors */
}

Real-Time

  • observeQuery() — auto-updating list, returns { items } snapshots. Recommended default.
  • onCreate() / onUpdate() / onDelete() — per-event subscriptions.

Both return an observable; call .subscribe({ next }) and call sub.unsubscribe() in cleanup.

useEffect(() => {
  const sub = client.models.Todo.observeQuery().subscribe({
    next: ({ items }) => setTodos(items),
  });
  return () => sub.unsubscribe();
}, []);

Filtering Subscriptions

useEffect(() => {
  const sub = client.models.Vote.observeQuery({
    filter: { pollId: { eq: currentPollId } },
  }).subscribe({
    next: ({ items }) => setVotes(items),
  });
  return () => sub.unsubscribe();
}, [currentPollId]);

When to Use Which

Pattern Best For
observeQuery() Continuously updated lists — handles pagination, filtering, deduplication. Use by default.
onCreate / onUpdate / onDelete Fine-grained control — animations, toasts, or single event type only.

observeQuery does NOT support server-side sorting. Sort results client-side after receiving them.

Server-Side (Next.js)

import { generateServerClientUsingCookies } from '@aws-amplify/adapter-nextjs/data';
import { cookies } from 'next/headers';
import outputs from '@/amplify_outputs.json';
import type { Schema } from '@/amplify/data/resource';

const cookieClient = generateServerClientUsingCookies<Schema>({ config: outputs, cookies });

Use cookieClient.models.* the same as the browser client. Works in Server Components, Server Actions, and App Router API routes.

React Native

Identical to the web client — uses generateClient<Schema>() from aws-amplify/data. All CRUD, observeQuery(), and subscription APIs (onCreate, onUpdate, onDelete) are the same.

Querying a Secondary Index

// Backend: define with queryField name
.secondaryIndexes(index => [
  index('pollId').sortKeys(['voterId']).queryField('votesByPollAndVoter')
])

// Frontend: call by name
const { data } = await client.models.Vote.votesByPollAndVoter({
  pollId: currentPollId,
  voterId: { eq: currentVoterId },
});

JSON Fields — Serialization Asymmetry

a.json() fields require JSON.stringify() on write but auto-parse on read:

// Write: stringify before saving
await client.models.Config.create({
  metadata: JSON.stringify({ key: "val", nested: { a: 1 } })
});

// Read: auto-parsed back to object
const { data } = await client.models.Config.get({ id });
console.log(data.metadata.key); // "val" — already an object

Passing a raw object on write fails silently with: "Variable 'metadata' has an invalid value"

(The a.json() field maps to GraphQL's AWSJSON scalar, which expects a JSON-encoded string as input.)

Pitfalls

  • Array field updates = full replacement: Array fields have no append/remove operations. You must read, modify, and write the entire array:

    const item = await client.models.Todo.get({ id });
    const updated = [...(item.data?.tags ?? []), 'newTag'];
    await client.models.Todo.update({ id, tags: updated });

    Risk: Concurrent updates can overwrite each other. For frequently-modified lists, consider a separate model with a relationship instead.

  • Subscription memory leaks: useEffect must return () => sub.unsubscribe() as a cleanup function. Without it, subscriptions accumulate across re-renders, causing memory leaks and duplicate data updates.

  • Wrong auth mode for subscriptions: Subscriptions require a WebSocket-compatible auth mode (userPool or iam). API key auth on subscriptions fails silently.

  • Missing <Schema> generic: generateClient() without <Schema> returns an untyped client — all operations lose autocomplete and type checking.

  • Server client without cookies: Using generateClient() in Next.js server components fails (no browser session) — use generateServerClientUsingCookies instead.

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