{"id":13533413,"url":"https://github.com/amazon-archives/wild-rydes-mobile","last_synced_at":"2025-04-01T21:32:16.833Z","repository":{"id":141667592,"uuid":"127942196","full_name":"amazon-archives/wild-rydes-mobile","owner":"amazon-archives","description":"Learn serverless mobile cloud computing with this fictional unicorn ride-sharing app.","archived":true,"fork":false,"pushed_at":"2018-07-21T17:31:09.000Z","size":122847,"stargazers_count":37,"open_issues_count":10,"forks_count":35,"subscribers_count":13,"default_branch":"intro-to-aws-mobile","last_synced_at":"2024-05-21T13:59:10.695Z","etag":null,"topics":["aws-amplify","cognito","lambda","react","react-native","reactjs","serverless"],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/amazon-archives.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2018-04-03T17:12:58.000Z","updated_at":"2023-09-25T08:31:22.000Z","dependencies_parsed_at":"2024-01-14T02:18:37.535Z","dependency_job_id":"67acf291-7d89-41a7-ae0a-233df667af44","html_url":"https://github.com/amazon-archives/wild-rydes-mobile","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amazon-archives%2Fwild-rydes-mobile","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amazon-archives%2Fwild-rydes-mobile/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amazon-archives%2Fwild-rydes-mobile/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/amazon-archives%2Fwild-rydes-mobile/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/amazon-archives","download_url":"https://codeload.github.com/amazon-archives/wild-rydes-mobile/tar.gz/refs/heads/intro-to-aws-mobile","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246713369,"owners_count":20821877,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws-amplify","cognito","lambda","react","react-native","reactjs","serverless"],"created_at":"2024-08-01T07:01:19.620Z","updated_at":"2025-04-01T21:32:16.501Z","avatar_url":"https://github.com/amazon-archives.png","language":null,"funding_links":[],"categories":["Example Projects"],"sub_categories":["Other blogs \u0026 tutorials"],"readme":"# AWS Mobile Loft - Introduction to AWS Mobile\n\n## 🤖 Getting started\n\nTo get started, we will first create a new React application using the Create React App CLI.\n\n\u003e If you do not already have Creeate React App installed, install it now with the following command:\n\n```\nnpm install -g create-react-app\n```\n\n#### Creating the app\n\n```\ncreate-react-app react-aws-app\n```\n\n#### Running the app\n\nFirst, change into the new directory of the app we just created.\n\n```bash\ncd react-aws-app\n```\n\nNext, run the following command to launch the app in the web browser:\n\n```bash\nnpm start\n```\n\n## 🤖 Lesson 1 - Introduction to AWS Mobile Hub \u0026 the AWS Mobile CLI\n\nInstalling \u0026 configuring a new mobile hub project.\n\n#### ⚡ Installing the AWS Mobile CLI\n\n```\nnpm i -g awsmobile-cli\n```\n\n#### ⚡ Configuring the CLI\n\n```\nawsmobile configure\n```\n\nIf you need to get an __accessKeyId__ \u0026 __secretAccessKey__:\n1. Visit the [IAM Console](https://console.aws.amazon.com/iam/home).\n2. Click __Users__ in left hand menu.\n3. Click __Add User__.\n4. Give the user a name \u0026 choose __programatic access__ as the access type \u0026 click next.\n5. Click __Create Group__.\n6. Give the group a name \u0026 choose __Administrator Access__ as the access type \u0026 click __Create Group__.\n7. Click __Next__ \u0026 click __Create User__.\n8. Copy the __accessKeyId__ \u0026 __secretAccessKey__ to the terminal to configure the CLI.\n\n#### ⚡ Creating a new Project\n\n```\nawsmobile init\n```\n\nAfter running the above command you will have a few options:\n\n- Choose default for source directory\n- Choose default for project's distribution directory\n- Choose default for build command\n- Choose default for project's start command\n- Give the project a name of __AmplifyReact__\n\n\nNow that the project is successfully created, we can view it in the AWS Console by running the following command:\n\n```bash\nawsmobile console\n```\n\n## 🤖 Lesson 2 - Integrating AWS \u0026 AWS Amplify into your React application\n\nIn this section, we'll first integrate our AWS Mobile Hub project in with our newly created React application using the [AWS Amplify](https://aws-amplify.github.io/amplify-js/media/developer_guide) library.    \n\nWe'll also learn how to add a new service, [Amazon Cognito](https://aws.amazon.com/cognito/), to our existing AWS Mobile Hub project using the CLI. Finally, we'll implement Authentication into the application using Amazon Cognito with AWS Amplify.\n\n#### ⚡ Configuring the project with `Amplify` \u0026 `aws-exports.js`\n\n1. Open __src/index.js__\n2. Add the following code below the last `import` statement\n\n```js\n// src/index.js\nimport Amplify from 'aws-amplify'\nimport config from './aws-exports'\nAmplify.configure(config)\n```\n\n#### ⚡ Adding a new service - User Signin with Amazon Cognito\n\n1. Add the new User Signin functionality using the CLI\n\n```bash\nawsmobile user-signin enable\n```\n\n2. Push the new configuration to the Mobile Hub Console\n\n```bash\nawsmobile push\n```\n\n3. To view the console, run the following command:\n\n```bash\nawsmobile console\n```\n\nNow, in the list of __Backend__ services, we see that __User Signin__ is now enabled.\n\n#### ⚡ Implementing User-signup \u0026 User-signin using the `withAuthenticator` HOC\n\n1. Open src/App.js\n\n2. Import the `withAuthenticator` HOC from `aws-amplify-react`\n\n```js\n// src/App.js\n\nimport { withAuthenticator } from 'aws-amplify-react'\n```\n\n3. Wrap the App export with the `withAuthenticator` HOC\n\n```js\nexport default withAuthenticator(App)\n```\n\n#### ⚡ Introduction to implementing hand-rolled Authentication \n\nAWS Amplify Auth category has over 30 different methods available, including `signUp`, `confirmSignUp`, `signIn`, `confirmSignIn`, `changePassword`, `forgotPassword` \u0026 many many others. You can view the entire API [here](https://aws-amplify.github.io/amplify-js/api/classes/authclass.html).\n\nTo manually sign up a new User with our existing Amazon Cognito configuration, we can call `Auth.signUp`, \u0026 must provide the following parameters:\n\n- username`\u003cstring\u003e`\n- password`\u003cstring\u003e`\n- attributes`\u003cobject\u003e`\n  - email`\u003cstring\u003e`\n  - phone_number`\u003cstring\u003e`\n\nWe would call some method, passing in the above info to `Auth.signUp`. In React, it could look something like this:\n\n```js\nimport { Auth } from 'aws-amplify'\n\nsignUpUser = () =\u003e {\n  const { username, password, email, phone_number } = this.state\n  Auth.signUp({\n    username, password, attributes: { email, phone_number }\n  })\n  .then(success =\u003e console.log('successfully signed up user!: ', success))\n  .catch(err =\u003e console.log('error signing up user: ', err))\n}\n```\n\nThis Sign Up would trigger an __MFA__ using the provided phone number.\n\nTo handle __MFA__ on user sign up \u0026 sign in, we can use `confirmSignUp` \u0026 `confirmSignIn`.\n\nTo see how to build a custom UI using the Auth class, check out [this](https://aws-amplify.github.io/amplify-js/media/authentication_guide#sign-in) section of the documentation.\n\n## 🤖 Lesson 3 - Adding an AWS Lambda Function\n\nIn this section, we'll see how to add a new Lambda function to our application. We'll then learn how to make changes to the Lambda function \u0026 push the new changes to our Mobile Hub console.\n\n#### ⚡ Creating a new Lambda Function using the CLI\n\n1. Run the following command to create a new Lambda function:\n\n```bash\nawsmobile cloud-api enable -p\n```\n\n2. Choose the following options:\n\n- Create a new API\n- API name: __PetAPI__\n- HTTP path name: __/pets__\n- Here, choose default Lambda function name by hitting enter on your keyboard\n- Add another HTTP path: __n__\n\n#### ⚡ Interacting with the Lambda function using AWS Amplify\n\n1. In src/App.js, add the following below the last import\n\n```js\n// src/App.js\nimport { API } from 'aws-amplify'\n\nlet apiName = 'PetAPI';\nlet path = '/pets';\n```\n\n2. In the App component add a new `componentDidMount` lifecycle method to log out the returned data from the API.\n\n```js\nasync componentDidMount() {\n  const data = await API.get(apiName, path)\n  console.log('data: ', data)\n}\n```\n\nNow, we should be able to run the app and see some information passed back to us from the API.\n\nTo see what is going on here, open the following file: `awsmobilejs/backend/cloud-api/PetAPI/app.js`\n\nHere, we can see that the Lamdba function is running an express server, handling various paths. If we look at the `app.get('/pets/'` path, we see that for right now it is returning `res.json(req.apiGateway.event);`\n\nLet's update this to return an array of pets.\n\n#### ⚡ Updating the Lambda function\n\n1. Update the `app.get('/pets/'` path to the following:\n\n```js\napp.get('/pets', function(req, res) {\n  const pets = [\n    'Buster', 'Mary', 'Spike', 'Pebbles'\n  ]\n  res.json({\n    data: pets\n  });\n});\n```\n\n2. Push the new code to Mobile Hub:\n\n```bash\nawsmobile push\n```\n\n3. Rerun the app\n\n```bash\nnpm start\n```\n\n#### ⚡ Rendering the list of pets from the API in the UI\n\nNext, we want to render the data being returned from the API. To do so, we'll create some state in the component to hold the data. Then, once the data is returned from the API, we'll reset the state, passing in the new data.\n\n1. Create state in the component\n\n```js\nstate = {\n  pets: []\n}\n```\n\n2. Change `componentDidMount` to set the state when the data is returned.\n\n```js\nasync componentDidMount() {\n  const data = await API.get(apiName, path)\n  console.log('data: ', data)\n  this.setState({\n    pets: data.data\n  })\n}\n```\n\n3. Finally, add the following code to your render method to display the list of pets in the UI:\n\n```js\n{\n  this.state.pets.map((pet, index) =\u003e (\n    \u003ch2 key={index}\u003e{pet}\u003c/h2\u003e\n  ))\n}\n```\n\n## 🤖 Lesson 4 - Adding Analytics with [Amazon Pinpoint](https://aws.amazon.com/pinpoint/)\n\nNext, we'd like to add analytics to the app!\n\nWhen we created the new Mobile Hub project, the initial configuration has Pinpoint enabled by default so we do not need to do anything add the service, we can just start using it.\n\nThe will be using the `Analytics` API from AWS Amplify to interact with Pinpoint \u0026 to log analytics.\n\nAnalytics can take the following arguments:\n\n```js\n// 1. only the event name\nAnalytics.record({ name: 'Add to cart button clicked' })\n\n// 2. event name \u0026 some attributes\nAnalytics.record({ name: 'Added socks to shopping cart', attributes: { username: 'amanda33' }})\n\n// 3. event name, attributes, \u0026 metrics\nAnalytics.record({ name: 'Added socks to shopping cart', attributes: { username: 'amanda33' }, metrics: { time: '8:33pm ET' } })\n```\n\n#### ⚡ Recording an Analytics event\n\nLet's create a button that records an event.\n\nIn src/App.js, import the `Analytics` module:\n\n```js\n// src/App.js\nimport { Analytics } from 'aws-amplify'\n```\n\nNext, add the following method to the class:\n\n```js\naddToCart = () =\u003e {\n  console.log('Simulating adding item to cart.')\n  Analytics.record('Item added to cart!')\n}\n```\n\nNow, create a button in the render method \u0026 attach the method to the onClick function of the button:\n\n```js\n\u003cbutton onClick={this.addToCart}\u003eAdd To Cart\u003c/button\u003e\n```\n\nNow, click on the button a couple of times. We should now be able to see the data from this event logged into our Pinpoint console.\n\n#### ⚡ Viewing Analytics events \u0026 data in the Pinpoint console\n\nNext, let's view the Pinpoint console to see the events we've logged so far.\n\n1. Open the AWS Mobile Hub console\n\n```bash\nawsmobile console\n```\n\n2. Click __Analytics__ in the top right hand corner\n\n3. Click on __Events__ in the left menu\n\n\n## 🤖 Lesson 5 - Adding GraphQL with AWS AppSync\n\nNext, we would like to add a AWS AppSync GraphQL API to the application.\n\n#### ⚡ Creating the API\n\nWe can create the new API from the command line:\n\n```bash\nawsmobile appsync enable -p\n```\n\nNext, choose __API_KEY__ as the __auth type__.\n\nNow, push the new configuration to AWS Mobile Hub:\n\n```bash\nawsmobile push\n```\n\nNow that the API has been created, let's go into the AWS console to update the configuration.\n\nVisit the AWS AppSync console at [https://console.aws.amazon.com/appsync/](https://console.aws.amazon.com/appsync/).\n\nFromt here, click on the __AmplifyReact__ API to open it in the console.\n\n#### ⚡ Configuring the API\n\nNow we need to update the existing schema to our new schema.\n\nClick on __Schema__ in the left hand menu to open the schema editor.\n\nHere, delete the existing schema and add the following, then click __Save Schema__:\n\n```js\ntype Pet {\n  id: ID!\n  name: String!\n}\n\ntype Query {\n  fetchPet(id: ID!): Pet\n}\n```\n\nNext, click on the __Create Resources__ button in the top right corner.\n\nWhen asked to __Define or select a type__, choose __Use existing type__, and then choose the Pet type. Then scroll down \u0026 click __Create__.\n\nOnce the resources have finished being created, we can start executing mutations against the API.\n\nIn the left hand menu, click on __Queries__, \u0026 add the following mutation into the query editor, then click the orange play button:\n\n```graphql\nmutation create {\n  createPet(input:{\n    name: \"Spike\"\n  }) {\n    id\n  }\n}\n```\n\n\u003e Feel free to create as many Pets as you would like, as we will be querying for this data in just a moment.\n\nIf you would like to query the data to make sure everything is working properly, try using this query in the query editor:\n\n```graphql\nquery list {\n  listPets {\n    items {\n      id\n      name\n    }\n  }\n}\n```\n\n#### ⚡ Connecting the React application to the AWS AppSync API\n\nNow that the API is created \u0026 working properly, let's go ahead and query for data from the client \u0026 show it in the UI.\n\nIn src/App.js, let's go ahead and import __API__ \u0026 __graphqlOperation__ from 'aws-amplify':\n\n```js\n// src/App.js\nimport { API, graphqlOperation } from 'aws-amplify'\n```\n\nNext, we'll define our query:\n\n```js\nconst ListPets = `\n  query {\n    listPets {\n      items {\n        id\n        name\n      }\n    }\n  }\n`\n```\n\nNow, in the class, we'll define some state, and set a pets property equal to an empty array for now:\n\n```js\nstate = { pets: [] }\n```\n\nNow that we have some initial state, we'll call the AppSync API to fetch the data within the `componentDidMount` lifecycle hook:\n\n```js\nasync componentDidMount() {\n  const pets = await API.graphql(graphqlOperation(ListPets))\n  console.log('pets: ', pets) // optional, if you would like to view the shape of the data\n  this.setState({ pets: pets.data.listPets.items })\n}\n```\n\nIn the render method, we can now display the data to the UI:\n\n```js\n{\n  this.state.pets.map((pet, index) =\u003e (\n    \u003ch2 key={index}\u003e{pet.name}\u003c/h2\u003e\n  ))\n}\n```\n\nThe final component code for querying the AWS AppSync API should look like this:\n\n```js\nimport React, { Component } from 'react';\nimport logo from './logo.svg';\nimport './App.css';\n\nimport { API, graphqlOperation } from 'aws-amplify'\n\nconst ListPets = `\n  query {\n    listPets {\n      items {\n        id\n        name\n      }\n    }\n  }\n`\n\nclass App extends Component {\n  state = { pets: [] }\n  async componentDidMount() {\n    const pets = await API.graphql(graphqlOperation(ListPets))\n    console.log('pets: ', pets)\n    this.setState({ pets: pets.data.listPets.items })\n  }\n  render() {\n    return (\n      \u003cdiv className=\"App\"\u003e\n        \u003cheader className=\"App-header\"\u003e\n          \u003cimg src={logo} className=\"App-logo\" alt=\"logo\" /\u003e\n          \u003ch1 className=\"App-title\"\u003eWelcome to React\u003c/h1\u003e\n        \u003c/header\u003e\n        \u003cp className=\"App-intro\"\u003e\n          To get started, edit \u003ccode\u003esrc/App.js\u003c/code\u003e and save to reload.\n        \u003c/p\u003e\n        {\n          this.state.pets.map((pet, index) =\u003e (\n            \u003ch2 key={index}\u003e{pet.name}\u003c/h2\u003e\n          ))\n        }\n      \u003c/div\u003e\n    );\n  }\n}\n\nexport default App;\n```\n\n#### ⚡ Creating a mutation\n\nFirst, we need to create a mutation:\n\n```js\nconst CreatePet = `\n  mutation($name: String!) {\n    createPet(input: {\n      name: $name\n    }) {\n      id\n    }\n  }\n`\n```\n\nNow we need to store some state in the class to keep up with user input:\n\n```js\nstate = { name: '', pets: [] }\n```\n\nNext, we'll create an `onChange` class method that will handle user input, storing it in the state:\n\n```js\nonChange = (e) =\u003e { this.setState({ name: e.target.value }) }\n```\n\nNow, we'll create a class method that will call the API to create the mutation:\n\n```js\ncreatePet = () =\u003e {\n  const pet = { name: this.state.name }\n  API.graphql(graphqlOperation(CreatePet, pet))\n  const pets = [...this.state.pets, pet]\n  this.setState({ pets, name: '' })\n}\n```\n\nFinally, in the render method we'll create a button \u0026 input form to work with the new methods:\n\n```js\n\u003cinput onChange={this.onChange} placeholder='Pet name' /\u003e\n\u003cbutton onClick={this.createPet}\u003eCreate Pet\u003c/button\u003e\n```\n\n## Deleting resources\n\nThroughout this tutorial, we've created a few resources in your AWS account. If you are interested in removing any resources you will not be using in the future, here are the resources you should delete around this project:\n\n1. In Mobile hub, delete the new project we created here\n2. In Amazon s3, delete the bucket associated with this project\n3. In AWS AppSync, delete the API we created along with this project\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famazon-archives%2Fwild-rydes-mobile","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Famazon-archives%2Fwild-rydes-mobile","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Famazon-archives%2Fwild-rydes-mobile/lists"}