How to Build a Full Stack App with AWS Amplify and React
By Braincuber Team
Published on April 7, 2026
This complete tutorial walks you through building a production-ready full stack application from scratch using AWS Amplify and React. Whether you want to add authentication, connect a database, store files in S3, or enable user uploads, this step by step guide covers every detail. You will use AWS Amplify CLI to provision Cognito for auth, AppSync with GraphQL for your API, DynamoDB for data storage, and S3 for file management all without writing backend infrastructure code.
What You'll Learn:
- How to create a React app with AWS Amplify authentication including signup, login, and logout
- How to add a GraphQL API with DynamoDB using Amplify CLI
- How to fetch, display, and update data from your database in React components
- How to add S3 file storage and access files with expiring URLs
- How to build a media player with ReactPlayer to play audio files from S3
- How to enable user file uploads with UUID-based file naming and database record creation
Built-in Authentication
AWS Cognito provides signup, login, email verification, and signout with zero custom backend code using Amplify UI components.
GraphQL API with AppSync
Define your data schema once and Amplify generates queries, mutations, and subscriptions automatically for your React app.
S3 File Storage
Store and retrieve files with expiring access URLs. Auth-only access ensures only logged-in users can read and upload files.
User File Uploads
Enable users to upload files directly to S3 with UUID-based naming and automatic database record creation via GraphQL mutations.
Prerequisites
You need Node.js and npm installed, an AWS account with admin permissions, and the AWS CLI configured. Basic knowledge of React and JavaScript is recommended.
How to Create the App with Signup, Login, and Logout
The first step in this beginner guide is setting up a new React app and configuring AWS Amplify authentication. This gives you a complete signup, login, and logout flow without writing any authentication code yourself.
Create a New React App
Use create-react-app to scaffold a new React project. Navigate into the project directory after creation.
Install and Configure Amplify CLI
Install @aws-amplify/cli globally, then run amplify configure to create an IAM user with admin permissions in your AWS account.
Initialize Amplify in Your Project
Run amplify init to set up the Amplify backend. Give your project a name and accept the default configuration for most options.
Add Authentication with Cognito
Run amplify add auth, select default configuration, choose email as the sign-in method, then deploy with amplify push.
# Create React app
npx create-react-app amplify-react-app
cd amplify-react-app
# Install and configure Amplify CLI
npm install -g @aws-amplify/cli
amplify configure
# Initialize Amplify in project
amplify init
# Add authentication
amplify add auth
# Select: Default configuration
# Select: Email for sign-in
# Select: No, I am done
# Deploy authentication resources
amplify push
AWS Console Configuration
When running amplify configure, it opens an AWS console tab. Make sure you are logged into the correct account with a user that has admin permissions. Stay on the page showing the access key and secret key until you have copied both values into the terminal.
How to Build the React App with Authentication
Now install the Amplify npm packages and configure your React app to use the authentication that was just deployed.
npm install --save aws-amplify @aws-amplify/ui-react
Edit your src/App.js file to configure Amplify and wrap your app with the authentication higher-order component.
import Amplify from 'aws-amplify';
import awsconfig from './aws-exports';
import { AmplifySignOut, withAuthenticator } from '@aws-amplify/ui-react';
Amplify.configure(awsconfig);
function App() {
return (
My App Content
);
}
export default withAuthenticator(App);
The withAuthenticator higher-order component wraps your app and automatically provides a login screen. The AmplifySignOut component renders a sign-out button. When you run npm start, you will see a fully functional login screen without writing any authentication UI code.
To create an account, click Create Account, enter your email and password, then submit the confirmation code sent to your email. After verification, you are redirected to the app home page.
How to Add a Database to Your App
This section of the complete tutorial covers adding a GraphQL API backed by DynamoDB. Amplify generates all the queries, mutations, and subscriptions you need automatically.
Add the GraphQL API
Run amplify add api and select GraphQL as the API type, Amazon Cognito User Pool for authentication, and single object with fields for the schema type.
Define Your GraphQL Schema
When prompted to edit the schema, define your data model with the @model directive. This tells Amplify to create a DynamoDB table and CRUD operations.
Deploy and Generate Code
Run amplify push, select Yes for code generation, JavaScript as the language, and accept the default file pattern and operation generation settings.
type Song @model {
id: ID!
title: String!
description: String!
filePath: String!
likes: Int!
owner: String!
}
| CLI Option | Selection |
|---|---|
| API type | GraphQL |
| API name | songAPI |
| Authentication | Amazon Cognito User Pool |
| Schema type | Single object with fields |
| Generate code | Yes |
| Language | JavaScript |
| File pattern | src/graphql/**/*.js |
| Generate all operations | Yes |
| Max statement depth | 2 |
How to Fetch and Display Data from the Database
Rename App.js to App.jsx and add a function to fetch songs from the GraphQL API. Use useEffect with an empty dependency array to call the fetch function once on component mount.
import React, { useState, useEffect } from 'react';
import { listSongs } from './graphql/queries';
import Amplify, { API, graphqlOperation } from 'aws-amplify';
const [songs, setSongs] = useState([]);
const fetchSongs = async () => {
try {
const songData = await API.graphql(graphqlOperation(listSongs));
const songList = songData.data.listSongs.items;
console.log('song list', songList);
setSongs(songList);
} catch (error) {
console.log('error on fetching songs', error);
}
};
useEffect(() => {
fetchSongs();
}, []);
How to Add Seed Data to DynamoDB
Since the database is empty, you need to add seed data manually through the AWS Console. Navigate to the DynamoDB service, find your Song table, and create items using the text view.
{
"id": "gr4334t4tog345ht35",
"title": "My First Song",
"description": "A test song for our amplify app",
"owner": "Sam Williams",
"filePath": "",
"likes": 4,
"createdAt": "2020-08-13T07:01:39.176Z",
"updatedAt": "2020-08-13T07:01:39.176Z"
}
To generate the createdAt and updatedAt timestamps, open your browser console and type new Date().toISOString(). Copy the result into your item data.
How to Render Song Cards with Material UI
Install Material UI for styling and render each song as a card component with play, like, and description elements.
npm install --save @material-ui/core @material-ui/icons
import { Paper, IconButton } from '@material-ui/core';
import PlayArrowIcon from '@material-ui/icons/PlayArrow';
import FavoriteIcon from '@material-ui/icons/Favorite';
{songs.map((song, idx) => {
return (
{song.title}
{song.owner}
{song.likes}
{song.description}
);
})}
How to Add the Like Functionality
Add an onClick handler to the like button that increments the like count, updates the database via GraphQL mutation, and refreshes the local state.
import { updateSong } from './graphql/mutations';
const addLike = async idx => {
try {
const song = songs[idx];
song.likes = song.likes + 1;
delete song.createdAt;
delete song.updatedAt;
const songData = await API.graphql(
graphqlOperation(updateSong, { input: song })
);
const songList = [...songs];
songList[idx] = songData.data.updateSong;
setSongs(songList);
} catch (error) {
console.log('error on adding Like to song', error);
}
};
The delete song.createdAt and delete song.updatedAt lines remove fields that cannot be passed into the updateSong operation. After the database update, we clone the songs array with [...songs] to trigger a React re-render.
How to Add File Storage with S3
Now that song data is stored in DynamoDB, you need to store the actual MP3 files somewhere. This step by step guide section covers adding S3 storage through Amplify and playing files directly in your app.
How to Add Play and Pause Functionality
Add state to track which song is currently playing and toggle between play and pause icons.
import PauseIcon from '@material-ui/icons/Pause';
const [songPlaying, setSongPlaying] = useState('');
const [audioURL, setAudioURL] = useState('');
const toggleSong = async idx => {
if (songPlaying === idx) {
setSongPlaying('');
return;
}
const songFilePath = songs[idx].filePath;
try {
const fileAccessURL = await Storage.get(songFilePath, {
expires: 60
});
console.log('access url', fileAccessURL);
setSongPlaying(idx);
setAudioURL(fileAccessURL);
return;
} catch (error) {
console.error('error accessing the file from s3', error);
setAudioURL('');
setSongPlaying('');
}
};
The Storage.get() method from Amplify returns a presigned URL that expires after 60 seconds. This is a security measure preventing unauthorized sharing of file URLs.
How to Add Storage to Amplify
Run amplify add storage
Select Content (images, audio, video, etc.) as the service type, give it a friendly name and bucket name.
Configure Access Permissions
Select Auth Users Only for access, then grant Read and Create/Update permissions. Skip Lambda triggers.
Deploy the Storage Resource
Run amplify push to create the S3 bucket and configure access policies. This takes a few minutes to complete.
How to Upload Songs to S3
Navigate to the S3 service in your AWS console, find your song-storage bucket, and create a folder called public. Upload your MP3 files into this folder.
Then update your DynamoDB items to point at those files by setting the filePath field to match the filename (e.g., tomorrow.mp3, epic.mp3).
How to Add a Media Player with ReactPlayer
Install the react-player library and conditionally render an audio player when a song is playing.
npm install --save react-player
import ReactPlayer from 'react-player';
{songPlaying === idx ? (
toggleSong(idx)}
/>
) : null}
The controls prop shows volume and pause buttons. The playing prop starts playback immediately. The onPause handler syncs the built-in pause button with your app state.
How to Enable User File Uploads
The final section of this complete tutorial covers allowing users to upload their own songs. This involves creating an upload form, uploading the file to S3 with a UUID filename, and creating a database record via GraphQL mutation.
How to Build the AddSong Component
Create an AddSong component with controlled text fields for title, artist, and description, plus a file input for the MP3 upload.
import { v4 as uuid } from 'uuid';
import { createSong } from './graphql/mutations';
import { Storage, API, graphqlOperation } from 'aws-amplify';
const AddSong = ({ onUpload }) => {
const [songData, setSongData] = useState({});
const [mp3Data, setMp3Data] = useState();
const uploadSong = async () => {
const { title, description, owner } = songData;
// Upload file to S3 with UUID filename
const { key } = await Storage.put(
`${uuid()}.mp3`,
mp3Data,
{ contentType: 'audio/mp3' }
);
// Create database record
const createSongInput = {
id: uuid(),
title,
description,
owner,
filePath: key,
likes: 0,
};
await API.graphql(
graphqlOperation(createSong, { input: createSongInput })
);
onUpload();
};
return (
setSongData({ ...songData, title: e.target.value })}
/>
setSongData({ ...songData, owner: e.target.value })}
/>
setSongData({ ...songData, description: e.target.value })}
/>
setMp3Data(e.target.files[0])}
/>
);
};
The Storage.put() method uploads the file to S3 and returns a key. We use uuid() for the filename to prevent collisions. After the upload, we create a database record with createSong mutation and call onUpload() to refresh the song list and close the form.
npm install --save uuid
How to Wire the AddSong Component to the Main App
Add state to control showing the AddSong form, and call fetchSongs() after upload to refresh the data.
import AddIcon from '@material-ui/icons/Add';
const [showAddSong, setShowAddNewSong] = useState(false);
{showAddSong ? (
{
setShowAddNewSong(false);
fetchSongs();
}}
/>
) : (
setShowAddNewSong(true)}>
)}
S3 Public Folder Requirement
Amplify Storage stores files in a public/ folder by default for authenticated users. Make sure to create this folder in your S3 bucket before uploading files manually. User uploads via Storage.put() handle this automatically.
Frequently Asked Questions
How to build a full stack app with AWS Amplify and React?
Create a React app, install Amplify CLI, run amplify init, then add auth, API, and storage with amplify add commands. Deploy each resource with amplify push to provision AWS services automatically.
How does Amplify authentication work with React?
Use the withAuthenticator higher-order component to wrap your app. It provides built-in signup, login, email verification, and signout UI powered by AWS Cognito User Pools.
How to add a GraphQL API with AWS Amplify?
Run amplify add api, select GraphQL, define your schema with the @model directive, then run amplify push. Amplify generates queries, mutations, and subscriptions in the src/graphql folder.
How to upload files to S3 with AWS Amplify Storage?
Use Storage.put(filename, fileData, { contentType }) to upload files. The method returns a key you can store in your database. Use Storage.get(key) to retrieve presigned URLs with expiration.
What is the Amplify @model directive?
The @model directive tells Amplify to create a DynamoDB table for that type and generate full CRUD GraphQL operations including queries, mutations, and real-time subscriptions automatically.
Need Help with AWS Amplify?
Our experts can help you design, build, and deploy full stack applications on AWS with Amplify, AppSync, and serverless architecture.
