To configure Amplify you need to install the toolchain globally and initialize the Amplify functionality in your project folder.

Toolchain

Install the CLI toolchain:

npm install -g @aws-amplify/cli

Configure Amplify Tools

Configure Amplify:

amplify configure

Project Setup

Initialize Amplify in your project directory:

amplify init

Add Categories

Add functionality to your project:

amplify add [notifications, api, auth, custom, storage, analytics, function, geo, hosting, interactions, predictions, xr]

JS Lib + React UI

If using Amplify JS library and UI React library:

npm i @aws-amplify/ui-react aws-amplify

Add styles:

import '@aws-amplify/ui-react/styles.css';

Add fonts:

@import url('https://fonts.googleapis.com/css2?family=Inter:slnt,wght@-10..0,100..900&display=swap');

Deployment

To deploy the project run:

amplify push

AWS Amplify provides a declarative and easy-to-use authentication system that enables developers to create and manage user accounts.

Add category

Add and setup Authentication in your project:

amplify add auth

JS Lib: Sing-up, Sign-in, Sign-out

import { Auth } from 'aws-amplify';

const { user } = await Auth.signUp({
    username,
    password,
    attributes: {
        email,
    },
    autoSignIn: {
        enabled: true,
    }
});
const user = await Auth.signIn(username, password);
await Auth.signOut();

React Lib: Sing-up, Sign-in, Sign-out

import { Amplify } from 'aws-amplify';

import { Authenticator } from '@aws-amplify/ui-react';
import awsExports from './aws-exports';
Amplify.configure(awsExports);

<Authenticator>
  {({ signOut, user }) => (
    <main>
      <h1>Logged in as: {user.username}</h1>
      <button onClick={signOut}>Log out</button>
    </main>
  )}
</Authenticator>

Amplify UI library consists of connected components that simplify complex workflows like authentication and dynamic data, primitive components that form the building blocks of a UI, and themes to make Amplify UI fit any brand.

Cloud Connected Componenets

Auth Hook:

import { Amplify } from 'aws-amplify';
import awsExports from './aws-exports';
import { withAuthenticator } from '@aws-amplify/ui-react';

Amplify.configure(awsExports);

function App({ signOut, user }) {
  return (
    <>
      <h1>Hello {user.username}</h1>
      <button onClick={signOut}>Sign out</button>
    </>
  );
}

export default withAuthenticator(App);

File Uploader:

import { FileUploader } from '@aws-amplify/ui-react';

<FileUploader
  acceptedFileTypes={['image/*']}
  accessLevel="public"
/>

Account Settings component:

import { AccountSettings } from '@aws-amplify/ui-react';

<AccountSettings.ChangePassword onSuccess={handleSuccess}/>
<AccountSettings.DeleteUser onSuccess={handleSuccess} />

In App Messaging:

import { Amplify, Notifications } from 'aws-amplify';
import {
  Text,
  InAppMessagingProvider,
  InAppMessageDisplay,
} from '@aws-amplify/ui-react';
const { InAppMessaging } = Notifications;

function App() {
  useEffect(() => {
    InAppMessaging.syncMessages();
  }, []);

  return (
    <InAppMessagingProvider>
      <InAppMessageDisplay />
      <Text>In-App Messaging Example</Text>
    </InAppMessagingProvider>
  );
}

Map:

import { MapView } from '@aws-amplify/ui-react';

<MapView />

Components

Flexbox:

<Flex
  direction="row"
  justifyContent="flex-start"
  alignItems="stretch"
  alignContent="flex-start"
  wrap="nowrap"
  gap="1rem"
>
...
</Flex>

Text:

<Text
    variation="primary"
    as="p"
    color="blue"
    lineHeight="1.5em"
    fontWeight={400}
    fontSize="1em"
    fontStyle="normal"
    textDecoration="none"
    width="30vw"
  >
    Hello World!
</Text>

Button:

<Button
  variation="primary"
  loadingText=""
  onClick={() => alert('hello')}
  ariaLabel=""
>
  Click me!
</Button>

Textfield:

<TextField
  descriptiveText="Enter a valid last name"
  label="Last name"
  errorMessage="There is an error"
/>

Theming

Wrap your app in ThemeProvider element:

import { ThemeProvider } from '@aws-amplify/ui-react';
//optionally define a custom theme
const customTheme = {...};
const App = (
  <ThemeProvider theme={customTheme}>
    <MyApp>/* AmplifyUI */</MyApp>
  </ThemeProvider>
);

Override default theme values:

import { ThemeProvider, defaultTheme } from '@aws-amplify/ui-react';

const customTheme = {
  name: 'my-theme',
  overrides: [
    {
      colorMode: 'light',
      tokens: {
        colors: {
          neutral: {
            10: { value: defaultTheme.tokens.colors.neutral[100].value }
          },
        },
      },
    }
  ],
};
const App = (
  <ThemeProvider theme={customTheme}>
    <MyApp>AmplifyUI</MyApp>
  </ThemeProvider>
);

CSS Overrides:

/* single element style */
.amplify-alert {
  border-radius: 100px;
}
/* global styles */
:root, [data-amplify-theme] {
  --amplify-primary-color: #333;
}

Responsive design:

<View
  color={{
    base: 'black',
    small: 'black',
    medium: 'black',
    large: 'white',
    xl: 'white',
    xxl: 'white',
  }}
>
  Hello
</View>

Breakpoint hook:

import { Alert, useBreakpointValue } from '@aws-amplify/ui-react';

const variation = useBreakpointValue({
  base: 'info',
  small: 'warning',
  medium: 'error',
  large: 'success',
});

<Alert variation={variation}>Responsive Alert</Alert>;

Figma-to-Code

  1. Duplicate the official Figma file. Or optionally use a professional template.

  2. Link Figma file in Amplify Studio

  3. Add and configure the Amplify UI library in your project

  4. Import components into your project:

    amplify pull
    

The API service category allows developers to quickly create an API with a GraphQL schema, as well as configure authorization and access control.

Add category

amplify add api

Select GraphQL as the service type.

Model Relationships

Has One

type Project @model {
  id: ID!
  name: String
  team: Team @hasOne
}

type Team @model {
  id: ID!
  name: String!
}

Has Many

type Post @model {
  id: ID!
  title: String!
  comments: [Comment] @hasMany
}

type Comment @model {
  id: ID!
  content: String!
}

Belongs To

type Post @model {
  id: ID!
  title: String!
  comments: [Comment] @hasMany
}

type Comment @model {
  id: ID!
  content: String!
  post: Post @belongsTo
}

Many To Many

type Post @model {
  id: ID!
  title: String!
  content: String
  tags: [Tag] @manyToMany(relationName: "PostTags")
}

type Tag @model {
  id: ID!
  label: String!
  posts: [Post] @manyToMany(relationName: "PostTags")
}

Authorization

Public authorization grants unauthenticated users or devices access protected by API key.

type Todo @model @auth(rules: [{ allow: public }]) {
  content: String
}

Owner authorization grants Cognito user access to specific CRUD permissions.

type Todo @model @auth(rules: [{ allow: owner, operations: [create, read, update] }]) {
  content: String
}

Multi-User authorization grants multiple Cognito users access to specific CRUD permissions.

type Todo @model @auth(rules: [{ allow: owner, ownerField: "authors" }]) {
  content: String
  authors: [String]
}

Signed-in data access grants ANY signed-in user specific CRUD permissions.

type Todo @model @auth(rules: [{ allow: private }]) {
  content: String
}

Queries and Mutations

Create an Item

import { API } from "aws-amplify";
import * as mutations from './graphql/mutations';

const todoDetails = {
  name: 'Todo 1',
  description: 'Learn AWS AppSync'
};

const newTodo = await API.graphql({ query: mutations.createTodo, variables: {input: todoDetails}});

Read Items

import { API } from 'aws-amplify';
import * as queries from './graphql/queries';

const allTodos = await API.graphql({ query: queries.listTodos });
console.log(allTodos);

const oneTodo = await API.graphql({
  query: queries.getTodo,
  variables: { id: 'some id' }
});

Update an Item

import { API } from "aws-amplify";
import * as mutations from './graphql/mutations';

const todoDetails = {
  id: 'some_id',
  description: 'My updated description!'
};

const updatedTodo = await API.graphql({ query: mutations.updateTodo, variables: {input: todoDetails}});

Delete an Item

import { API } from "aws-amplify";
import * as mutations from './graphql/mutations';

const todoDetails = {
  id: 'some_id',
};

const deletedTodo = await API.graphql({ query: mutations.deleteTodo, variables: {input: todoDetails}});

Custom authorization

const todos = await API.graphql({
  query: queries.listTodos,
  authMode: 'AWS_IAM' | 'API_KEY' | 'AMAZON_COGNITO_USER_POOLS'
});

AWS Amplify provides a DataStore service to easily create and manage a backend database. The service allows developers to quickly create a database with offline and online synchronization capabilities.

Setup API

Set conflict detection as required if you have not done so:

amplify update api

Select the default resolution strategy -> Auto Merge

CRUD operations

Create:

import { DataStore } from 'aws-amplify';

await DataStore.save(
  new Post({
    title: 'My First Post',
    rating: 10,
    status: PostStatus.INACTIVE
  })
);

Read:

// find by ID
const post = await DataStore.query(Post, "1234567");
// find by predicate
const posts = await DataStore.query(
  Post,
  (c) => c.and((c) => [
      c.rating.gt(4), 
      c.status.eq(PostStatus.ACTIVE)
  ]),
  {
    sort: (s) => s.rating(SortDirection.ASCENDING),
    page: 0,
    limit: 100,
  }
);

Update:

const original = await DataStore.query(Post, id);
await DataStore.save(
  Post.copyOf(original, updated => {
    updated.title = newTitle
  })
);

Delete:

const original = await DataStore.query(Post, id);
DataStore.delete(original);

Real-time subscriptions

Observe single item:

const subscription = DataStore.observe(Post, id).subscribe(msg => {
  console.log(msg.model, msg.opType, msg.element);
});

// Call unsubscribe to close the subscription
subscription.unsubscribe();

Observe collection:

const subscription = DataStore.observeQuery(
  Post,
  p => p.and(p => [
    p.title.beginsWith("post"),
    p.rating.gt(10)
  ]), {
    sort: s => s.rating(SortDirection.ASCENDING)
  }
).subscribe(snapshot => {
  const { items, isSynced } = snapshot;
  console.log(`[Snapshot] item count: ${items.length}, isSynced: ${isSynced}`);
});

The storage service allows developers to store and retrieve data from Amazon S3 and Amazon DynamoDB, as well as other cloud-based services. The Amplify Storage module provides APIs to read, write, and list files, as well as metadata information.

Add category

amplify add storage

For S3 bucket setup select Content.

Uploads and Downloads

Upload:

async function onChange(e) {
  const file = e.target.files[0];
  try {
    await Storage.put(file.name, file, {
      contentType: "image/png",
      level: "private" | "protected" | "public"
    });
  } catch (error) {
    console.log("Error uploading file: ", error);
  }
}

<input type="file" onChange={onChange} />;

Download link:

const signedURL = await Storage.get(key, {
  level: "private" | "protected" | "public"
}); 

<a href={signedURL} target="_blank" rel='noreferrer'>{fileName}</a>

Download blob:

const result = await Storage.get('filename.txt', {
    download: true
  });

result.Body.text().then(string => { 
  // handle the String data return String 
});

The API service allows developers to quickly create an API with REST endpoints, as well as configure authorization and access control.

Add category

amplify add api

Select REST as the service type.

GET and POST

GET Data:

import { API } from "aws-amplify";

API.get("MyApiName", path, {
  headers:{},
  queryStringParameters:{}
})
  .then((response) => {
    // Add your code here
  })
  .catch((error) => {
    console.log(error.response);
  });

POST Data:

import { API } from "aws-amplify";

API.post("MyApiName", path, {
  headers:{},
  body:{}
})
  .then((response) => {
    // Add your code here
  })
  .catch((error) => {
    console.log(error.response);
  });