| Key | Value |
|---|---|
| Environment | LocalStack, AWS |
| Services | Cognito, AppSync, DynamoDB, CloudFormation, S3, Lambda, SSM, IAM |
| Integrations | AWS Amplify Gen 2 (ampx), AWS CDK, AWS SDK for JavaScript, lstk |
| Categories | Serverless, GraphQL, Full-stack web |
| Level | Beginner |
| Use Case | Local development of Amplify Gen 2 apps, Sandbox dev loop |
| GitHub | Repository link |
This sample deploys an AWS Amplify Gen 2 application to LocalStack instead of an AWS account. The backend is the stock create-amplify template: a Cognito user pool and identity pool from defineAuth, and a Todo model from defineData that becomes an AppSync GraphQL API backed by a DynamoDB table. Guests (visitors who have not signed in) get temporary credentials from the identity pool and can create, read, update and delete todos. The frontend is a small React + Vite app that lists, adds, edits and deletes todos and shows which endpoints it is talking to.
The point of the sample is the workflow. npx ampx sandbox, the Amplify Gen 2 developer sandbox, deploys the backend through CloudFormation to LocalStack, writes amplify_outputs.json with the local endpoints, and redeploys on every change under amplify/. The same code runs against AWS: deploy an AWS sandbox and start the frontend without the LocalStack mode.
The following diagram shows the architecture that this sample application builds and deploys:
- Cognito user pool and identity pool for authentication. The app uses the identity pool's guest access to sign requests.
- AppSync GraphQL API with the generated
createTodo,getTodo,listTodos,updateTodoanddeleteTodooperations and their resolvers. - DynamoDB table for the
Todomodel, created by Amplify's table manager, a Lambda function deployed as a CloudFormation custom resource. - CloudFormation root stack with nested stacks for the auth and data categories, deployed by the CDK toolkit embedded in
ampx. - S3 bucket from the CDK bootstrap for templates and assets, and SSM parameters for Amplify's bookkeeping.
- A valid LocalStack for AWS license. Your license provides a
LOCALSTACK_AUTH_TOKENto activate LocalStack. Cognito and AppSync require a licensed plan. lstkCLI 1.0 or later.- Docker.
- Node.js 22.12 or later. The frontend uses Vite 8, which needs it.
- The AWS CDK CLI (
npm install -g aws-cdk), whichlstk cdkwraps. makefor running the sample application via the provided Makefile.
To run the sample application, you need to install the required dependencies.
First, clone the repository:
git clone https://github.com/localstack-samples/sample-amplify-gen2-todo-app.gitThen, navigate to the project directory:
cd sample-amplify-gen2-todo-appInstall the dependencies:
make installStart LocalStack. The Makefile passes two settings: LOCALSTACK_EXTRA_CORS_ALLOWED_ORIGINS=http://localhost:5173 so the browser can call Cognito and AppSync from the Vite dev server's origin, and LOCALSTACK_LAMBDA_IGNORE_ARCHITECTURE=1 because Amplify pins one of its CloudFormation helper functions to arm64, which this setting runs natively on x86_64 hosts as well:
export LOCALSTACK_AUTH_TOKEN=<your-auth-token>
make startampx deploys with an AWS profile. Write the localstack profile once:
make setupDeploy the backend. This bootstraps the CDK toolkit stack in LocalStack and runs npx ampx sandbox --once --identifier local --profile localstack:
make deployThe output ends with the local AppSync endpoint and the generated outputs file:
✔ Deployment completed in 55.307 seconds
AppSync API endpoint = http://localhost.localstack.cloud:4566/graphql/4f77b9c21fa740f885cfdc9594
File written: amplify_outputs.jsonRun the frontend against LocalStack:
make runOpen http://localhost:5173 and add a few todos. The panel on the right shows the AppSync host, the identity pool and the guest identity Cognito issued to your browser session.
Run the end-to-end test against the deployed backend. It obtains guest credentials from the identity pool and runs the Todo operations through AppSync with the Amplify data client, the same way the frontend does:
make test data.url = http://localhost.localstack.cloud:4566/graphql/4f77b9c21fa740f885cfdc9594
identity pool = us-east-1:7fd216cc
guest identity = us-east-1:5b1c2d3e
PASS guest credentials issued
PASS createTodo returns id and content
PASS getTodo reads the item back
PASS listTodos contains the item
PASS updateTodo returns the new content
PASS listTodos filter matches the new content
PASS updateTodo on a missing id fails
PASS deleteTodo returns the id
PASS getTodo after delete returns null
All checks passedThe GitHub Actions workflow runs the same deployment and test on every push.
ampx sandbox is Amplify's per-developer dev loop: it synthesizes the backend with CDK, deploys it through CloudFormation, and redeploys on every file save. Everything ampx does goes through the AWS SDK for JavaScript v3, which resolves endpoints from the AWS profile, so --profile localstack is all it takes to deploy to LocalStack. make sandbox runs it in watch mode; edit amplify/data/resource.ts (for example, add isDone: a.boolean() to the Todo model) and the change is hotswapped into the running AppSync API in a few seconds.
Two details make the flow work:
- The CDK toolkit uploads assets with the bucket name in the hostname. LocalStack recognises those requests as S3 on
s3.localhost.localstack.cloud, so the Makefile setsAWS_ENDPOINT_URL_S3=http://s3.localhost.localstack.cloud:4566forampx. - LocalStack starts from a clean state, while the CDK toolkit keeps a hotswap cache under
.amplify/.scripts/reset-cdk-cache.mjsdrops that cache before a deploy, so a restarted LocalStack always gets a full deployment.
amplify_outputs.json carries the AppSync URL, so the data layer needs nothing extra. Cognito endpoints are derived from the Region inside the Amplify library and have no field in the outputs file, so src/amplify-config.ts adds userPoolEndpoint and identityPoolEndpoint when VITE_LOCALSTACK_ENDPOINT is set. make run starts Vite in the localstack mode, which loads .env.localstack; plain npm run dev leaves the endpoints alone and the app talks to AWS.
lstk status # every resource ampx created
lstk aws cloudformation list-stacks --query 'StackSummaries[].StackName'
lstk aws appsync list-graphql-apis
lstk aws dynamodb scan --table-name <Todo-...> # the todos, with createdAt/updatedAt/__typename
lstk logs --follow # requests as you click aroundThe LocalStack Web App shows the same resources in its Resource Browser.
Delete the sandbox stack and stop LocalStack:
make destroy
make stopThis sample demonstrates how to:
- Deploy an Amplify Gen 2 backend (Cognito, AppSync, DynamoDB) to LocalStack with the standard
ampx sandboxcommand and an AWS profile. - Run the Amplify sandbox dev loop, including hotswapped schema changes, against a local container.
- Point the
aws-amplifyclient library at LocalStack with a single override for the Cognito endpoints. - Test the deployed API end to end with guest credentials, locally and in CI.
- Amplify Gen 2 documentation
- LocalStack Cognito, AppSync and DynamoDB documentation
lstkCLI
We appreciate your interest in contributing to our project and are always looking for new ways to improve the developer experience. We welcome feedback, bug reports, and even feature ideas from the community. Please refer to the contributing file for more details on how to get started.
This project is licensed under the Apache License 2.0. See the LICENSE file for details.

