<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: gerard-sans</title>
    <description>The latest articles on DEV Community by gerard-sans (@gerardsans).</description>
    <link>https://dev.to/gerardsans</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F149957%2F8c5a18de-f478-4298-adfe-7a31512ecadf.jpg</url>
      <title>DEV Community: gerard-sans</title>
      <link>https://dev.to/gerardsans</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gerardsans"/>
    <language>en</language>
    <item>
      <title>Offline-first made easy with GraphQL, Amplify DataStore and Vue</title>
      <dc:creator>gerard-sans</dc:creator>
      <pubDate>Thu, 01 Oct 2020 11:10:08 +0000</pubDate>
      <link>https://dev.to/aws/offline-first-made-easy-with-graphql-amplify-datastore-and-vue-3cok</link>
      <guid>https://dev.to/aws/offline-first-made-easy-with-graphql-amplify-datastore-and-vue-3cok</guid>
      <description>&lt;p&gt;Create a PWA cloud-enabled offline-first chatroom using Vue&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8p5vwdneli9dzi1asapf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8p5vwdneli9dzi1asapf.png" alt="Image for post" width="800" height="642"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article, you will create Chatty, a chatroom Progressive Web App (PWA) that stores data on the device while offline, and synchronises in real-time with other devices when online using Amplify DataStore, GraphQL and Amazon DynamoDB. We will cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Introduction to &lt;strong&gt;Offline-first&lt;/strong&gt;, &lt;strong&gt;PWAs&lt;/strong&gt; and &lt;strong&gt;Amplify DataStore&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Setting up a new project with the &lt;strong&gt;Vue CLI&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Creating a new &lt;strong&gt;GraphQL API&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Amplify DataStore&lt;/strong&gt;: setup, data models and usage&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Creating the UI with Vue&lt;/strong&gt;: the chatroom, sending and deleting messages; and doing real-time with subscriptions&lt;/li&gt;
&lt;li&gt;  Making Chatty a &lt;strong&gt;PWA&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Adding a &lt;strong&gt;PWA custom configuration&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Improving UX&lt;/strong&gt; while offline&lt;/li&gt;
&lt;li&gt;  Publishing your app via the &lt;strong&gt;AWS Amplify Console&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Installing Chatty in the &lt;strong&gt;Desktop and Mobile&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Cleaning up &lt;strong&gt;cloud services&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;In order to follow this post you will need a basic knowledge of GraphQL. You can learn the basics following this tutorial at&lt;/em&gt; &lt;a href="https://graphql.org/learn/" rel="noopener noreferrer"&gt;&lt;em&gt;graphql.org&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. We will be referring to GraphQL schema, directives, types, queries, mutations, subscriptions and resolvers.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Please let me know if you have any questions or want to learn more at &lt;a href="https://twitter.com/intent/user?screen_name=gerardsans" rel="noopener noreferrer"&gt;@gerardsans&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&amp;gt; &lt;a href="https://github.com/gsans/amplify-datastore-chatty-pwa-vue" rel="noopener noreferrer"&gt;Final solution&lt;/a&gt; and step by step tutorial in &lt;a href="https://github.com/gsans/amplify-datastore-chatty-vue" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction to Offline-first, PWAs and Amplify DataStore
&lt;/h1&gt;

&lt;p&gt;Offline-first is an approach to software development, where an application is built to function, with or without an internet connection. Using this approach, data is stored locally on the user’s device and periodically uploaded and replicated into the cloud. Features include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Offline ready&lt;/strong&gt;: application works offline. This usually comes with some limitations regarding feature set and device capabilities. Eg: PWAs require an install step where the user needs to be online to download all the necessary application assets.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Great user experience&lt;/strong&gt;: application loads fast and transitions seamlessly from online to offline improving user retention. The user is in control regarding app updates, data synchronisation, data conflict resolution and connectivity. Eg: App shell; user is informed about connectivity changes.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Native-like features&lt;/strong&gt;: application behaves similar to a native app. Eg: PWAs are able to run on multiple operating systems as standalone applications and don’t require the user to interact with the browser.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Reliable storage&lt;/strong&gt;: user can exit the application at any moment without losing data. Application stores user data securely on-device and synchronises with the cloud transparently when possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Progressive Web Apps
&lt;/h2&gt;

&lt;p&gt;Progressive Web Apps combine the benefits from native apps, while being able to run on more platforms, leveraging browser technologies. PWA features allow Web apps to close the gap with native applications while creating similar user experiences. PWA features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Works &lt;strong&gt;offline&lt;/strong&gt; via service worker.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Great&lt;/strong&gt; &lt;strong&gt;performance&lt;/strong&gt; via app shell and pre-cached assets.&lt;/li&gt;
&lt;li&gt;  Access to &lt;strong&gt;device APIs&lt;/strong&gt; via &lt;a href="https://whatwebcando.today/" rel="noopener noreferrer"&gt;Web APIs&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;  Supports &lt;strong&gt;push notifications&lt;/strong&gt; via service worker.&lt;/li&gt;
&lt;li&gt;  Works in &lt;strong&gt;Web, Mobile and Desktop&lt;/strong&gt; via Web app manifest.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most important requirements for PWA are: security, must be served via HTTPS, the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers" rel="noopener noreferrer"&gt;service worker&lt;/a&gt; and the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Manifest" rel="noopener noreferrer"&gt;Web app manifest&lt;/a&gt;. We will incorporate all of these to Chatty.&lt;/p&gt;

&lt;h2&gt;
  
  
  Amplify DataStore
&lt;/h2&gt;

&lt;p&gt;Amplify DataStore, is an on device persistent repository for interacting with local data, and able to automatically synchronise via GraphQL. Using Amplify DataStore, you can provide a &lt;strong&gt;great offline-first experience&lt;/strong&gt; for your users, while using a &lt;strong&gt;simple programming model&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;GraphQL knowledge is beneficial when using Amplify DataStore to understand its inner workings but not necessary to use DataStore APIs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Amplify takes care of all the heavy lifting regarding hosting your data source in the cloud using &lt;strong&gt;Amazon DynamoDB&lt;/strong&gt;; and scaling real-time messaging, synchronising data and running conflict resolution with &lt;strong&gt;AWS AppSync&lt;/strong&gt; and &lt;strong&gt;GraphQL.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Amplify DataStore uses your &lt;strong&gt;GraphQL schema&lt;/strong&gt; to generate data models. These will help keep your client code consistent with the type and fields defined in your GraphQL schema; and reduce type checks and data related run-time errors while enforcing &lt;strong&gt;GraphQL type safety&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Amplify DataStore behaves differently when in offline or online modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;In offline mode,&lt;/strong&gt; we use the &lt;strong&gt;DataStore API&lt;/strong&gt; to manage the data on the device via the &lt;strong&gt;Storage Engine&lt;/strong&gt; using GraphQL. The local &lt;strong&gt;Data Store&lt;/strong&gt; being used will vary depending on the user device. This can either be IndexedDB in the browser or SQL Lite in Android and iOS.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ficgrqb6ys4llnsvb8x70.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ficgrqb6ys4llnsvb8x70.png" alt="Image for post" width="800" height="193"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Amplify DataStore data flow in offline mode&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;In online mode,&lt;/strong&gt; Amplify DataStore, will synchronise with the cloud using the &lt;strong&gt;Sync Engine&lt;/strong&gt; via GraphQL to automatically synchronise with your GraphQL API. At the query level, this is implemented as an &lt;strong&gt;AWS AppSync resolver&lt;/strong&gt; accessing &lt;strong&gt;Amazon DynamoDB&lt;/strong&gt;, &lt;strong&gt;AWS Lambda&lt;/strong&gt; or &lt;strong&gt;Amazon ElasticSearch&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvvgck1m69zp6ih2v2n2y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvvgck1m69zp6ih2v2n2y.png" alt="Image for post" width="800" height="329"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Amplify DataStore data flow in online mode&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Amplify DataStore supports the following conflict resolution modes during synchronisation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Optimistic concurrency&lt;/strong&gt;, this mode rejects any incoming changes if there’s a mismatch in the tracking version between the incoming change and the item being changed. A further step on the client is required to resolve the conflict.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Auto merge&lt;/strong&gt; (default), this mode doesn’t require further steps to resolve conflicts. It accommodates mutations on a field-by-field basis as long as scalar types don’t clash. If they do, they are ignored but all other fields are merged, if possible.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Custom&lt;/strong&gt;, this mode uses AWS Lambda to allow more control and complex use cases.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more details read &lt;a href="https://docs.aws.amazon.com/appsync/latest/devguide/conflict-detection-and-sync.html" rel="noopener noreferrer"&gt;conflict detection and sync&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  Setting up a new project with the Vue CLI
&lt;/h1&gt;

&lt;p&gt;Before moving to the next section, please complete the steps described in “&lt;a href="///@gerard.sans/build-your-first-full-stack-serverless-app-with-vue-and-aws-amplify-9ed7ef9e9926"&gt;Build your first full-stack serverless app with Vue&lt;/a&gt;”. Here you will set up the initial project, familiarise with &lt;strong&gt;Amplify CLI&lt;/strong&gt; and add an authorisation flow so users can register themselves via an automated verification code sent to their email and login.&lt;/p&gt;
&lt;h1&gt;
  
  
  Creating a new GraphQL API
&lt;/h1&gt;

&lt;p&gt;First, we are going to create the GraphQL API to service &lt;strong&gt;Chatty&lt;/strong&gt; chatroom. To create it, we will use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify add api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Answer the following questions&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Please select from one of the below mentioned services &lt;strong&gt;GraphQL&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Provide API name: &lt;strong&gt;ChattyAPI&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Choose the default authorization type for the API &lt;strong&gt;API key&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Enter a description for the API key: &lt;strong&gt;(empty)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  After how many days from now the API key should expire (1–365): &lt;strong&gt;7&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;It’s important that you don’t miss the following steps to set up conflict detection. If you missed it, you can recover with &lt;code&gt;amplify api update&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;  Do you want to configure advanced settings for the GraphQL API &lt;strong&gt;Yes, I want to make some additional changes.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Configure additional auth types? &lt;strong&gt;No&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Configure conflict detection? &lt;strong&gt;Yes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Select the default resolution strategy &lt;strong&gt;Auto Merge&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Do you want to override default per model settings? &lt;strong&gt;No&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Do you have an annotated GraphQL schema? &lt;strong&gt;No&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Choose a schema template: &lt;strong&gt;Single object with fields (e.g., “Todo” with ID, name, description)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Do you want to edit the schema now? &lt;strong&gt;Yes&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When prompted, replace the default schema with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Chatty&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;model&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;  
  &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;  
  &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;  
  &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AWSDateTime&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By adding &lt;code&gt;@model&lt;/code&gt; to the &lt;code&gt;Chatty&lt;/code&gt; type we are telling the &lt;strong&gt;Amplify CLI&lt;/strong&gt; to create the resolvers to support queries, mutations and subscriptions in &lt;strong&gt;Amazon DynamoDB&lt;/strong&gt;. Besides the regular &lt;strong&gt;CRUD operations&lt;/strong&gt;, we are also getting some more advanced features like pagination, filtering and real-time synchronisation that we are going to use later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pushing your GraphQL API to the cloud
&lt;/h2&gt;

&lt;p&gt;Let’s run the push command to create the GraphQL API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  Are you sure you want to continue? &lt;strong&gt;Yes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Do you want to generate code for your newly created GraphQL API &lt;strong&gt;Yes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Choose the code generation language target &lt;strong&gt;javascript&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Enter the file name pattern of graphql queries, mutations and subscriptions &lt;strong&gt;src/graphql/**/*.js&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Do you want to generate/update all possible GraphQL operations — queries, mutations and subscriptions &lt;strong&gt;Yes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Enter maximum statement depth [increase from default if your schema is deeply nested] &lt;strong&gt;2&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Write down your &lt;strong&gt;GraphQL endpoint&lt;/strong&gt; and &lt;strong&gt;API KEY&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is the resulting architecture with our new GraphQL API managed by &lt;strong&gt;AWS AppSync&lt;/strong&gt; and &lt;strong&gt;Amazon DynamoDB&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg88ai7tibycevxu9mgus.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg88ai7tibycevxu9mgus.png" alt="Image for post" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run the command below to access the &lt;strong&gt;AWS AppSync console&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify console api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  Please select from one of the below mentioned services &lt;strong&gt;GraphQL&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Amplify DataStore setup
&lt;/h1&gt;

&lt;p&gt;Run the command below to install the necessary dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install --save @aws-amplify/core @aws-amplify/datastore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Data model generation
&lt;/h2&gt;

&lt;p&gt;Generate the data models to manage our messages for our &lt;strong&gt;ChattyAPI&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify codegen models
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Important: DO NOT forget to regenerate your models every time you introduce a change in your schema.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After running this command, &lt;strong&gt;AWS Amplify CLI&lt;/strong&gt; has generated the necessary data models in a new folder. The files in this folder hold your data model classes and schema.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;amplify-app&amp;gt;  
    |\_ src  
      |\_ models
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating a message
&lt;/h2&gt;

&lt;p&gt;Now that the GraphQL API and &lt;strong&gt;data models&lt;/strong&gt; are created, we can begin using the &lt;strong&gt;DataStore API&lt;/strong&gt;. The first thing we’ll do is create a new message passing the generated &lt;strong&gt;data model&lt;/strong&gt; to &lt;code&gt;save&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Using data models allow us to be always compliant with the GraphQL schema and prevent errors right in the client.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DataStore&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@aws-amplify/datastore&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Chatty&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./models&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;DataStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Chatty&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
  &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;amplify-user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hi everyone!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
&lt;span class="p"&gt;}))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a record locally in your device and synchronise it in the background using the underlying &lt;strong&gt;GraphQL API&lt;/strong&gt; when in online mode.&lt;/p&gt;

&lt;h2&gt;
  
  
  Querying data
&lt;/h2&gt;

&lt;p&gt;Let’s see how we can query the data using Amplify DataStore. In order to query our &lt;strong&gt;data model&lt;/strong&gt; we will use a query and a predicate to indicate that we want all records.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DataStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Predicates&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@aws-amplify/datastore&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Chatty&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./models&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;DataStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Chatty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Predicates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ALL&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return an array of messages that we can display in our UI. &lt;strong&gt;Predicates&lt;/strong&gt; also support filters for common types like &lt;code&gt;Strings&lt;/code&gt;, &lt;code&gt;Numbers&lt;/code&gt; and &lt;code&gt;Lists&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Find all supported filters at&lt;/em&gt; &lt;a href="https://aws-amplify.github.io/docs/js/datastore#query-with-predicates" rel="noopener noreferrer"&gt;&lt;em&gt;query with Predicates&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Creating the UI with Vue
&lt;/h1&gt;

&lt;p&gt;Now, let’s look at how we can create the UI to create and display messages for Chatty chatroom.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message of sorted&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message.id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nf"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YYYY-MM-DD HH:mm:ss&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}})&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;DataStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Predicates&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@aws-amplify/datastore&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Chatty&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./models&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;moment&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;moment&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;  
      &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="p"&gt;},&lt;/span&gt;  
  &lt;span class="na"&gt;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nf"&gt;sorted&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;localeCompare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="p"&gt;},&lt;/span&gt;  
  &lt;span class="nf"&gt;created&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="c1"&gt;// authentication state managament  &lt;/span&gt;
    &lt;span class="nf"&gt;onAuthUIStateChange&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="c1"&gt;// set current user and load data after login  &lt;/span&gt;
      &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="nx"&gt;AuthState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SignedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadMessages&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
          &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
        &lt;span class="p"&gt;}&lt;/span&gt;  
      &lt;span class="p"&gt;}&lt;/span&gt;  
    &lt;span class="p"&gt;});&lt;/span&gt;  
  &lt;span class="p"&gt;},&lt;/span&gt;  
  &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;moment&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;  
    &lt;span class="nf"&gt;loadMessages&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nx"&gt;DataStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Chatty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Predicates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ALL&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
      &lt;span class="p"&gt;});&lt;/span&gt;  
    &lt;span class="p"&gt;},&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the user signs in, we call &lt;code&gt;loadMessages&lt;/code&gt;. This fetches all the messages in our local store. We are sorting the list with a computed method &lt;code&gt;sorted&lt;/code&gt; as we want our messages to show the most recent at the top. We are also using &lt;code&gt;moment&lt;/code&gt; to format our time variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a message
&lt;/h2&gt;

&lt;p&gt;Now, let’s look at how we create new messages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prevent&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;form.message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Enter your message...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;  
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;click&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sendMessage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Send&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/form&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="na"&gt;form&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;  
    &lt;span class="p"&gt;};&lt;/span&gt;  
  &lt;span class="p"&gt;},&lt;/span&gt;   
  &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nf"&gt;sendMessage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt;  
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
      &lt;span class="nx"&gt;DataStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Chatty&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
        &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
        &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
      &lt;span class="p"&gt;})).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;  
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadMessages&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
      &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error creating message...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
      &lt;span class="p"&gt;});&lt;/span&gt;  
    &lt;span class="p"&gt;},&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use a form to read the message from the user and call &lt;code&gt;sendMessage&lt;/code&gt; with &lt;code&gt;save&lt;/code&gt; passing the user and current date along with the message. Once the message has been created we reset the input field and reload all messages. Note how we use Amplify DataStore as our source of truth in this implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deleting all messages
&lt;/h2&gt;

&lt;p&gt;One of the main advantages of working using Amplify DataStore is being able to run a series of GraphQL mutations without having to use a series of individual operations. See below how we can use delete together with a predicate to remove all messages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;DataStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Chatty&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Predicates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ALL&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;messages deleted!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;When using Amplify DataStore records are never removed, but marked for removal. Records will then be automatically removed as defined in their &lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/TTL.html" rel="noopener noreferrer"&gt;TTL&lt;/a&gt; attribute. At the time of writing, this is set to 30 days.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Real-time with GraphQL subscriptions
&lt;/h2&gt;

&lt;p&gt;Next, let’s see how we can create a GraphQL subscription. To do so, we will listen for changes of data in our API, and update the state whenever a new piece of data comes through. When the component is destroyed, we will &lt;code&gt;unsubscribe&lt;/code&gt; to avoid memory leaks.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As we are using Amplify DataStore, as our source of truth, we don’t need another copy of it at the app level so we just need to load the latest state with &lt;code&gt;loadMessages&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="na"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="p"&gt;};&lt;/span&gt;  
  &lt;span class="p"&gt;},&lt;/span&gt;  
  &lt;span class="nf"&gt;created&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="c1"&gt;//Subscribe to changes  &lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscription&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DataStore&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Chatty&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;opType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loadMessages&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
    &lt;span class="p"&gt;});&lt;/span&gt;  
  &lt;span class="p"&gt;},&lt;/span&gt;   
  &lt;span class="nf"&gt;destroyed&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subscription&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unsubscribe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  
  &lt;span class="p"&gt;},&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, the chatroom is fully working including authentication flow and data synchronisation in real-time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb734zj1l05ougjsj9hkm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb734zj1l05ougjsj9hkm.png" alt="Image for post" width="800" height="457"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Real-time synchronisation using Chrome and Firefox clients side-by-side.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On the other hand, we haven’t made much progress in making it work offline or having native-like features. In order to tick these boxes, we are going to make our app a &lt;strong&gt;PWA&lt;/strong&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  Making Chatty a PWA
&lt;/h1&gt;

&lt;p&gt;The &lt;a href="https://cli.vuejs.org/core-plugins/pwa.html#vue-cli-plugin-pwa" rel="noopener noreferrer"&gt;PWA CLI plugin&lt;/a&gt; can help us making Chatty a PWA by running a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vue add @vue/pwa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will make few changes to the project and add a few new assets necessary to run the app as a PWA. The most important change happens in &lt;code&gt;src/main.js&lt;/code&gt; where we are now registering a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers" rel="noopener noreferrer"&gt;&lt;strong&gt;service worker&lt;/strong&gt;&lt;/a&gt; that will allow Chatty to work offline.&lt;/p&gt;

&lt;p&gt;Using the default settings, the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers" rel="noopener noreferrer"&gt;&lt;strong&gt;service worker&lt;/strong&gt;&lt;/a&gt; is configured to pre-cache all the assets resulting from the build (&lt;code&gt;js&lt;/code&gt;, &lt;code&gt;css&lt;/code&gt; and &lt;code&gt;public&lt;/code&gt; folder). Using this setup, the browser can access the cache to load the app while offline. See the diagram below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3y6g3ekbu5g2k7grlgk9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3y6g3ekbu5g2k7grlgk9.png" alt="Image for post" width="800" height="355"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Service worker serving assets from the cache while offline&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Learn more about service workers at &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers" rel="noopener noreferrer"&gt;using service workers&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Run the build command to see changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your &lt;code&gt;dist&lt;/code&gt; folder you should find the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;└── dist  
  ├── css  
  │   └── app.&amp;lt;version&amp;gt;.css  
  ├── img/icons  
  │   ├── android-chrome-&amp;lt;size&amp;gt;.png  
  │   └── ...  
  ├── js  
  │   ├── app.&amp;lt;version&amp;gt;.png  
  │   └── ...  
  ├── favicon.ico  
  ├── index.html  
  ├── manifest.json  
  ├── precache-manifest.&amp;lt;version&amp;gt;.json  
  ├── robots.txt  
  └── service-worker.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;index.html&lt;/code&gt; has been modified to include the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Manifest" rel="noopener noreferrer"&gt;Web app manifest&lt;/a&gt; &lt;code&gt;manifest.json&lt;/code&gt; along with some meta tags and entries to support different devices and platforms. You can further customise these settings. The most important is&lt;code&gt;manifest.json/display&lt;/code&gt; set to &lt;code&gt;standalone&lt;/code&gt;. This setting will give the app a look and feel like a native application for Desktop and Mobile. Learn about all the options available in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Manifest" rel="noopener noreferrer"&gt;Web app manifest&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another important file is &lt;code&gt;service-worker.js&lt;/code&gt;. This contains the implementation for the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers" rel="noopener noreferrer"&gt;&lt;strong&gt;service worker&lt;/strong&gt;&lt;/a&gt; which determines the behaviour of the app while offline. As part of it, &lt;code&gt;precache-manifest.&amp;lt;version&amp;gt;.json&lt;/code&gt; includes all files to be installed and pre-cached as part of the app. This will make the app load almost instantly as it won’t use the network. These files were created by the &lt;a href="https://cli.vuejs.org/core-plugins/pwa.html#vue-cli-plugin-pwa" rel="noopener noreferrer"&gt;PWA CLI plugin&lt;/a&gt; and include all the assets from your build.&lt;/p&gt;

&lt;p&gt;Test the app running the following commands on a new terminal window:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd dist  
python -m SimpleHTTPServer 8887  // open localhost:8887
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Remember that in order to test the app you need to install the service worker first. This requires at least loading the app once.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To test the app while offline you can use the &lt;strong&gt;Developer Tools&lt;/strong&gt; or switch off your &lt;strong&gt;internet connection&lt;/strong&gt;. See below a screen capture after refreshing the page while offline:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpj5loto0tyjohxmwstrk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpj5loto0tyjohxmwstrk.png" alt="Image for post" width="800" height="444"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Chatty app while offline.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As you can see in the screenshot above using Chrome, in the &lt;strong&gt;Network tab&lt;/strong&gt;, the files are served by the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers" rel="noopener noreferrer"&gt;&lt;strong&gt;service worker&lt;/strong&gt;&lt;/a&gt; while offline (in green). Unfortunately the default setup won’t include any custom assets like our &lt;strong&gt;SVG logo&lt;/strong&gt; in the header (in red) or external fonts.&lt;/p&gt;
&lt;h1&gt;
  
  
  Adding a PWA custom configuration
&lt;/h1&gt;

&lt;p&gt;Let’s fix the issue with our logo by using a &lt;strong&gt;custom configuration&lt;/strong&gt;. Create &lt;code&gt;vue.config.js&lt;/code&gt; with the following content at the root of your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// vue.config.js  &lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;manifest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./public/manifest.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;pwa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;short_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;themeColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;theme_color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;msTileColor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;manifest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;background_color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;appleMobileWebAppCapable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yes&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;appleMobileWebAppStatusBarStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;black&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;workboxPluginMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;InjectManifest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;workboxOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="na"&gt;swSrc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/service-worker.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file controls the &lt;a href="https://cli.vuejs.org/core-plugins/pwa.html#vue-cli-plugin-pwa" rel="noopener noreferrer"&gt;PWA CLI plugin&lt;/a&gt; and deal with settings in the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Manifest" rel="noopener noreferrer"&gt;Web app manifest&lt;/a&gt; and UX for different devices.&lt;/p&gt;

&lt;p&gt;The custom configuration uses &lt;a href="https://developers.google.com/web/tools/workbox" rel="noopener noreferrer"&gt;workbox&lt;/a&gt; in &lt;code&gt;injectManifest&lt;/code&gt; mode and points to the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers" rel="noopener noreferrer"&gt;service worker&lt;/a&gt; implementation we want to use. Find all configuration options at the &lt;a href="https://cli.vuejs.org/core-plugins/pwa.html#configuration" rel="noopener noreferrer"&gt;official website&lt;/a&gt;. Now create &lt;code&gt;src/service-worker.js&lt;/code&gt; with the following code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/service-worker.js  &lt;/span&gt;
&lt;span class="nx"&gt;workbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setCacheNameDetails&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;amplify-datastore&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;workbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;skipWaiting&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
&lt;span class="nx"&gt;workbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clientsClaim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cacheFiles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;  
 &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;revision&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;e653ab4d124bf16b5232&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
 &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;[https://aws-amplify.github.io/img/amplify.svg](https://aws-amplify.github.io/img/amplify.svg)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;  
&lt;span class="p"&gt;}]&lt;/span&gt;

&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__precacheManifest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cacheFiles&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__precacheManifest&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;  
&lt;span class="nx"&gt;workbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;precaching&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;precacheAndRoute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__precacheManifest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For our &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers" rel="noopener noreferrer"&gt;&lt;strong&gt;service worker&lt;/strong&gt;&lt;/a&gt;, we are setting a prefix for our cache to easily find our files while using the &lt;strong&gt;Developer Tools&lt;/strong&gt;. We are also setting the behaviour for new service worker versions. These will be applied immediately replacing any existing ones with &lt;code&gt;skipWaiting&lt;/code&gt; and &lt;code&gt;clientsClaim&lt;/code&gt; as explained &lt;a href="https://developers.google.com/web/tools/workbox/modules/workbox-core#skip_waiting_and_clients_claim" rel="noopener noreferrer"&gt;here&lt;/a&gt;. To fix our &lt;strong&gt;SVG issue&lt;/strong&gt;, we are adding the url to the SVG file, to the &lt;strong&gt;pre-cached files&lt;/strong&gt; defined in the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Manifest" rel="noopener noreferrer"&gt;Web app manifest&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Improving UX while offline
&lt;/h1&gt;

&lt;p&gt;We are almost done. Our app can survive offline reloads, can store messages while offline and can synchronise when back online thanks to Amplify DataStore.&lt;/p&gt;

&lt;p&gt;The only remaining issue now is &lt;strong&gt;improving the user experience&lt;/strong&gt; as the user doesn’t know when the app is operating online or offline. This is not a great UX, as sometimes &lt;strong&gt;the user might inadvertently go offline&lt;/strong&gt; and be confused as for not receiving any feedback or explanation from the app. We can fix this by using the code below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// &amp;lt;div v-if="offline"&amp;gt;You are offline.&amp;lt;/div&amp;gt;  &lt;/span&gt;
&lt;span class="c1"&gt;// &amp;lt;div v-bind:class="{ offline: offline }"&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// App.vue  &lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Hub&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-amplify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;offline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;  
  &lt;span class="p"&gt;},&lt;/span&gt;  
  &lt;span class="nf"&gt;created&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listener&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Hub&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;datastore&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;networkStatus&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;active&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
      &lt;span class="p"&gt;}&lt;/span&gt;  
    &lt;span class="p"&gt;})&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are using the &lt;a href="https://docs.amplify.aws/lib/utilities/hub/q/platform/js" rel="noopener noreferrer"&gt;&lt;strong&gt;Amplify Hub&lt;/strong&gt;&lt;/a&gt; to detect &lt;strong&gt;network changes&lt;/strong&gt; and use it to set the &lt;code&gt;offline&lt;/code&gt; flag. Once in place, we can use it to display messages or style the UI accordingly as shown at the beginning of the code above. We are now ready to publish &lt;strong&gt;Chatty&lt;/strong&gt; to the cloud and test it using different devices.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fntva3eedyehvodvbwe2d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fntva3eedyehvodvbwe2d.png" alt="Image for post" width="472" height="624"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Chatty PWA informing the user of changes in the network status.&lt;/em&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Publishing your app via the AWS Amplify Console
&lt;/h1&gt;

&lt;p&gt;The first thing you need to do is &lt;strong&gt;create a new repo&lt;/strong&gt; for this project. Once you’ve created the repo, copy the &lt;strong&gt;URL&lt;/strong&gt; for the project to the clipboard and initialise git in your local project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git init  
git remote add origin [repo@repoofyourchoice.com](mailto:repo@repoofyourchoice.com):username/project-name.git  
git add .git commit -m 'initial commit'git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next visit the &lt;a href="https://aws.amazon.com/amplify/console/" rel="noopener noreferrer"&gt;&lt;strong&gt;AWS Amplify Console&lt;/strong&gt;&lt;/a&gt; in your &lt;strong&gt;AWS account&lt;/strong&gt;. Click &lt;strong&gt;Get Started&lt;/strong&gt; to create a new deployment. Next, authorise your repository provider as the repository service. Next, choose the new repository and branch for the project you just created and click &lt;strong&gt;Next&lt;/strong&gt;. In the next screen, create a new role and use this role to allow the &lt;strong&gt;AWS Amplify Console&lt;/strong&gt; to deploy these resources and click &lt;strong&gt;Next&lt;/strong&gt;. Finally, click &lt;strong&gt;Save&lt;/strong&gt; and &lt;strong&gt;Deploy&lt;/strong&gt; to deploy your application!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw9z0sufnqo8bime3nlkm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw9z0sufnqo8bime3nlkm.png" alt="Image for post" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;AWS Amplify Console deployment steps.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This will generate a public url that uses &lt;strong&gt;HTTPS&lt;/strong&gt;, which is a requirement for &lt;strong&gt;PWAs.&lt;/strong&gt; Congratulations! You can now test it in your browser, Desktop and Mobile.&lt;/p&gt;
&lt;h1&gt;
  
  
  Installing the Chatty app in the Desktop and Mobile
&lt;/h1&gt;

&lt;p&gt;Due to the inclusion of the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Manifest" rel="noopener noreferrer"&gt;Web app manifest&lt;/a&gt; in our &lt;code&gt;index.html&lt;/code&gt; page, you can now install the &lt;strong&gt;Chatty&lt;/strong&gt; app in the Desktop and Mobile devices in Windows, Mac and Linux. The way it works, changes slightly depending the device and operating system you are using. Try it out following the steps in &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Add_to_home_screen" rel="noopener noreferrer"&gt;Add to Home screen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frbsdcxmkyll8z6x1pqov.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frbsdcxmkyll8z6x1pqov.png" alt="Image for post" width="800" height="544"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Use add to Home screen to install in Desktop and Mobile.&lt;/em&gt;&lt;/p&gt;
&lt;h1&gt;
  
  
  Cleaning up cloud services
&lt;/h1&gt;

&lt;p&gt;If at any time, you would like to delete a service from your project and your &lt;strong&gt;AWS Account&lt;/strong&gt;, you can do this by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify delete
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Congratulations! You successfully built your first &lt;strong&gt;offline-first app&lt;/strong&gt; using &lt;strong&gt;Vue&lt;/strong&gt; and &lt;strong&gt;Amplify&lt;/strong&gt;. You created a chatroom &lt;strong&gt;PWA&lt;/strong&gt; that stores data on the device while offline and when online synchronises in real-time with other devices using &lt;strong&gt;Amplify DataStore, AWS AppSync&lt;/strong&gt;, &lt;strong&gt;GraphQL&lt;/strong&gt; and &lt;strong&gt;Amazon DynamoDB&lt;/strong&gt;. Thanks for following this tutorial.&lt;/p&gt;

&lt;p&gt;If you prefer, you can follow the instructions in this video to build the chatroom app.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/CXeRQn62Ptw"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Thanks for reading!
&lt;/h1&gt;

&lt;p&gt;Have you got any questions regarding this tutorial or &lt;strong&gt;AWS Amplify&lt;/strong&gt;? Feel free to reach out to me anytime at &lt;a href="https://twitter.com/intent/user?screen_name=gerardsans" rel="noopener noreferrer"&gt;@gerardsans&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7uedkcfqzn3p8hbnb3wl.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7uedkcfqzn3p8hbnb3wl.jpeg" alt="Image for post" width="360" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;My Name is &lt;a href="https://twitter.com/gerardsans" rel="noopener noreferrer"&gt;Gerard Sans&lt;/a&gt;. I am a Developer Advocate at &lt;a href="https://aws.amazon.com/products/mobile" rel="noopener noreferrer"&gt;AWS Mobile&lt;/a&gt; working with &lt;a href="https://aws-amplify.github.io/" rel="noopener noreferrer"&gt;AWS Amplify&lt;/a&gt; and &lt;a href="https://aws.amazon.com/appsync/" rel="noopener noreferrer"&gt;AWS AppSync&lt;/a&gt; teams.&lt;br&gt;
GraphQL is an open source data query and manipulation language for APIs, and a runtime for fulfilling queries with existing data.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>aws</category>
      <category>amplify</category>
      <category>vue</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Build your first full-stack serverless app with Vue and AWS Amplify</title>
      <dc:creator>gerard-sans</dc:creator>
      <pubDate>Tue, 29 Sep 2020 19:21:00 +0000</pubDate>
      <link>https://dev.to/aws/build-your-first-full-stack-serverless-app-with-vue-and-aws-amplify-13p8</link>
      <guid>https://dev.to/aws/build-your-first-full-stack-serverless-app-with-vue-and-aws-amplify-13p8</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5isjzenr75va583us2k4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5isjzenr75va583us2k4.png" alt="Image" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Build flexible, scalable, and reliable apps with AWS Amplify&lt;/p&gt;




&lt;p&gt;In this tutorial, you will learn how to build a full-stack serverless app using &lt;strong&gt;Vue&lt;/strong&gt; and &lt;strong&gt;AWS Amplify&lt;/strong&gt;. You will create a new project and add a full authorisation flow using the &lt;strong&gt;authenticator component&lt;/strong&gt;. This includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Introduction to &lt;strong&gt;AWS Amplify&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Setting up a new project with the &lt;strong&gt;Vue CLI&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Installing &lt;strong&gt;Amplify CLI&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Adding &lt;strong&gt;authentication&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Publishing&lt;/strong&gt; your app&lt;/li&gt;
&lt;li&gt;Cleaning up &lt;strong&gt;cloud services&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please let me know if you have any questions or want to learn more on the above at &lt;a href="https://twitter.com/intent/user?screen_name=gerardsans" rel="noopener noreferrer"&gt;@gerardsans&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction to AWS Amplify
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Amplify&lt;/strong&gt; makes developing, releasing and operating modern full-stack serverless apps easy and delightful. Mobile and frontend web developers are being supported throughout the app life cycle via an open source &lt;strong&gt;Amplify Framework&lt;/strong&gt; (consisting of the Amplify libraries and Amplify CLI) and seamless integrations with &lt;strong&gt;AWS cloud services&lt;/strong&gt;, and the &lt;strong&gt;AWS Amplify Console&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Amplify libraries&lt;/strong&gt;: in this article we will be using &lt;code&gt;aws-amplify&lt;/code&gt; and &lt;code&gt;@aws-amplify/ui-vue&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Amplify CLI&lt;/strong&gt;: command line tool for configuring and integrating cloud services.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;UI components&lt;/strong&gt;: authenticator, photo picker, photo album and chat bot.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Cloud services&lt;/strong&gt;: authentication, storage, analytics, notifications, AWS Lambda functions, REST and GraphQL APIs, predictions, chat bots and extended reality (AR/VR).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Offline-first support&lt;/strong&gt;: Amplify DataStore provides a programming model for leveraging shared and distributed data without writing additional code for data reconciliation between offline and online scenarios.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By using AWS Amplify, teams can focus on development while the Amplify team enforces best patterns and practices throughout the AWS Amplify stack.&lt;/p&gt;

&lt;h1&gt;
  
  
  Amplify CLI
&lt;/h1&gt;

&lt;p&gt;The &lt;strong&gt;Amplify CLI&lt;/strong&gt; provides a set of commands to help with repetitive tasks and automating &lt;strong&gt;cloud service&lt;/strong&gt; setup and provision.&lt;/p&gt;

&lt;p&gt;Some commands will prompt questions and provide sensible defaults to assist you during its execution. These are some common tasks. Run:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;amplify init&lt;/code&gt;, to setup a new environment. Eg: dev, test, dist.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;amplify push&lt;/code&gt;, to provision local resources to the cloud.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;amplify status&lt;/code&gt;, to list local resources and their current status.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The&lt;/em&gt; &lt;strong&gt;&lt;em&gt;Amplify CLI&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;uses&lt;/em&gt; &lt;strong&gt;&lt;em&gt;AWS CloudFormation&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;to manage service configuration and resource provisioning via&lt;/em&gt; &lt;strong&gt;&lt;em&gt;templates&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;. This a declarative and atomic approach to configuration. Once a template is executed, it will either fail or succeed.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Setting up a new project with the Vue CLI
&lt;/h1&gt;

&lt;p&gt;To get started, create a new project using the &lt;a href="https://cli.vuejs.org/" rel="noopener noreferrer"&gt;Vue CLI&lt;/a&gt;. If you already have it, skip to the next step. If not, install it and create the app using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn global add @vue/cli  
vue create amplify-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate to the new directory and check everything checks out before continuing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd amplify-app  
yarn serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;p&gt;Before going forward make sure you have gone through the &lt;a href="https://docs.amplify.aws/start/getting-started/installation/q/integration/vue" rel="noopener noreferrer"&gt;instructions in our docs&lt;/a&gt; to sign up to your &lt;strong&gt;AWS Account&lt;/strong&gt; and install and configure the &lt;strong&gt;Amplify CLI&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setting up your Amplify project
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;AWS Amplify&lt;/strong&gt; allows you to create different environments to define your preferences and settings. For any new project you need to run the command below and answer as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  Enter a name for the project: &lt;strong&gt;amplify-app&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Enter a name for the environment: &lt;strong&gt;dev&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Choose your default editor: &lt;strong&gt;Visual Studio Code&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Please choose the type of app that you’re building &lt;strong&gt;javascript&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  What javascript framework are you using &lt;strong&gt;vue&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Source Directory Path: &lt;strong&gt;src&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Distribution Directory Path: &lt;strong&gt;dist&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Build Command: &lt;strong&gt;npm run-script build&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Start Command: &lt;strong&gt;npm run-script serve&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Do you want to use an AWS profile? &lt;strong&gt;Yes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Please choose the profile you want to use &lt;strong&gt;default&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, the &lt;strong&gt;Amplify CLI&lt;/strong&gt; has initialised a new project and a new folder: &lt;strong&gt;amplify&lt;/strong&gt;. The files in this folder hold your project configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;amplify-app&amp;gt;  
    |\_ amplify  
      |\_ .config  
      |\_ #current-cloud-backend  
      |\_ backend  
      team-provider-info.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Installing the AWS Amplify dependencies
&lt;/h1&gt;

&lt;p&gt;Install the required dependencies for &lt;strong&gt;AWS Amplify&lt;/strong&gt; and &lt;strong&gt;Vue&lt;/strong&gt; using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add aws-amplify @aws-amplify/ui-vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Adding authentication
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;AWS Amplify&lt;/strong&gt; provides authentication via the &lt;code&gt;auth&lt;/code&gt; category which gives us access to &lt;strong&gt;AWS Cognito&lt;/strong&gt;. To add authentication use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify add auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When prompted choose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Do you want to use default authentication and security configuration?: &lt;strong&gt;Default configuration&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  How do you want users to be able to sign in when using your Cognito User Pool?: &lt;strong&gt;Username&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Do you want to configure advanced settings? &lt;strong&gt;No&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Pushing changes to the cloud
&lt;/h1&gt;

&lt;p&gt;By running the push command, the cloud resources will be provisioned and created in your &lt;strong&gt;AWS account&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To quickly check your newly created &lt;strong&gt;Cognito User Pool&lt;/strong&gt; you can run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;To access the&lt;/em&gt; &lt;strong&gt;&lt;em&gt;AWS Cognito Console&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;at any time, go to the dashboard at&lt;/em&gt; &lt;a href="https://console.aws.amazon.com/cognito/" rel="noopener noreferrer"&gt;&lt;em&gt;https://console.aws.amazon.com/cognito&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. Also be sure that your region is set correctly.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Your resources have been created and you can start using them!&lt;/p&gt;

&lt;h1&gt;
  
  
  Configuring the Vue application
&lt;/h1&gt;

&lt;p&gt;Reference the auto-generated &lt;code&gt;aws-exports.js&lt;/code&gt; file that is now in your &lt;code&gt;src&lt;/code&gt; folder. To configure the app, open &lt;code&gt;main.ts&lt;/code&gt; and add the following code below the last import:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Vue&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;  

&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Amplify&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-amplify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@aws-amplify/ui-vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;_exports&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./aws-exports&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;Amplify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;_exports&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

&lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productionTip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;  

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
  &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;h&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;$mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Using the Authenticator Component
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;AWS Amplify&lt;/strong&gt; provides &lt;strong&gt;UI components&lt;/strong&gt; that you can use in your app. Let’s add these components to the project&lt;/p&gt;

&lt;p&gt;In order to use the &lt;strong&gt;authenticator component&lt;/strong&gt; add it to &lt;code&gt;src/App.vue&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;amplify&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;authenticator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
&lt;span class="o"&gt;+&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Hey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;amplify&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;sign&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/amplify-sign-out&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/amplify-authenticator&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AuthState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onAuthUIStateChange&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@aws-amplify/ui-components&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt;      &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="p"&gt;},&lt;/span&gt;  
  &lt;span class="nf"&gt;created&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="c1"&gt;// authentication state managament  &lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="nf"&gt;onAuthUIStateChange&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt;      &lt;span class="c1"&gt;// set current user and load data after login  &lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;AuthState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SignedIn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt;        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt;      &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="p"&gt;})&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can run the app and see that an &lt;strong&gt;authentication flow&lt;/strong&gt; has been added in front of your &lt;strong&gt;app&lt;/strong&gt; &lt;strong&gt;component&lt;/strong&gt;. This flow gives users the ability to sign up and sign in.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;To view any users that were created, go back to the&lt;/em&gt; &lt;strong&gt;&lt;em&gt;Cognito Dashboard&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;at&lt;/em&gt; &lt;a href="https://console.aws.amazon.com/cognito/" rel="noopener noreferrer"&gt;&lt;em&gt;https://console.aws.amazon.com/cognito&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. Also be sure that your region is set correctly.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Alternatively you can also use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify console auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Accessing User Data
&lt;/h1&gt;

&lt;p&gt;To access the user’s info using the Auth API. This will return a &lt;strong&gt;promise&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Auth&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-amplify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;Auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;currentAuthenticatedUser&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Publishing your app
&lt;/h1&gt;

&lt;p&gt;To deploy and host your app on AWS, we can use the &lt;code&gt;hosting&lt;/code&gt; category.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify add hosting
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  Select the plugin module to execute: &lt;strong&gt;Amazon CloudFront and S3&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Select the environment setup: &lt;strong&gt;DEV&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  hosting bucket name &lt;strong&gt;YOURBUCKETNAME&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  index doc for the website &lt;strong&gt;index.html&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  error doc for the website &lt;strong&gt;index.html&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, everything is set up &amp;amp; we can publish it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Cleaning up Services
&lt;/h1&gt;

&lt;p&gt;To wipe out all resources from your project and your &lt;strong&gt;AWS Account&lt;/strong&gt;, you can do this by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify delete
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Congratulations! You successfully built your first &lt;strong&gt;full-stack serverless app&lt;/strong&gt; using &lt;strong&gt;Vue&lt;/strong&gt; and &lt;strong&gt;AWS Amplify&lt;/strong&gt;. Thanks for following this tutorial.&lt;/p&gt;

&lt;p&gt;You have learnt how to provide an &lt;strong&gt;authentication flow&lt;/strong&gt; using the &lt;strong&gt;authenticator component&lt;/strong&gt; or via the &lt;strong&gt;service API&lt;/strong&gt; and how to use &lt;strong&gt;Amplify CLI&lt;/strong&gt; to execute common tasks including adding and removing services.&lt;/p&gt;

&lt;h1&gt;
  
  
  Thanks for reading!
&lt;/h1&gt;

&lt;p&gt;Have you got any questions regarding this tutorial or &lt;strong&gt;AWS Amplify&lt;/strong&gt;? Feel free to reach out to me anytime at &lt;a href="https://twitter.com/intent/user?screen_name=gerardsans" rel="noopener noreferrer"&gt;@gerardsans&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7uedkcfqzn3p8hbnb3wl.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7uedkcfqzn3p8hbnb3wl.jpeg" alt="Image for post" width="360" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;My Name is &lt;a href="https://twitter.com/gerardsans" rel="noopener noreferrer"&gt;Gerard Sans&lt;/a&gt;. I am a Developer Advocate at &lt;a href="https://aws.amazon.com/products/mobile" rel="noopener noreferrer"&gt;AWS Mobile&lt;/a&gt; working with &lt;a href="https://aws-amplify.github.io/" rel="noopener noreferrer"&gt;AWS Amplify&lt;/a&gt; and &lt;a href="https://aws.amazon.com/appsync/" rel="noopener noreferrer"&gt;AWS AppSync&lt;/a&gt; teams.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>aws</category>
      <category>amplify</category>
      <category>vue</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Create a REST API integrated with Amazon DynamoDB using AWS Amplify and Vue</title>
      <dc:creator>gerard-sans</dc:creator>
      <pubDate>Mon, 28 Sep 2020 21:38:56 +0000</pubDate>
      <link>https://dev.to/aws/create-a-rest-api-integrated-with-amazon-dynamodb-using-aws-amplify-and-vue-566a</link>
      <guid>https://dev.to/aws/create-a-rest-api-integrated-with-amazon-dynamodb-using-aws-amplify-and-vue-566a</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhds1v81jud56uj40u09x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhds1v81jud56uj40u09x.png" alt="Image for post" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this article you will create a &lt;strong&gt;REST API&lt;/strong&gt; integrated with &lt;strong&gt;Amazon DynamoDB&lt;/strong&gt; using &lt;strong&gt;AWS Amplify&lt;/strong&gt; including &lt;strong&gt;CRUD operations&lt;/strong&gt; and publication. Access to the REST API will allow both registered users and guests. In order to test it you will create a client including an authentication flow using &lt;strong&gt;Vue&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Setting up a new project with the &lt;strong&gt;Vue CLI&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Creating a &lt;strong&gt;REST API&lt;/strong&gt; with &lt;strong&gt;Amplify CLI&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Creating a new &lt;strong&gt;REST API&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Implementing &lt;strong&gt;CRUD operations using Amazon DynamoDB&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Pushing your &lt;strong&gt;REST API&lt;/strong&gt; to the cloud&lt;/li&gt;
&lt;li&gt;  Publishing your app via the &lt;strong&gt;AWS Amplify Console&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Cleaning up &lt;strong&gt;cloud services&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please let me know if you have any questions or want to learn more at &lt;a href="https://twitter.com/intent/user?screen_name=gerardsans" rel="noopener noreferrer"&gt;@gerardsans&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&amp;gt; Final solution in &lt;a href="https://github.com/gsans/amplify-rest-todos-ui-vue" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setting up a new project with the Vue CLI
&lt;/h1&gt;

&lt;p&gt;Before moving to the next section, please complete the steps described in “&lt;a href="https://dev.to/aws/build-your-first-full-stack-serverless-app-with-vue-and-aws-amplify-14k4"&gt;Build your first full-stack serverless app with Vue&lt;/a&gt;”. Here you will set up the initial project, familiarise with &lt;strong&gt;Amplify CLI&lt;/strong&gt; and add an authorisation flow so users can register themselves via an automated verification code sent to their email and login.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating a REST API with Amplify CLI
&lt;/h1&gt;

&lt;p&gt;The &lt;strong&gt;Amplify CLI&lt;/strong&gt; provides a guided workflow to easily add, develop, &lt;a href="https://docs.amplify.aws/cli/restapi/testing" rel="noopener noreferrer"&gt;test&lt;/a&gt; and manage REST APIs to access your AWS resources from your web and mobile applications.&lt;/p&gt;

&lt;p&gt;A REST API or &lt;strong&gt;HTTP endpoint&lt;/strong&gt; will be composed by one or more paths. Eg: &lt;code&gt;/todos&lt;/code&gt;. Each path will use a &lt;strong&gt;Lambda function&lt;/strong&gt; to handle &lt;strong&gt;HTTP requests&lt;/strong&gt; and responses. Amplify CLI creates a single resource in &lt;strong&gt;Amazon API Gateway&lt;/strong&gt; so you can handle all routes, &lt;strong&gt;HTTP Methods&lt;/strong&gt; and &lt;strong&gt;paths&lt;/strong&gt;, with a single Lambda function via a &lt;a href="https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Lambda Proxy integration&lt;/strong&gt;&lt;/a&gt;. HTTP proxy integrations forward all requests and responses directly through to your &lt;strong&gt;HTTP endpoint&lt;/strong&gt;. Eg: &lt;code&gt;/todos&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fruquu3uc7qohqrv55ifc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fruquu3uc7qohqrv55ifc.png" alt="Image for post" width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Architecture diagram for the Todo App&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating a new REST API
&lt;/h1&gt;

&lt;p&gt;In this post, you are going to create a &lt;strong&gt;REST API&lt;/strong&gt; to service a todo app with a single endpoint &lt;code&gt;/todos&lt;/code&gt; using &lt;strong&gt;Amazon DynamoDB&lt;/strong&gt; as a data source. To create it, use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify add api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Answer the following questions&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Please select from one of the below mentioned services: &lt;strong&gt;REST&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Provide a friendly name for your resource to be used as a label for this category in the project: &lt;strong&gt;todosApi&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Provide a path (e.g., /book/{isbn}): &lt;strong&gt;/todos&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This will be the configuration for &lt;code&gt;/todos&lt;/code&gt; path in &lt;strong&gt;Amazon API Gateway&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/                          
|\_ /todos        Main resource. Eg: /todos  
   ANY           Methods: DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT  
   OPTIONS       Allow pre-flight requests in CORS by browser  
   |\_ /{proxy+}  Eg: /todos/, /todos/id  
      ANY        Methods: DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT  
      OPTIONS    Allow pre-flight requests in CORS by browser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, &lt;strong&gt;Amplify CLI&lt;/strong&gt; creates a greedy path variable &lt;code&gt;/todos/{proxy+}&lt;/code&gt; that catches all child resources for a path and forwards them to your Lambda. This will match all child routes including &lt;code&gt;/todos/id&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Choose a Lambda source &lt;strong&gt;Create a new Lambda function&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Provide a friendly name for your resource to be used as a label for this category in the project: &lt;strong&gt;todosLambda&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Provide the AWS Lambda function name: &lt;strong&gt;todosLambda&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Choose the runtime that you want to use: &lt;strong&gt;NodeJS&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Choose the function template that you want to use: &lt;strong&gt;CRUD function for Amazon DynamoDB&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Lambda function template, &lt;strong&gt;CRUD function for Amazon DynamoDB&lt;/strong&gt; implements route handlers for &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;POST&lt;/code&gt;, &lt;code&gt;PUT&lt;/code&gt; and &lt;code&gt;DELETE&lt;/code&gt; Http Methods and paths for &lt;code&gt;/todos&lt;/code&gt; and &lt;code&gt;/todos/*&lt;/code&gt;. Some possible routes examples include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /todos         List all todos  
GET /todos/1       Load a todo by id  
POST /todos        Create a todo  
PUT /todos         Update a todo  
DELETE /todos/1    Delete a todo by id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  Do you want to access other resources in this project from your Lambda function? &lt;strong&gt;No&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Do you want to invoke this function on a recurring schedule? &lt;strong&gt;No&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Do you want to configure Lambda layers for this function? &lt;strong&gt;No&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Do you want to edit the local lambda function now? &lt;strong&gt;Yes&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;We are going to change this template later but it’s good that you have it open as you follow the next steps.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;  Press enter to continue&lt;/li&gt;
&lt;li&gt;  Restrict API access &lt;strong&gt;Yes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Who should have access? &lt;strong&gt;Authenticated and Guest users&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  What kind of access do you want for Authenticated users? &lt;strong&gt;create, read, update, delete&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  What kind of access do you want for Guest users? &lt;strong&gt;read&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Amplify CLI restricts API access combining &lt;strong&gt;Amazon Cognito&lt;/strong&gt; for authentication and &lt;strong&gt;AWS IAM&lt;/strong&gt; (Identity and Access Management) for granting execution permissions on routes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;  Do you want to add another path? &lt;strong&gt;No&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s all! Before we publish to the cloud though, let’s see how to change the default template to implement &lt;strong&gt;create&lt;/strong&gt;, &lt;strong&gt;read&lt;/strong&gt;, &lt;strong&gt;update&lt;/strong&gt; and &lt;strong&gt;delete&lt;/strong&gt; operations for your todo app.&lt;/p&gt;

&lt;h1&gt;
  
  
  Implementing CRUD operations with Amazon DynamoDB
&lt;/h1&gt;

&lt;p&gt;In order to manage your todo app you want to implement all &lt;strong&gt;CRUD operations&lt;/strong&gt;, these are: create, read, update and delete. The template we picked in the last section uses &lt;a href="https://github.com/awslabs/aws-serverless-express" rel="noopener noreferrer"&gt;&lt;strong&gt;AWS Serverless Express&lt;/strong&gt;&lt;/a&gt;. &lt;strong&gt;Amazon API Gateway&lt;/strong&gt; will proxy incoming requests to your &lt;strong&gt;todosLambda&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For the implementation, you need to add &lt;strong&gt;route handlers&lt;/strong&gt; to match all HTTP methods and paths you want to support. The first to match with an incoming request will be then executed. This will be in the same order as you have define them. If there’s no match an error will be returned.&lt;/p&gt;

&lt;p&gt;See below, how different &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods" rel="noopener noreferrer"&gt;HTTP methods&lt;/a&gt; and operations match route definitions in &lt;strong&gt;AWS Serverless Express&lt;/strong&gt; and &lt;a href="https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/dynamodb-example-document-client.html" rel="noopener noreferrer"&gt;&lt;strong&gt;DynamoDB Document Client&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0u995gm08t9wiy7ck4ds.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0u995gm08t9wiy7ck4ds.png" alt="Image for post" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;REST API mapping between HTTP requests, AWS Serverless Express and Document Client calls.&lt;/p&gt;

&lt;p&gt;Before we start, you need to install a library to generate the ids for new todos. To install this dependency run the following commands from the root of your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd /amplify/backend/function/todosLambda/src  
npm i --save uuid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;/amplify/backend/function/todosLambda/src/app.js&lt;/code&gt; and replace its content for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AWS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;awsServerlessExpressMiddleware&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-serverless-express/middleware&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;bodyParser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;body-parser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;v4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;uuidv4&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;uuid&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nx"&gt;AWS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;region&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TABLE_REGION&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;  
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dynamodb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;AWS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DynamoDB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DocumentClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tableName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;todosTable&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ENV&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ENV&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;NONE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nx"&gt;tableName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tableName&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ENV&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyParser&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;  
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;awsServerlessExpressMiddleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eventContext&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Access-Control-Allow-Origin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Access-Control-Allow-Headers&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Origin, X-Requested-With, Content-Type, Accept&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
  &lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;  
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the same code from the default template adding the &lt;a href="https://github.com/uuidjs/uuid" rel="noopener noreferrer"&gt;&lt;strong&gt;uuid&lt;/strong&gt;&lt;/a&gt; library. This takes care of initialising &lt;strong&gt;DynamoDB Document Client&lt;/strong&gt; API to interact with DynamoDB, the DynamoDB table name taking into account the &lt;a href="https://docs.amplify.aws/cli/teams/overview" rel="noopener noreferrer"&gt;current environment&lt;/a&gt; and enabling &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS" rel="noopener noreferrer"&gt;CORS headers&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s handle the first route, we will use the &lt;strong&gt;HTTP Method&lt;/strong&gt; and path by the title for reference as in the next section. For each operation, first we will include the code from the client; and then, followed by the code serving it in the &lt;strong&gt;todosLambda&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fetching todos (GET, /todos)
&lt;/h2&gt;

&lt;p&gt;In the client, we use the &lt;strong&gt;Amplify JavaScript library&lt;/strong&gt; &lt;code&gt;aws-amplify&lt;/code&gt; to consume the &lt;strong&gt;REST API&lt;/strong&gt;. In order to fetch the todos use&lt;code&gt;API.get&lt;/code&gt; with the &lt;code&gt;todosApi&lt;/code&gt; followed by the path &lt;code&gt;/todos&lt;/code&gt; and an empty payload. The result is an array with the todos as part of the &lt;code&gt;body&lt;/code&gt;. Remember to use &lt;code&gt;JSON.parse&lt;/code&gt; as the &lt;code&gt;result.body&lt;/code&gt; needs to be in plain text due to &lt;strong&gt;HTTP transport&lt;/strong&gt;. The result object also contains the &lt;code&gt;statusCode&lt;/code&gt; and path as &lt;code&gt;url&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// client request: fetching todos  &lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;API&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-amplify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;API&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;todosApi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/todos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
 &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
 &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s look at the code in todosLambda. To fetch todos, map a handler function to the &lt;strong&gt;GET Method&lt;/strong&gt; and the &lt;code&gt;/todos&lt;/code&gt; path. Then run a &lt;code&gt;dynamodb.scan&lt;/code&gt; operation. This fetches all records in the table specified. Limit the results to 100 items. Find more details in the &lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStarted.NodeJs.03.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Developer Guide&lt;/strong&gt;&lt;/a&gt; from Amazon DynamoDB.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Scan returns all the data in a table so you may consider to change it for a query if you expect more than just few records.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// todosLambda route handler: fetching todos&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/todos&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="nx"&gt;dynamodb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="p"&gt;});&lt;/span&gt;  
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns the todos array as part of the &lt;code&gt;body&lt;/code&gt;. Don’t forget to use &lt;code&gt;JSON.stringify&lt;/code&gt;as it needs to be in plain text due to &lt;strong&gt;HTTP transport&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Once the operation finishes, check for errors and create a &lt;strong&gt;JSON response&lt;/strong&gt; accordingly. You will use the same approach in the rest of operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fetching a todo by id (GET, /todos/:id)
&lt;/h2&gt;

&lt;p&gt;Let’s quickly see the code necessary on the client below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// client request: fetching a todo by id&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;API&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-amplify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;API&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;todosApi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/todos/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how to use &lt;code&gt;API.get&lt;/code&gt; with a path using a template string generating the path. Eg: &lt;code&gt;/todos/${id}&lt;/code&gt; becomes &lt;code&gt;"/todos/c71f0be2–607d-48bc-b721–4cb77c90a58f"&lt;/code&gt;. The result receives the todo details.&lt;/p&gt;

&lt;p&gt;Let’s see how to get the details from a single todo in &lt;strong&gt;todosLambda&lt;/strong&gt;. In order to capture the todo &lt;code&gt;id&lt;/code&gt; use &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/routes?#Route_parameters" rel="noopener noreferrer"&gt;route parameters&lt;/a&gt;, a feature from &lt;strong&gt;AWS Serverless Express&lt;/strong&gt;. Route parameters use a semicolon to capture values at specific position in the URL like in &lt;code&gt;/users/**:userId**/books/**:bookId**&lt;/code&gt;. Values are then available in the request object as &lt;code&gt;request.params.userId&lt;/code&gt; and &lt;code&gt;request.params.bookId&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// todosLambda route handler: fetching a todo by id&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/todos/:id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="nx"&gt;dynamodb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="p"&gt;});&lt;/span&gt;  
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As in the code above, use &lt;code&gt;dynamodb.get&lt;/code&gt; to set your table and partition key &lt;code&gt;Key.id&lt;/code&gt; from the request parameters.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;For &lt;code&gt;todosApi&lt;/code&gt; we only have a partition key, if you have a composed key (partition key + sort key) include the sort key too as part of the &lt;code&gt;Key.sk&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Creating a new todo (POST, /todos)
&lt;/h2&gt;

&lt;p&gt;In order to create a new todo, use &lt;code&gt;API.post&lt;/code&gt; and set the payload to include the new todo description &lt;code&gt;text&lt;/code&gt; within the request &lt;code&gt;body&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// client request: creating a new todo&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;API&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-amplify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;API&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;todosApi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/todos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
 &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;todo-1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;strong&gt;todosLambda&lt;/strong&gt;, creating a new todo is a bit more elaborated as we need to provide some new attributes and values. As we saw in the code above, the &lt;code&gt;request.body&lt;/code&gt;contains the description for the new todo: &lt;code&gt;text&lt;/code&gt;. Generate a new &lt;code&gt;id&lt;/code&gt;, set &lt;code&gt;complete&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt;, add&lt;code&gt;createdAt&lt;/code&gt;and &lt;code&gt;updatedAt&lt;/code&gt; timestamps and include the &lt;code&gt;userId&lt;/code&gt;. To create the todo use &lt;code&gt;dynamodb.put&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// todosLambda route handler: creating a new todoapp.post("/todos", function (request, response) {  &lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;uuidv4&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;               &lt;span class="c1"&gt;// auto-generate id  &lt;/span&gt;
      &lt;span class="na"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;            &lt;span class="c1"&gt;// default for new todos  &lt;/span&gt;
      &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
      &lt;span class="na"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
      &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;getUserId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// userId from request  &lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt; 
  &lt;span class="nx"&gt;dynamodb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="p"&gt;});&lt;/span&gt;  
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The helper function &lt;code&gt;getUserId&lt;/code&gt; below extracts the user id from &lt;strong&gt;Amazon Cognito&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// todosLambda route handler: helper function&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getUserId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reqContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;apiGateway&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requestContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authProvider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;reqContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cognitoAuthenticationProvider&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;authProvider&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;authProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;:CognitoSignIn:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;UNAUTH&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;UNAUTH&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code tries to capture the user id from the request identity context and if unsuccessful, returns an unauthorised token with &lt;code&gt;UNAUTH&lt;/code&gt; as the value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updating a todo (PUT, /todos)
&lt;/h2&gt;

&lt;p&gt;At this point you should know how to use the &lt;strong&gt;Amplify API&lt;/strong&gt;. In order to update a todo use &lt;code&gt;API.put&lt;/code&gt; and the &lt;code&gt;/todos&lt;/code&gt; path. As you did creating a new todo provide the todo changes including its &lt;code&gt;id&lt;/code&gt; as part of the &lt;code&gt;body&lt;/code&gt;. As in the code below, change both the &lt;code&gt;description&lt;/code&gt; and the &lt;code&gt;complete&lt;/code&gt; values. The result contains any fields that were changed and their new values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// client request: updating a todo&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;API&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-amplify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;API&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;todosApi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/todos`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;   
 &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;todo-2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;todo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The update in &lt;strong&gt;todosLambda&lt;/strong&gt; uses most of the code you are already familiar but including a new &lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStarted.NodeJs.03.html" rel="noopener noreferrer"&gt;update expression&lt;/a&gt;. This expression includes optional attributes so we need to create it dynamically. Eg: to service a request changing only the description &lt;code&gt;text&lt;/code&gt; but not the other attributes. We used &lt;code&gt;UPDATED_NEW&lt;/code&gt; to return only the updated attributes in &lt;strong&gt;DynamoDB&lt;/strong&gt; but if you need all attributes use &lt;code&gt;ALL_NEW&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// todosLambda route handler: updating a todo&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/todos&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;  
    &lt;span class="na"&gt;ExpressionAttributeNames&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;  
    &lt;span class="na"&gt;ExpressionAttributeValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;  
    &lt;span class="na"&gt;ReturnValues&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;UPDATED_NEW&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;  
  &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UpdateExpression&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SET &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ExpressionAttributeValues&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UpdateExpression&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#text = :text, &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ExpressionAttributeValues&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:complete&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UpdateExpression&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;complete = :complete, &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ExpressionAttributeValues&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:updatedAt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
    &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UpdateExpression&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;updatedAt = :updatedAt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="nx"&gt;dynamodb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Attributes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="p"&gt;});&lt;/span&gt;  
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;To keep the semantics of HTTP PUT use the todo id from &lt;code&gt;request.body.id&lt;/code&gt; instead of the &lt;code&gt;request.params.id&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Deleting a todo by id (DELETE, /todos/:id)
&lt;/h2&gt;

&lt;p&gt;Let’s implement the request to delete a todo. On the client, use &lt;code&gt;API.del&lt;/code&gt; with a path including the &lt;code&gt;id&lt;/code&gt; as a &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/routes?#Route_parameters" rel="noopener noreferrer"&gt;route parameter&lt;/a&gt;. If successful, the result &lt;code&gt;body&lt;/code&gt; will be &lt;code&gt;{}&lt;/code&gt; with &lt;code&gt;statusCode:200&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// client request: deleting a todo by id&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;API&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-amplify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;API&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;del&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;todosApi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/todos/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{}).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;strong&gt;todosLambda&lt;/strong&gt;, use the same techniques from the previous route handlers now using &lt;code&gt;dynamodb.delete&lt;/code&gt; operation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// todosLambda route handler: deleting a todo by id&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/todos/:id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="na"&gt;TableName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tableName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
    &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="nx"&gt;dynamodb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
      &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;  
    &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="p"&gt;});&lt;/span&gt;  
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This completes all the CRUD operations. Before we can test it we need to publish it.&lt;/p&gt;

&lt;h1&gt;
  
  
  Pushing your new REST API to the cloud
&lt;/h1&gt;

&lt;p&gt;Let’s deploy the new &lt;strong&gt;REST API&lt;/strong&gt; in the cloud by running this command in the root of your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the end of this command you can take note of your new REST API url.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;REST APIs follow this pattern&lt;/em&gt; &lt;code&gt;https://{restapi-id}.execute-api.{region}.amazonaws.com/{environment}/{path}&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s see an overview of all the resources created by &lt;strong&gt;Amplify CLI&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REST  
 |\_ /todos (path)  
    |\_ todosApi (Amazon API Gateway)   
       |\_ todosLambda (AWS Lambda)  
          |\_ Logs (Amazon CloudWatch)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have covered all AWS Services but &lt;strong&gt;Amazon CloudWatch&lt;/strong&gt;. This service will allow you to monitor usage and access to logs during development and testing.&lt;/p&gt;

&lt;h1&gt;
  
  
  Publishing your app via the AWS Amplify Console
&lt;/h1&gt;

&lt;p&gt;The first thing you need to do is &lt;strong&gt;create a new repo&lt;/strong&gt; for this project. Once you’ve created the repo, copy the URL for the project to the clipboard and initialise git in your local project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git init  
git remote add origin [repo@repoofyourchoice.com](mailto:repo@repoofyourchoice.com):username/project-name.git  
git add .git commit -m 'initial commit'git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next visit the &lt;a href="https://aws.amazon.com/amplify/console/" rel="noopener noreferrer"&gt;&lt;strong&gt;AWS Amplify Console&lt;/strong&gt;&lt;/a&gt; in your &lt;strong&gt;AWS account&lt;/strong&gt;. Click &lt;strong&gt;Get Started&lt;/strong&gt; to create a new deployment. Next, authorise your repository provider as the repository service. Next, choose the new repository and branch for the project you just created and click &lt;strong&gt;Next&lt;/strong&gt;. In the next screen, create a new role and use this role to allow the &lt;strong&gt;AWS Amplify Console&lt;/strong&gt; to deploy these resources and click &lt;strong&gt;Next&lt;/strong&gt;. Finally, click &lt;strong&gt;Save&lt;/strong&gt; and &lt;strong&gt;Deploy&lt;/strong&gt; to deploy your application!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvrgvq0rey9db3r19m8z6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvrgvq0rey9db3r19m8z6.png" alt="Image for post" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AWS Amplify Console deployment steps.&lt;/p&gt;

&lt;h1&gt;
  
  
  Cleaning up cloud services
&lt;/h1&gt;

&lt;p&gt;If at any time, you would like to delete the services from your project and your &lt;strong&gt;AWS Account&lt;/strong&gt;, you can do this by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify delete
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Congratulations! You successfully created a &lt;strong&gt;REST API&lt;/strong&gt; using &lt;strong&gt;AWS Amplify&lt;/strong&gt;, implemented all CRUD operations using &lt;strong&gt;Amazon DynamoDB&lt;/strong&gt; and created a client to consume it &lt;strong&gt;restricting access to both registered users and guests&lt;/strong&gt; using &lt;strong&gt;Vue&lt;/strong&gt;. Thanks for following this tutorial.&lt;/p&gt;

&lt;p&gt;If you prefer, you can also follow this video to achieve the same result.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/hXL5z1TaqTk"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Thanks for reading!
&lt;/h1&gt;

&lt;p&gt;Have you got any questions about this tutorial or &lt;strong&gt;AWS Amplify&lt;/strong&gt;? Feel free to reach me anytime at &lt;a href="https://twitter.com/intent/user?screen_name=gerardsans" rel="noopener noreferrer"&gt;@gerardsans&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm5j2pdu97dgvlb2l9xb5.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm5j2pdu97dgvlb2l9xb5.jpeg" alt="Image for post" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;My Name is&lt;/em&gt; &lt;a href="https://twitter.com/gerardsans" rel="noopener noreferrer"&gt;&lt;em&gt;Gerard Sans&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. I am a Developer Advocate at&lt;/em&gt; &lt;a href="https://aws.amazon.com/products/mobile" rel="noopener noreferrer"&gt;&lt;em&gt;AWS Mobile&lt;/em&gt;&lt;/a&gt; &lt;em&gt;working with&lt;/em&gt; &lt;a href="https://aws-amplify.github.io/" rel="noopener noreferrer"&gt;&lt;em&gt;AWS Amplify&lt;/em&gt;&lt;/a&gt; &lt;em&gt;and&lt;/em&gt; &lt;a href="https://aws.amazon.com/appsync/" rel="noopener noreferrer"&gt;&lt;em&gt;AWS AppSync&lt;/em&gt;&lt;/a&gt; &lt;em&gt;teams.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>aws</category>
      <category>dynamodb</category>
      <category>amplify</category>
      <category>vue</category>
    </item>
    <item>
      <title>Create a cloud-enabled GraphQL API with AWS Amplify and Vue</title>
      <dc:creator>gerard-sans</dc:creator>
      <pubDate>Mon, 28 Sep 2020 20:49:56 +0000</pubDate>
      <link>https://dev.to/aws/create-a-cloud-enabled-graphql-api-with-aws-amplify-and-vue-271o</link>
      <guid>https://dev.to/aws/create-a-cloud-enabled-graphql-api-with-aws-amplify-and-vue-271o</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdsa7wjpentwkfg0dtpu9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdsa7wjpentwkfg0dtpu9.png" alt="Image for post" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this tutorial, we will learn how to build a GraphQL data-driven serverless app using &lt;strong&gt;Vue&lt;/strong&gt;, &lt;strong&gt;AWS Amplify&lt;/strong&gt; and &lt;strong&gt;AWS AppSync&lt;/strong&gt;. We will create a new project with Vue, generate a serverless GraphQL API using &lt;strong&gt;AWS AppSync&lt;/strong&gt; and build a client to consume it including real-time. We will cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Introduction to &lt;strong&gt;AWS AppSync&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Setting up a new project with the &lt;strong&gt;Vue CLI&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Creating a new &lt;strong&gt;GraphQL API&lt;/strong&gt; and using your first &lt;strong&gt;GraphQL transform&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Pushing your &lt;strong&gt;GraphQL API&lt;/strong&gt; to the cloud&lt;/li&gt;
&lt;li&gt;  Building the &lt;strong&gt;client&lt;/strong&gt;: adding queries, mutations and real-time&lt;/li&gt;
&lt;li&gt;  Publishing your app via the &lt;strong&gt;AWS Amplify Console&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Cleaning up &lt;strong&gt;cloud services&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;In order to follow this post you will need a basic knowledge of GraphQL. You can learn the basics following this tutorial at&lt;/em&gt; &lt;a href="https://graphql.org/learn/" rel="noopener noreferrer"&gt;&lt;em&gt;graphql.org&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&amp;gt; Final solution and step by step tutorial in &lt;a href="https://github.com/gsans/fullstack-serverless-amplify-ui-vue" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Please let me know if you have any questions or want to learn more at &lt;a href="https://twitter.com/intent/user?screen_name=gerardsans" rel="noopener noreferrer"&gt;@gerardsans&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction to AWS AppSync
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;AWS AppSync&lt;/strong&gt; allows you to create highly scalable serverless GraphQL data-driven mobile and web apps by providing an open source &lt;strong&gt;Amplify&lt;/strong&gt; &lt;strong&gt;Framework&lt;/strong&gt; (consisting of AWS AppSync Clients, GraphQL transforms and the CLI), integrations with multiple &lt;strong&gt;data sources&lt;/strong&gt;, and the &lt;strong&gt;AWS AppSync console&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;GraphQL client&lt;/strong&gt;: client-side library to securely access data from your GraphQL API. Built-in support for real-time and offline/delta client synchronisation.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Amplify CLI&lt;/strong&gt;: set of commands, via the&lt;code&gt;api&lt;/code&gt; category, to automate the setup and provision of resources for AWS AppSync and Amazon API Gateway cloud services. Support for REST and GraphQL APIs.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;GraphQL Transforms&lt;/strong&gt;: custom GraphQL schema directives that can be used in your GraphQL schema to enable custom workflows.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Data sources&lt;/strong&gt;: databases (Amazon DynamoDB for NoSQL, Amazon Aurora for RDBMS), searches (Amazon Elasticsearch Service), and AWS Lambda functions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By using AWS AppSync, teams can quickly create highly scalable serverless GraphQL data-driven apps for mobile and web while leaving the heavy lifting to the Amplify CLI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmtbnumde7tchpx0fgq2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmtbnumde7tchpx0fgq2.png" alt="Image for post" width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AWS AppSync data-driven apps architecture overview&lt;/p&gt;

&lt;h1&gt;
  
  
  Setting up a new project with the Vue CLI
&lt;/h1&gt;

&lt;p&gt;Before moving to the next section, please complete the steps described in “&lt;a href="https://dev.to/aws/build-your-first-full-stack-serverless-app-with-vue-and-aws-amplify-14k4"&gt;Build your first full-stack serverless app with Vue&lt;/a&gt;”.&lt;/p&gt;

&lt;h1&gt;
  
  
  Creating a new GraphQL API
&lt;/h1&gt;

&lt;p&gt;For this post we are going to create a GraphQL API to list our favourite restaurants. To create it, we will use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify add api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Answer the following questions&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Please select from one of the below mentioned services &lt;strong&gt;GraphQL&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Provide API name: &lt;strong&gt;RestaurantAPI&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Choose the default authorization type for the API &lt;strong&gt;API key&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Enter a description for the API key: &lt;strong&gt;(empty)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  After how many days from now the API key should expire (1–365): &lt;strong&gt;7&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Do you want to configure advanced settings for the GraphQL API &lt;strong&gt;No, I am done.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Do you have an annotated GraphQL schema? &lt;strong&gt;No&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Choose a schema template: &lt;strong&gt;Single object with fields (e.g., “Todo” with ID, name, description)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Do you want to edit the schema now? &lt;strong&gt;Yes&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When prompted, replace the default schema with the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Restaurant @model {  
  id: ID!  
  name: String!  
  description: String!  
  city: String!  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should be familiar with everything in the GraphQL schema above but for the &lt;code&gt;@model&lt;/code&gt; directive. This is a GraphQL transform provided by AppSync.&lt;/p&gt;

&lt;h1&gt;
  
  
  Using your first GraphQL transform
&lt;/h1&gt;

&lt;p&gt;GraphQL transforms allow AppSync to provide further customisation and support for common scenarios, so you don’t have to.&lt;/p&gt;

&lt;p&gt;By adding&lt;code&gt;@model&lt;/code&gt; to the&lt;code&gt;Restaurant&lt;/code&gt;type we are telling the Amplify CLI runtime to create the resolvers to support queries, mutations and subscriptions in DynamoDB. Besides the regular CRUD operations, we are also getting some more advanced features like pagination and filtering that we are going to cover later.&lt;/p&gt;

&lt;p&gt;Once we apply&lt;code&gt;@model&lt;/code&gt; to a type we get access to these other transforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;@key&lt;/code&gt; to configure custom index structures in &lt;strong&gt;DynamoDB&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;@searchable&lt;/code&gt; to enable searches using &lt;strong&gt;Amazon Elasticsearch&lt;/strong&gt; Service&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;@connection&lt;/code&gt; to add relationships between types&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;@lambda&lt;/code&gt; to generate &lt;strong&gt;AWS Lambda&lt;/strong&gt; resolvers&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;@auth&lt;/code&gt; to add fine grained multi-authorisation support&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;@versioned&lt;/code&gt; to add conflict resolution for offline scenarios&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Learn how to use each transform in detail from the &lt;a href="https://docs.amplify.aws/cli/graphql-transformer/directives" rel="noopener noreferrer"&gt;official docs&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;GraphQL Transforms are implemented using custom GraphQL schema directives as defined in the&lt;/em&gt; &lt;a href="https://graphql.github.io/graphql-spec/draft/#sec-Language.Directives" rel="noopener noreferrer"&gt;&lt;em&gt;GraphQL specification&lt;/em&gt;&lt;/a&gt;&lt;em&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Pushing your GraphQL API to the cloud
&lt;/h1&gt;

&lt;p&gt;Let’s run the push command to create the GraphQL API and see the results of using the &lt;code&gt;@model&lt;/code&gt; transform:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  Are you sure you want to continue? &lt;strong&gt;Yes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Do you want to generate code for your newly created GraphQL API &lt;strong&gt;Yes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Choose the code generation language target &lt;strong&gt;javascript&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Enter the file name pattern of graphql queries, mutations and subscriptions &lt;strong&gt;src/graphql/**/*.js&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Do you want to generate/update all possible GraphQL operations — queries, mutations and subscriptions &lt;strong&gt;Yes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Enter maximum statement depth [increase from default if your schema is deeply nested] &lt;strong&gt;2&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Write down your &lt;strong&gt;GraphQL endpoint&lt;/strong&gt; and &lt;strong&gt;API KEY&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Run the command below to access the &lt;strong&gt;AWS AppSync console&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify console api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  Please select from one of the below mentioned services &lt;strong&gt;GraphQL&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Testing your new GraphQL API
&lt;/h1&gt;

&lt;p&gt;Once in the AWS AppSync console, click on &lt;strong&gt;Queries&lt;/strong&gt; on the left side. This will open an editor that we can use to edit and test GraphQL queries.&lt;/p&gt;

&lt;p&gt;Execute the following mutation to create a new restaurant:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mutation createRestaurant {  
  createRestaurant(input: {  
    name: "Nobu"  
    description: "Great Sushi"  
    city: "New York"  
  }) {  
    id name description city  
  }  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, run this query to list the restaurant we just added:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query listRestaurants {  
  listRestaurants {  
    items {  
      id  
      name  
      description  
      city  
    }  
  }  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Besides creating all common CRUD operations for your types, AWS AppSync also creates extra utility features like filters. Run this query to try using filters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query searchRestaurants {  
  listRestaurants(filter: {  
    city: {  
      contains: "New York"  
    }  
  }) {  
    items {  
      id  
      name  
      description  
      city  
    }  
  }  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AWS AppSync creates filters on GraphQL scalar types (ID, String, Int, Float, Boolean) for list operations like listRestaurants.&lt;/p&gt;

&lt;h1&gt;
  
  
  Querying data with queries
&lt;/h1&gt;

&lt;p&gt;In the earlier sections, we made sure we had a working GraphQL API. On the client, we will start by displaying a list.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;  
  &amp;lt;div v-for="restaurant of restaurants" :key="restaurant.id"&amp;gt;  
    {{restaurant.name}}  
  &amp;lt;/div&amp;gt;  
&amp;lt;/template&amp;gt;  
&amp;lt;script&amp;gt;  
import { API, graphqlOperation } from 'aws-amplify';  
import { listRestaurants } from './graphql/queries';  

export default {  
  name: 'app',  
  data() {  
    return {  
      restaurants: [],  
    }  
  },  
  created() {  
    this.getData();  
  },  
  methods: {  
    async getData() {  
      try {  
        const response = await API.graphql(graphqlOperation(listRestaurants));  
        this.restaurants = response.data.listRestaurants.items;  
      }  
      catch (error) {  
        console.log('Error loading restaurants...', error);  
      }  
    },  
  }  
}  
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the code above, we are using &lt;code&gt;API.graphql&lt;/code&gt;to run the &lt;code&gt;listRestaurants&lt;/code&gt;query within &lt;code&gt;getData&lt;/code&gt;. Queries were created by the Amplify CLI during the push command. This call returns a promise that we handle by using async/await and render the result using &lt;code&gt;v-for&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You might be wondering why we used &lt;code&gt;listRestaurants.items&lt;/code&gt;. This is because AWS AppSync created an intermediate type &lt;code&gt;ModelRestaurantConnection&lt;/code&gt;. This is so we can handle pagination scenarios together with&lt;code&gt;limit&lt;/code&gt; and &lt;code&gt;nextToken&lt;/code&gt;parameters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;listRestaurants(filter: ModelRestaurantFilterInput, limit: Int, nextToken: String): ModelRestaurantConnection 
type ModelRestaurantConnection {  
 items: [Restaurant]  
 nextToken: String  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Creating data with mutations
&lt;/h1&gt;

&lt;p&gt;In order to add new restaurants, we are going to create a data entry using &lt;code&gt;form&lt;/code&gt; to take the required user input and pass it forward to the &lt;strong&gt;createRestaurant&lt;/strong&gt; mutation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;  
  &amp;lt;div&amp;gt;  
    &amp;lt;form v-on:submit.prevent&amp;gt;  
      &amp;lt;div&amp;gt;  
        &amp;lt;label&amp;gt;Name: &amp;lt;/label&amp;gt;  
        &amp;lt;input v-model='form.name' class='input' /&amp;gt;  
      &amp;lt;/div&amp;gt;  
      ...  
      &amp;lt;button @click='createRestaurant' class='button'&amp;gt;Create&amp;lt;/button&amp;gt;  
    &amp;lt;/form&amp;gt;  
  &amp;lt;/div&amp;gt;  
&amp;lt;/template&amp;gt;  
&amp;lt;script&amp;gt;  
import { createRestaurant } from './graphql/mutations';  

export default {  
  name: 'app',  
  data() {  
    return {  
      form: { },  
    }  
  },  
  methods: {  
    async createRestaurant() {  
      const { name, description, city } = this.form  
      if (!name || !description || !city) return;  

      const restaurant = { name, description, city };  
      try {  
        const response = await API.graphql(graphqlOperation(createRestaurant, { input: restaurant }))  
        console.log('Item created!')  
        this.restaurants = [...this.restaurants, response.data.createRestaurant];  
        this.form = { name: '', description: '', city: '' };  
      } catch (error) {  
        console.log('Error creating restaurant...', error)  
      }  
    },  
  }  
}  
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note how AWS AppSync instead of passing each field as an argument created an input type &lt;code&gt;CreateRestaurantInput&lt;/code&gt; which makes our client code simpler and convenient.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Mutation {  
 createRestaurant(input: CreateRestaurantInput!): Restaurant  
}input CreateRestaurantInput {  
 id: ID  
 name: String!  
 description: String!  
 city: String!  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we did before with queries, we are using async/await to run our mutation as we submit the form via &lt;code&gt;onCreate&lt;/code&gt;. Once we get the result, we use the form data to update the list and clear the form inputs.&lt;/p&gt;

&lt;h1&gt;
  
  
  Adding real-time with subscriptions
&lt;/h1&gt;

&lt;p&gt;To demonstrate real-time, we are going to use a subscription to update AppSync clients when new restaurants are added. AppSync clients will subscribe to listen for changes going through our GraphQL API. More specifically, restaurant creation mutations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { onCreateRestaurant } from './graphql/subscriptions';  

export default {  
  name: 'app',  
  created() {  
    //Subscribe to changes  
    API.graphql(graphqlOperation(onCreateRestaurant))  
    .subscribe((sourceData) =&amp;gt; {  
      const newRestaurant = sourceData.value.data.onCreateRestaurant  
      if (newRestaurant) {  
        // skip our own mutations and duplicates  
        if (this.restaurants.some(r =&amp;gt; r.id == newRestaurant.id)) return;  
        this.restaurants = [newRestaurant, ...this.restaurants];  
      }   
    });  
  },  
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We use &lt;code&gt;created&lt;/code&gt;to setup the subscription and immediately &lt;code&gt;subscribe&lt;/code&gt; to start listening for notifications. Then for each notification, we will update our list of restaurants with changes.&lt;/p&gt;

&lt;h1&gt;
  
  
  Publishing your app via the AWS Amplify Console
&lt;/h1&gt;

&lt;p&gt;The first thing you need to do is &lt;strong&gt;create a new repo&lt;/strong&gt; for this project. Once you’ve created the repo, copy the URL for the project to the clipboard and initialise git in your local project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git init  
git remote add origin [repo@repoofyourchoice.com](mailto:repo@repoofyourchoice.com):username/project-name.git  
git add .git commit -m 'initial commit'git push origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next visit the &lt;a href="https://aws.amazon.com/amplify/console/" rel="noopener noreferrer"&gt;&lt;strong&gt;AWS Amplify Console&lt;/strong&gt;&lt;/a&gt; in your &lt;strong&gt;AWS account&lt;/strong&gt;. Click &lt;strong&gt;Get Started&lt;/strong&gt; to create a new deployment. Next, authorise your repository provider as the repository service. Next, choose the new repository and branch for the project you just created and click &lt;strong&gt;Next&lt;/strong&gt;. In the next screen, create a new role and use this role to allow the &lt;strong&gt;AWS Amplify Console&lt;/strong&gt; to deploy these resources and click &lt;strong&gt;Next&lt;/strong&gt;. Finally, click &lt;strong&gt;Save&lt;/strong&gt; and &lt;strong&gt;Deploy&lt;/strong&gt; to deploy your application!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1uv18ced5zf4hwpxqv5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1uv18ced5zf4hwpxqv5.png" alt="Image for post" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AWS Amplify Console deployment steps.&lt;/p&gt;

&lt;h1&gt;
  
  
  Cleaning up cloud services
&lt;/h1&gt;

&lt;p&gt;If at any time, you would like to delete a service from your project and your &lt;strong&gt;AWS Account&lt;/strong&gt;, you can do this by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify delete
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Congratulations! You successfully built your first &lt;strong&gt;GraphQL API&lt;/strong&gt; using &lt;strong&gt;Vue&lt;/strong&gt; and &lt;strong&gt;AWS AppSync&lt;/strong&gt;. Thanks for following this tutorial.&lt;/p&gt;

&lt;p&gt;If you prefer, you can follow the instructions in this video to build the same app but deploying to &lt;strong&gt;Amazon Cloudfront&lt;/strong&gt; and &lt;strong&gt;Amazon S3&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/CAueVfEYn6s"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h1&gt;
  
  
  Thanks for reading!
&lt;/h1&gt;

&lt;p&gt;Have you got any questions regarding this tutorial or &lt;strong&gt;AWS Amplify&lt;/strong&gt;? Feel free to reach out to me anytime at &lt;a href="https://twitter.com/intent/user?screen_name=gerardsans" rel="noopener noreferrer"&gt;@gerardsans&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7uedkcfqzn3p8hbnb3wl.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7uedkcfqzn3p8hbnb3wl.jpeg" alt="Image for post" width="360" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;My Name is &lt;a href="https://twitter.com/gerardsans" rel="noopener noreferrer"&gt;Gerard Sans&lt;/a&gt;. I am a Developer Advocate at &lt;a href="https://aws.amazon.com/products/mobile" rel="noopener noreferrer"&gt;AWS Mobile&lt;/a&gt; working with &lt;a href="https://aws-amplify.github.io/" rel="noopener noreferrer"&gt;AWS Amplify&lt;/a&gt; and &lt;a href="https://aws.amazon.com/appsync/" rel="noopener noreferrer"&gt;AWS AppSync&lt;/a&gt; teams.&lt;br&gt;
GraphQL is an open source data query and manipulation language for APIs, and a runtime for fulfilling queries with existing data.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>aws</category>
      <category>amplify</category>
      <category>vue</category>
      <category>graphql</category>
    </item>
    <item>
      <title>Build your first full-stack serverless app with Vue and AWS Amplify</title>
      <dc:creator>gerard-sans</dc:creator>
      <pubDate>Tue, 22 Sep 2020 12:57:56 +0000</pubDate>
      <link>https://dev.to/aws/build-your-first-full-stack-serverless-app-with-vue-and-aws-amplify-14k4</link>
      <guid>https://dev.to/aws/build-your-first-full-stack-serverless-app-with-vue-and-aws-amplify-14k4</guid>
      <description>&lt;p&gt;Build flexible, scalable, and reliable apps with AWS Amplify&lt;/p&gt;




&lt;p&gt;In this tutorial, you will learn how to build a full-stack serverless app using &lt;strong&gt;Vue&lt;/strong&gt; and &lt;strong&gt;AWS Amplify&lt;/strong&gt;. You will create a new project and add a full authorisation flow using the &lt;strong&gt;authenticator component&lt;/strong&gt;. This includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Introduction to &lt;strong&gt;AWS Amplify&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Setting up a new project with the &lt;strong&gt;Vue CLI&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Installing &lt;strong&gt;Amplify CLI&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Adding &lt;strong&gt;authentication&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Publishing&lt;/strong&gt; your app&lt;/li&gt;
&lt;li&gt;Cleaning up &lt;strong&gt;cloud services&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please let me know if you have any questions or want to learn more on the above at &lt;a href="https://twitter.com/intent/user?screen_name=gerardsans" rel="noopener noreferrer"&gt;@gerardsans&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction to AWS Amplify
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Amplify&lt;/strong&gt; makes developing, releasing and operating modern full-stack serverless apps easy and delightful. Mobile and frontend web developers are being supported throughout the app life cycle via an open source &lt;strong&gt;Amplify Framework&lt;/strong&gt; (consisting of the Amplify libraries and Amplify CLI) and seamless integrations with &lt;strong&gt;AWS cloud services&lt;/strong&gt;, and the &lt;strong&gt;AWS Amplify Console&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Amplify libraries&lt;/strong&gt;: in this article we will be using &lt;code&gt;aws-amplify&lt;/code&gt; and &lt;code&gt;@aws-amplify/ui-vue&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Amplify CLI&lt;/strong&gt;: command line tool for configuring and integrating cloud services.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;UI components&lt;/strong&gt;: authenticator, photo picker, photo album and chat bot.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Cloud services&lt;/strong&gt;: authentication, storage, analytics, notifications, AWS Lambda functions, REST and GraphQL APIs, predictions, chat bots and extended reality (AR/VR).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Offline-first support&lt;/strong&gt;: Amplify DataStore provides a programming model for leveraging shared and distributed data without writing additional code for data reconciliation between offline and online scenarios.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By using AWS Amplify, teams can focus on development while the Amplify team enforces best patterns and practices throughout the AWS Amplify stack.&lt;/p&gt;

&lt;h1&gt;
  
  
  Amplify CLI
&lt;/h1&gt;

&lt;p&gt;The &lt;strong&gt;Amplify CLI&lt;/strong&gt; provides a set of commands to help with repetitive tasks and automating &lt;strong&gt;cloud service&lt;/strong&gt; setup and provision.&lt;/p&gt;

&lt;p&gt;Some commands will prompt questions and provide sensible defaults to assist you during its execution. These are some common tasks. Run:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;amplify init&lt;/code&gt;, to setup a new environment. Eg: dev, test, dist.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;amplify push&lt;/code&gt;, to provision local resources to the cloud.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;amplify status&lt;/code&gt;, to list local resources and their current status.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;The&lt;/em&gt; &lt;strong&gt;&lt;em&gt;Amplify CLI&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;uses&lt;/em&gt; &lt;strong&gt;&lt;em&gt;AWS CloudFormation&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;to manage service configuration and resource provisioning via&lt;/em&gt; &lt;strong&gt;&lt;em&gt;templates&lt;/em&gt;&lt;/strong&gt;&lt;em&gt;. This a declarative and atomic approach to configuration. Once a template is executed, it will either fail or succeed.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Setting up a new project with the Vue CLI
&lt;/h1&gt;

&lt;p&gt;To get started, create a new project using the &lt;a href="https://cli.vuejs.org/" rel="noopener noreferrer"&gt;Vue CLI&lt;/a&gt;. If you already have it, skip to the next step. If not, install it and create the app using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn global add @vue/cli  
vue create amplify-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate to the new directory and check everything checks out before continuing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd amplify-app  
yarn serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;p&gt;Before going forward make sure you have gone through the &lt;a href="https://docs.amplify.aws/start/getting-started/installation/q/integration/vue" rel="noopener noreferrer"&gt;instructions in our docs&lt;/a&gt; to sign up to your &lt;strong&gt;AWS Account&lt;/strong&gt; and install and configure the &lt;strong&gt;Amplify CLI&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setting up your Amplify project
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;AWS Amplify&lt;/strong&gt; allows you to create different environments to define your preferences and settings. For any new project you need to run the command below and answer as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  Enter a name for the project: &lt;strong&gt;amplify-app&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Enter a name for the environment: &lt;strong&gt;dev&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Choose your default editor: &lt;strong&gt;Visual Studio Code&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Please choose the type of app that you’re building &lt;strong&gt;javascript&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  What javascript framework are you using &lt;strong&gt;vue&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Source Directory Path: &lt;strong&gt;src&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Distribution Directory Path: &lt;strong&gt;dist&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Build Command: &lt;strong&gt;npm run-script build&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Start Command: &lt;strong&gt;npm run-script serve&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Do you want to use an AWS profile? &lt;strong&gt;Yes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Please choose the profile you want to use &lt;strong&gt;default&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this point, the &lt;strong&gt;Amplify CLI&lt;/strong&gt; has initialised a new project and a new folder: &lt;strong&gt;amplify&lt;/strong&gt;. The files in this folder hold your project configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;amplify-app&amp;gt;  
    |\_ amplify  
      |\_ .config  
      |\_ #current-cloud-backend  
      |\_ backend  
      team-provider-info.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Installing the AWS Amplify dependencies
&lt;/h1&gt;

&lt;p&gt;Install the required dependencies for &lt;strong&gt;AWS Amplify&lt;/strong&gt; and &lt;strong&gt;Vue&lt;/strong&gt; using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;yarn add aws-amplify @aws-amplify/ui-vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Adding authentication
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;AWS Amplify&lt;/strong&gt; provides authentication via the &lt;code&gt;auth&lt;/code&gt; category which gives us access to &lt;strong&gt;AWS Cognito&lt;/strong&gt;. To add authentication use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify add auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When prompted choose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Do you want to use default authentication and security configuration?: &lt;strong&gt;Default configuration&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  How do you want users to be able to sign in when using your Cognito User Pool?: &lt;strong&gt;Username&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Do you want to configure advanced settings? &lt;strong&gt;No&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Pushing changes to the cloud
&lt;/h1&gt;

&lt;p&gt;By running the push command, the cloud resources will be provisioned and created in your &lt;strong&gt;AWS account&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To quickly check your newly created &lt;strong&gt;Cognito User Pool&lt;/strong&gt; you can run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;To access the&lt;/em&gt; &lt;strong&gt;&lt;em&gt;AWS Cognito Console&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;at any time, go to the dashboard at&lt;/em&gt; &lt;a href="https://console.aws.amazon.com/cognito/" rel="noopener noreferrer"&gt;&lt;em&gt;https://console.aws.amazon.com/cognito&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. Also be sure that your region is set correctly.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Your resources have been created and you can start using them!&lt;/p&gt;

&lt;h1&gt;
  
  
  Configuring the Vue application
&lt;/h1&gt;

&lt;p&gt;Reference the auto-generated &lt;code&gt;aws-exports.js&lt;/code&gt; file that is now in your &lt;code&gt;src&lt;/code&gt; folder. To configure the app, open &lt;code&gt;main.ts&lt;/code&gt; and add the following code below the last import:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Vue&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;  
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;  

&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Amplify&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-amplify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@aws-amplify/ui-vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;_exports&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./aws-exports&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  

&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;Amplify&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;aws&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;_exports&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  

&lt;span class="nx"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productionTip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;  

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Vue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;  
  &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;h&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;  
&lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;$mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Using the Authenticator Component
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;AWS Amplify&lt;/strong&gt; provides &lt;strong&gt;UI components&lt;/strong&gt; that you can use in your app. Let’s add these components to the project&lt;/p&gt;

&lt;p&gt;In order to use the &lt;strong&gt;authenticator component&lt;/strong&gt; add it to &lt;code&gt;src/App.vue&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;amplify&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;authenticator&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; 
&lt;span class="o"&gt;+&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Hey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;!&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;amplify&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;sign&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/amplify-sign-out&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt;&lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/amplify-authenticator&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&amp;gt; &lt;/span&gt;&lt;span class="err"&gt; 
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/template&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AuthState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onAuthUIStateChange&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@aws-amplify/ui-components&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
  &lt;span class="nf"&gt;data&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt;      &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;  
  &lt;span class="p"&gt;},&lt;/span&gt;  
  &lt;span class="nf"&gt;created&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="c1"&gt;// authentication state managament  &lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="nf"&gt;onAuthUIStateChange&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt;      &lt;span class="c1"&gt;// set current user and load data after login  &lt;/span&gt;
&lt;span class="o"&gt;+&lt;/span&gt;      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;AuthState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SignedIn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt;        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt;      &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="o"&gt;+&lt;/span&gt;    &lt;span class="p"&gt;})&lt;/span&gt; 
  &lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can run the app and see that an &lt;strong&gt;authentication flow&lt;/strong&gt; has been added in front of your &lt;strong&gt;app&lt;/strong&gt; &lt;strong&gt;component&lt;/strong&gt;. This flow gives users the ability to sign up and sign in.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;To view any users that were created, go back to the&lt;/em&gt; &lt;strong&gt;&lt;em&gt;Cognito Dashboard&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;at&lt;/em&gt; &lt;a href="https://console.aws.amazon.com/cognito/" rel="noopener noreferrer"&gt;&lt;em&gt;https://console.aws.amazon.com/cognito&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. Also be sure that your region is set correctly.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Alternatively you can also use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify console auth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Accessing User Data
&lt;/h1&gt;

&lt;p&gt;To access the user’s info using the Auth API. This will return a &lt;strong&gt;promise&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Auth&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-amplify&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;Auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;currentAuthenticatedUser&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Publishing your app
&lt;/h1&gt;

&lt;p&gt;To deploy and host your app on AWS, we can use the &lt;code&gt;hosting&lt;/code&gt; category.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify add hosting
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  Select the plugin module to execute: &lt;strong&gt;Amazon CloudFront and S3&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  Select the environment setup: &lt;strong&gt;DEV&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  hosting bucket name &lt;strong&gt;YOURBUCKETNAME&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  index doc for the website &lt;strong&gt;index.html&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;  error doc for the website &lt;strong&gt;index.html&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, everything is set up &amp;amp; we can publish it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Cleaning up Services
&lt;/h1&gt;

&lt;p&gt;To wipe out all resources from your project and your &lt;strong&gt;AWS Account&lt;/strong&gt;, you can do this by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amplify delete
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Congratulations! You successfully built your first &lt;strong&gt;full-stack serverless app&lt;/strong&gt; using &lt;strong&gt;Vue&lt;/strong&gt; and &lt;strong&gt;AWS Amplify&lt;/strong&gt;. Thanks for following this tutorial.&lt;/p&gt;

&lt;p&gt;You have learnt how to provide an &lt;strong&gt;authentication flow&lt;/strong&gt; using the &lt;strong&gt;authenticator component&lt;/strong&gt; or via the &lt;strong&gt;service API&lt;/strong&gt; and how to use &lt;strong&gt;Amplify CLI&lt;/strong&gt; to execute common tasks including adding and removing services.&lt;/p&gt;

&lt;h1&gt;
  
  
  Thanks for reading!
&lt;/h1&gt;

&lt;p&gt;Have you got any questions regarding this tutorial or &lt;strong&gt;AWS Amplify&lt;/strong&gt;? Feel free to reach out to me anytime at &lt;a href="https://twitter.com/intent/user?screen_name=gerardsans" rel="noopener noreferrer"&gt;@gerardsans&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7uedkcfqzn3p8hbnb3wl.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7uedkcfqzn3p8hbnb3wl.jpeg" alt="Image for post" width="360" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;My Name is &lt;a href="https://twitter.com/gerardsans" rel="noopener noreferrer"&gt;Gerard Sans&lt;/a&gt;. I am a Developer Advocate at &lt;a href="https://aws.amazon.com/products/mobile" rel="noopener noreferrer"&gt;AWS Mobile&lt;/a&gt; working with &lt;a href="https://aws-amplify.github.io/" rel="noopener noreferrer"&gt;AWS Amplify&lt;/a&gt; and &lt;a href="https://aws.amazon.com/appsync/" rel="noopener noreferrer"&gt;AWS AppSync&lt;/a&gt; teams.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>aws</category>
      <category>amplify</category>
      <category>vue</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
