SKILL.md
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()) with defaultAuthorizationMode: '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
Step 2: Backend Features
Read the corresponding reference for each backend feature you need:
Feature
Reference
When to Use
Authentication
Email/password, social login, MFA, SAML/OIDC
Data Models
GraphQL schema, DynamoDB, relationships, auth rules
File Storage
S3 uploads/downloads, access rules
Functions & API
Lambda, custom resolvers, REST/HTTP APIs, calling from client
AI Features
Conversation, generation, AI tools via Bedrock (backend config + React/Next.js frontend)
Geo, PubSub, CDK
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
Data CRUD & subscriptions
Storage upload/download
Mobile (Flutter, Swift, Android):
Feature
Reference
Auth UI & flows
Data CRUD & subscriptions
Storage upload/download
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 via
defineBackend()
- 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 frontend
Amplify.configure(). Gitignored — generated by npx ampx sandbox
(local dev) or npx 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 })
│ ├── 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:
amplify/directory exists withbackend.ts
@aws-amplify/backendinpackage.jsondevDependencies
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 for the correct sequence.
React (Vite) — src/main.tsx:
import { Amplify } from 'aws-amplify';
import outputs from '../amplify_outputs.json';
Amplify.configure(outputs);
Next.js (App Router) — app/layout.tsx:
Important: layout.tsx is a server component in App Router. Use the ConfigureAmplifyClientSide client 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.tsx is a server component. Client components need Amplify.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, before aws-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"** (NOT client:load) to avoid SSR hydration errors.
Links
All documentation links use react as 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