aws-amplify
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).
- 6,493
- installs
- 0 up / 0 down, score 0.00
- votes
- 2,930
- repo stars
- Updated
- less than a month ago
- In the catalog since
- 1 Oct 2026
- From
- aws/agent-toolkit-for-aws
Skill instructions
Rendered from the published SKILL.md, 381 lines.
AWS Amplify Gen2
Build and deploy full-stack applications using AWS Amplify Gen2's TypeScript code-first approach. This skill covers backend resource creation, frontend integration across 8 frameworks, and deployment workflows.
Prerequisites
- Node.js ^18.19.0 || ^20.6.0 || >=22 and npm
- AWS credentials configured (
aws sts get-caller-identitysucceeds) - For sandbox:
npx ampx --versionreturns a valid version - For mobile: Platform-specific tooling (Xcode, Android Studio, Flutter SDK)
Defaults & Assumptions
When the user does not specify a framework:
- Web: Default to React (Vite) and explain the choice.
- Mobile: Ask which platform (Flutter, Swift, Android, or React Native) — there is no universal mobile default, so guessing leads to wasted effort.
- Neither specified: If the user says "build an app" without clarifying web vs. mobile, ask before proceeding — the framework choice affects every subsequent step.
- Backend only: If only backend changes are requested and no frontend framework is mentioned, skip the frontend integration step entirely.
When the user does not specify tooling or strategy:
- Package manager: Default to npm unless the user specifies yarn or pnpm.
- Language: Default to TypeScript. Gen2 backends are TypeScript-only; frontends should follow the project's existing language.
- Next.js: Default to App Router unless the user specifies Pages Router.
- React Native: Ask whether the user uses Expo or bare React Native CLI.
- Auth: You MUST ask which login method the user wants (email/password, social login, SAML, passwordless, etc.). Do not assume a default.
- Data authorization: default to
publicApiKey(allow.publicApiKey()) — this is the starter template default. When auth is added, switch to owner-based (allow.owner()) withdefaultAuthorizationMode: 'userPool'.
Quick Start — Route to the Right Reference
Step 1: Identify the Task Type
| Task | Go To |
|---|---|
| Create a new project | → scaffolding.md, then Step 2 and/or Step 3 |
| Add or modify a backend feature | → Step 2 (Backend Features) |
| Connect frontend to existing backend | → Step 3 (Frontend Integration) |
| Deploy the application | → deployment.md |
Step 2: Backend Features
Read the corresponding reference for each backend feature you need:
| Feature | Reference | When to Use |
|---|---|---|
| Authentication | auth-backend.md | Email/password, social login, MFA, SAML/OIDC |
| Data Models | data-backend.md | GraphQL schema, DynamoDB, relationships, auth rules |
| File Storage | storage-backend.md | S3 uploads/downloads, access rules |
| Functions & API | functions-and-api.md | Lambda, custom resolvers, REST/HTTP APIs, calling from client |
| AI Features | ai.md | Conversation, generation, AI tools via Bedrock (backend config + React/Next.js frontend) |
| Geo, PubSub, CDK | geo-pubsub-cdk.md | Backend-only: custom CDK stacks, overrides, custom outputs. Backend + frontend: Geo, PubSub, Face Liveness |
Each backend feature file is self-contained. Load only what you need.
Routing note: These files apply for both adding and modifying features. Route to the same file whether the user says "add auth" or "change auth config" — each reference covers the full define surface.
Step 3: Frontend Integration
After configuring backend resources, connect the frontend. Choose by platform and feature:
Web (React, Next.js, Vue, Angular, React Native):
| Feature | Reference |
|---|---|
| Auth UI & flows | auth-web.md |
| Data CRUD & subscriptions | data-web.md |
| Storage upload/download | storage-web.md |
Mobile (Flutter, Swift, Android):
| Feature | Reference |
|---|---|
| Auth UI & flows | auth-mobile.md |
| Data CRUD & subscriptions | data-mobile.md |
| Storage upload/download | storage-mobile.md |
Note: AI and Functions frontend patterns are included in ai.md and functions-and-api.md respectively — they are not split into separate web/mobile files.
Core Concepts
Amplify Gen2 Architecture
- Code-first: All backend resources defined in TypeScript under
amplify/ - Main config:
amplify/backend.tsimports and combines all resources viadefineBackend() - Resource files:
amplify/auth/resource.ts,amplify/data/resource.ts,amplify/storage/resource.ts,amplify/functions/<name>/resource.ts - Generated output:
amplify_outputs.json— consumed by frontendAmplify.configure(). Gitignored — generated bynpx ampx sandbox(local dev) ornpx ampx pipeline-deploy(CI/CD), never committed.
Directory Structure
amplify/ and src/ must be siblings under the project root — placing
them at different directory levels breaks sandbox detection. (Exception: in monorepos, amplify/ may be in a packages/ subdirectory — the key is that amplify_outputs.json must be accessible from the frontend entry point.)
project-root/
├── amplify/
│ ├── backend.ts # defineBackend({ auth, data, ... })
│ ├── auth/resource.ts # defineAuth({ ... })
│ ├── data/resource.ts # defineData({ schema })
Show the whole skill (261 more lines)
│ ├── storage/resource.ts # defineStorage({ ... }) │ └── functions/ │ └── my-func/ │ ├── resource.ts # defineFunction({ ... }) │ └── handler.ts # export const handler = ... ├── src/ # Frontend code ├── amplify_outputs.json # Generated, gitignored — never edit or commit └── package.json
### Key APIs
| Package | Purpose |
|---------|---------|
| `@aws-amplify/backend` | `defineAuth`, `defineData`, `defineStorage`, `defineFunction`, `defineBackend` |
| `aws-amplify` | Frontend: `Amplify.configure()`, `generateClient()`, auth/data/storage APIs |
| `@aws-amplify/ui-react` | Pre-built UI: `<Authenticator>`, `<StorageBrowser>` |
| `@aws-amplify/ui-react-ai` | AI UI: `<AIConversation>`, `useAIConversation` |
## Framework Setup
These patterns apply to **every** web task — not just new projects. Verify
each one before implementing any feature.
### Gen2 Detection
Before modifying any code, check if the project is already Gen2:
1. `amplify/` directory exists with `backend.ts`
2. `@aws-amplify/backend` in `package.json` devDependencies
If both are true, the project is already Gen2 — skip to feature
implementation. If `amplify/.config/` exists instead, this is a Gen1
project — do not proceed (requires separate migration skill).
### Frontend Configuration
Import the generated outputs and configure Amplify in the **correct entry
point** for your framework. Placing this in the wrong file causes silent
failures — Amplify API calls return undefined or empty responses with no error.
**WARNING:** `amplify_outputs.json` must exist before the app can
compile — without it, the build fails with a module-not-found error.
Run `npx ampx sandbox` (or `npx ampx sandbox --once`) first to
generate it. See [scaffolding.md](references/scaffolding.md) for the correct sequence.
**React (Vite)** — `src/main.tsx`:
```typescript
import { Amplify } from 'aws-amplify';
import outputs from '../amplify_outputs.json';
Amplify.configure(outputs);
Next.js (App Router) — app/layout.tsx:
Important:
layout.tsxis a server component in App Router. Use theConfigureAmplifyClientSideclient component pattern below instead.
{ ssr: true } is a Next.js-only option (not needed by Vue, Angular, or React SPA). Both App Router and Pages Router use it, but apply it differently:
- App Router — set globally in
ConfigureAmplifyClientSideclient component- Pages Router — set per-file where server-side access is needed
Next.js App Router: Client-Side Configuration
Next.js App Router requires a dedicated client component to configure Amplify for browser-side operations:
// components/ConfigureAmplifyClientSide.tsx
"use client";
import { Amplify } from "aws-amplify";
import outputs from "@/amplify_outputs.json";
Amplify.configure(outputs, { ssr: true });
export default function ConfigureAmplifyClientSide() {
return null;
}
Import in your root layout:
// app/layout.tsx
import ConfigureAmplifyClientSide from "@/components/ConfigureAmplifyClientSide";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
<ConfigureAmplifyClientSide />
{children}
</body>
</html>
);
}
Why? In App Router,
layout.tsxis a server component. Client components needAmplify.configure()to run in the browser. Without this, you get "Auth UserPool not configured" errors.
Vue — src/main.js:
import { Amplify } from 'aws-amplify';
import outputs from '../amplify_outputs.json';
Amplify.configure(outputs);
Angular — src/main.ts:
import { Amplify } from 'aws-amplify';
import outputs from '../amplify_outputs.json';
Amplify.configure(outputs);
Next.js Pages Router
Pages Router does NOT need { ssr: true } in _app.tsx. Instead, configure per-file where you need server-side access:
// pages/api/protected.ts or getServerSideProps
import { Amplify } from 'aws-amplify';
import outputs from '@/amplify_outputs.json';
Amplify.configure(outputs, { ssr: true });
Key difference: App Router uses a global client component. Pages Router configures per-file.
<Authenticator.Provider> is required in layout.tsx for auth context.
React Native
React Native uses the same aws-amplify JS package as web frameworks (it is
part of amplify-js, not the native mobile SDKs). All web APIs apply to RN
with the additions below.
Required Packages
npm install aws-amplify @aws-amplify/react-native \
@react-native-async-storage/async-storage \
react-native-get-random-values
@react-native-async-storage/async-storage is required — the Amplify
SDK uses it for token persistence and will fail at runtime without it.
Configure Entry Points
No plugin registration needed — configure only.
React Native (Expo) — App.tsx:
import 'react-native-get-random-values'; // MUST be first
import { Amplify } from 'aws-amplify';
import outputs from './amplify_outputs.json';
Amplify.configure(outputs);
React Native (Bare CLI) — index.js (before AppRegistry.registerComponent):
import 'react-native-get-random-values'; // MUST be first
import { Amplify } from 'aws-amplify';
import outputs from './amplify_outputs.json';
Amplify.configure(outputs);
React Native Pitfalls
- Import order:
react-native-get-random-valuesmust be the FIRST import in the entry file, beforeaws-amplify. Reversing the order causes cryptographic failures at runtime. - Missing AsyncStorage: Without
@react-native-async-storage/async-storage, auth tokens are not persisted and users must re-authenticate on every app restart.
SvelteKit
Configure Amplify in the client hooks file:
// src/hooks.client.ts
import { Amplify } from 'aws-amplify';
import outputs from '../amplify_outputs.json';
Amplify.configure(outputs);
Note: No
@aws-amplify/ui-*components exist for Svelte. Use core APIs directly.
Unsupported Frameworks (Astro, Solid, etc.)
For frameworks without official Amplify support:
- Use
npm create amplify@latest -yto scaffold the backend (works in any project) - Configure Amplify inside a client-side component (not at build time)
Astro
Amplify is client-side only in Astro. Create a React component (no Astro syntax):
// src/components/AuthenticatedApp.tsx
import { Amplify } from 'aws-amplify';
import { Authenticator } from '@aws-amplify/ui-react';
import outputs from '../amplify_outputs.json';
Amplify.configure(outputs);
export default function AuthenticatedApp() {
return (
<Authenticator>
{({ signOut, user }) => <main>Hello {user?.username}</main>}
</Authenticator>
);
}
Use in an Astro page with client:only:
---
// src/pages/index.astro — no Amplify imports here
---
<html>
<body>
<AuthenticatedApp client:only="react" />
</body>
</html>
Must use
client:only="react"(NOTclient:load) to avoid SSR hydration errors.
Links
All documentation links use
reactas the default platform slug. Replace/react/in any URL with your target framework:
| Framework | Slug |
|---|---|
| React | react |
| Next.js | nextjs |
| Vue | vue |
| Angular | angular |
| React Native | react-native |
| Flutter | flutter |
| Swift | swift |
| Android | android |