<section class="blog-post-content"><p>AWS Amplify is the fastest and easiest way to build cloud-powered mobile and web apps on AWS. Amplify comprises a set of tools and services that enables front-end web and mobile developers to leverage the power of AWS services to build innovative and feature-rich applications.</p><p>Chrome extensions are a great way to build mini applications that utilize the browser functionality to serve content to users. These extensions provide the means for additional functionality by allowing ways to configure and embed information into a webpage. When combining the power of AWS cloud-based services and Chrome browser functionality, we can customize applications to increase productivity and decrease development time.</p><h2><strong>Chrome extension</strong></h2><p>The following example outlines a use case of adding an extension to a specific URL/webpage. This allows users who are using the extension to add images. For example, if we would like to take a screenshot of text or activities on the page that allows users to store the images, then the user has a catalog of images that they can refer back to upon revisiting the page. The extension harnesses the Amplify-provided resource by adding an <a href="https://aws.amazon.com/s3/" target="_blank" rel="noopener noreferrer">Amazon Simple Storage Service (Amazon S3)</a> bucket to store the images and Amplify UI component to display the images.</p><div id="attachment_8696" class="wp-caption aligncenter c4"><img aria-describedby="caption-attachment-8696" class="wp-image-8696" src="https://d2908q01vomqb2.cloudfront.net/0a57cb53ba59c46fc4b692527a38a87c78d84028/2022/09/15/extension.gif" alt="A GIF that shows the final demonstration of the Chrome extension that displays the image of a cat" width="500" height="244" /><p id="caption-attachment-8696" class="wp-caption-text">A GIF that shows the final demonstration of the Chrome extension that displays the image of a cat</p></div><p>The application utilizes the latest chrome manifest V3 to create an extension, and it’s developed using the React JavaScript library with Amplify resources to provide functionality.</p><p>The Chrome extension manifest is an entry point that contains three main components.</p><ol><li>The Popup scripts</li><li>Content scripts</li><li>Background scripts</li></ol><p>The Popup scripts are elements visible to the user when they select an extension. Content scripts are elements that run in a web page that let us make, modify, or add functionality to the web pages. Background scripts or service workers are event-based programs that let us monitor and send messages to other scripts.</p><p>In this application, we’ll be utilizing the Content script to modify a web page by adding an upload button and display an image.</p><p>For detailed information refer to the <a href="https://developer.chrome.com/docs/extensions/mv3/getstarted/" target="_blank" rel="noopener noreferrer">Chrome Documentation</a>.</p><h2><strong>AWS Amplify</strong></h2><p>AWS Amplify is a set of purpose-built tools and features that lets frontend web and mobile developers quickly and easily build full-stack applications on AWS. This also includes the flexibility to leverage the breadth of AWS services as your use cases evolve.</p><p>The Amplify Command Line Interface (CLI) is a unified toolchain to create, integrate, and manage the AWS cloud services for your app.</p><p>We’ll utilize <a href="https://docs.amplify.aws/cli/" target="_blank" rel="noopener noreferrer">Amplify CLI</a> to add Amazon S3 storage and Authentication capabilities. Additionally, we’ll use<a href="https://ui.docs.amplify.aws/"> Amplify UI</a> components to add a picker component.</p><h2><strong>Architecture</strong></h2><div id="attachment_8723" class="wp-caption aligncenter c5"><img aria-describedby="caption-attachment-8723" class="wp-image-8723" src="https://d2908q01vomqb2.cloudfront.net/0a57cb53ba59c46fc4b692527a38a87c78d84028/2022/09/26/architecture-2.jpg" alt="The Architecture diagram for the Amplify application showing the interaction with the S3 bucket and Chrome scripts" width="400" height="770" /><p id="caption-attachment-8723" class="wp-caption-text">Figure 1. The Architecture diagram for the Amplify application showing the interaction with the S3 bucket and Chrome scripts</p></div><h2><strong>Walkthrough</strong></h2><p>In this application we create a post build script that modifies the manifest file on each build. The post build script copies the file names of JS and CSS files needed for the content script to append HTML elements to a page.</p><p>The following information outlines the steps needed in creating an Amplify chrome extension:</p><ul><li>Create a React project and install the necessary packages</li><li>Create a Post build script and Manifest</li><li>Add Amplify resources</li><li>Add code to inject the HTML elements</li><li>Test the application in the Chrome browser</li></ul><p>Find the GitHub repository <a href="https://github.com/ykethan/Amplify-Chrome-extension" target="_blank" rel="noopener noreferrer">here</a>.</p><h3>Prerequisites</h3><p>The following prerequisites are required for this post:</p><h3>Setup a new React project</h3><p>Let’s create a react project and install the necessary packages by running the following commands:</p><pre class="lang-bash">npx create-react-app AmplifyExtension cd AmplifyExtension</pre><p>Next, we’ll install packages necessary for the application, such as Amplify CLI, Amplify UI, and tiny-glob packages. We use the Amplify UI and tiny-glob package, as this enables us to decrease development time. The scripts and UI components can be replaced with your preferred elements.</p><pre class="lang-bash">npm install -g @aws-amplify/cli npm install aws-amplify @aws-amplify/ui-react npm install tiny-glob</pre><h3>Create a Post build script and Add Manifest</h3><p>Create a folder named scripts at the root of the React application.</p><p>In the scripts folder, create a file called <code>postbuild.js</code> and paste the following code:</p><pre class="lang-js">const fs = require("fs");const path = require('path')const glob = require("tiny-glob");const manifest = require("../public/manifest.json"); async function getFileNames(pattern) { const files = await glob(build/static${pattern}
) return files.map(file => path.posix.relative('build', file.split(path.sep).join(path.posix.sep)));} async function main() { const js = await getFileNames('/js/*/.js') const css = await getFileNames('/css/*/.css') const logo = await getFileNames('/media/logo*.svg') const newManifest = { ...manifest,- content_scripts: [ { ...manifest.content_scripts[0], js, css, }, ], web_accessible_resources: [ { ...manifest.web_accessible_resources[0], resources: [...css, ...logo], }, ], }; console.log('WRITING', path.resolve("./build/manifest.json")) fs.writeFileSync( path.resolve("./build/manifest.json"), JSON.stringify(newManifest, null, 2), 'utf8' );} main();</pre><p>Open the <code>package.json</code> file present at the root of the project and add the following to the scripts block:</p><p><code>"postbuild": "node ./scripts/postbuild.js"</code></p><p>The end result should appear as follows:</p><div id="attachment_8707" class="wp-caption aligncenter c4"><img aria-describedby="caption-attachment-8707" class="wp-image-8707" src="https://d2908q01vomqb2.cloudfront.net/0a57cb53ba59c46fc4b692527a38a87c78d84028/2022/09/15/packagejson.jpg" alt="Picture showing the end result for package.json file" width="500" height="186" /><p id="caption-attachment-8707" class="wp-caption-text">Figure 2. Picture showing the end result for package.json file</p></div><p>Add the following to the <code>manifest.json</code> present in the public folder at the root of the application:</p><pre class="lang-json">{ "manifest_version": 3, "name": "React Content Script", "version": "0.0.1", "content_scripts": [ { "matches": ["https://docs.amplify.aws/"], "run_at": "document_end", "js": [], "css": [], "media": [] } ], "web_accessible_resources": [ { "resources": [], "matches": ["<all_urls>"] } ]}</pre><h3>Add Amplify resources</h3><p>Let’s initialize the application with Amplify CLI. Run the command:</p><pre class="lang-bash">amplify init</pre><p>Select the prompts.</p><pre class="lang-bash">? Enter a name for the project: AmplifyExtensionThe following configuration will be applied:Project information| Name: AmplifyExtension| Environment: dev| Default editor: Visual Studio Code| App type: javascript| Javascript framework: react| Source Directory Path: src| Distribution Directory Path: build| Build Command: npm.cmd run-script build| Start Command: npm.cmd run-script start? Initialize the project with the above configuration? (Y/n) Y</pre><p>Next let’s add Cognito as the authenticator resource for login. Run the command:</p><pre class="lang-bash">amplify add auth</pre><p>Select the following prompts:</p><pre class="lang-bash">Do you want to use the default authentication and security configuration? Default configurationHow do you want users to be able to sign in? UsernameDo you want to configure advanced settings? No, I am done.</pre><p>Let’s add an S3 bucket to our application. Run the command:</p><pre class="lang-bash">amplify add storage</pre><p>Select the Prompts:</p><pre class="lang-bash">Select Content (Images, audio, video, etc.)for who should have access, select: Auth users onlyWhat kind of access do you want for Authenticated users? · create/update, read</pre><p>To create the resources in the cloud, run the following command:</p><pre class="lang-bash">amplify push</pre><p>Then, select <code>yes</code> when prompted.</p><h3>Add code to inject the HTML elements</h3><p>Add the following to the <code>Index.js</code> file present under the src folder:</p><pre class="lang-js">import React from 'react';import ReactDOM from 'react-dom';import './index.css';import App from './App';import reportWebVitals from './reportWebVitals';//find the body elementconst body = document.querySelector('body');//create div elementconst app = document.createElement('div');app.id = 'root';if (body) { body.prepend(app);}ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root'));reportWebVitals();</pre><p>Next add the following to the <code>App.js</code> file in the src folder:</p><pre class="lang-js">import logo from './logo.svg';import './App.css';import { Amplify } from 'aws-amplify';import { withAuthenticator } from '@aws-amplify/ui-react';import '@aws-amplify/ui-react/styles.css';import { AmplifyS3Album } from '@aws-amplify/ui-react/legacy';import awsExports from './aws-exports';Amplify.configure(awsExports);function App() {return (<div className="App"><header className="App-header"><p>Hello</p><AmplifyS3Album /></header></div>);}//withAuthenticator componentexport default withAuthenticator(App);</pre><h3>Test the Application in a Chrome browser</h3><p>Run the following command to build the application:</p><pre class="lang-bash">npm run build</pre><h4>To test on a browser</h4><ul><li>Open the Chrome browser.</li><li>Open extensions in the Chrome settings.</li><li>In the right side top of the screen, toggle developer mode on.</li></ul><p><img class="aligncenter wp-image-8715 size-full" src="https://d2908q01vomqb2.cloudfront.net/0a57cb53ba59c46fc4b692527a38a87c78d84028/2022/09/15/enabledev.gif" alt="A GIF showing how you can toggle chrome extension tab from settings" width="800" height="328" /></p><ul><li>Select load unpacked and select the location for the build folder of the application. This is present in the root of the React application and gets generated on a build command.</li><li>Open <a href="https://docs.amplify.aws/">https://docs.amplify.aws/</a> in a new tab and observe the following at the top of the page:</li></ul><div id="attachment_8717" class="wp-caption aligncenter c6"><img aria-describedby="caption-attachment-8717" class="wp-image-8717" src="https://d2908q01vomqb2.cloudfront.net/0a57cb53ba59c46fc4b692527a38a87c78d84028/2022/09/15/login.jpg" alt="Cognito login screen to authenticate a user with email and password" width="300" height="203" /><p id="caption-attachment-8717" class="wp-caption-text">Figure 3. Cognito login screen to authenticate a user with email and password</p></div><ul><li>Create an account. Note that you must provide a valid email, as a verification code will be sent.</li><li>Upon logging in, the page will load a Button at the top.</li><li>Upon selecting the <code>Pick a file</code> button and selecting a picture from your file system, we’ll observe the output as follows.</li></ul><p><img class="wp-image-8732 size-full" src="https://d2908q01vomqb2.cloudfront.net/0a57cb53ba59c46fc4b692527a38a87c78d84028/2022/09/26/outpext.png" alt="A final image of a cat is displayed with a button to pick a file" /></p><p>In the background, the picture is being uploaded to an S3 bucket and then displayed here.</p><h2><strong>Cleanup resources</strong></h2><p>Now that you’ve finished this walkthrough solution, you can delete your Amplify application if you aren’t going to use it anymore. Run the following command in the terminal at the root of the project.</p><pre class="lang-bash">amplify delete</pre><p>Note that this action can’t be undone. Once the project is deleted, you can’t recover it. If you need it again, then you must re-deploy it.</p><p>To prevent any data loss, Amplify doesn’t delete the Amazon S3 storage bucket created via the CLI. We can delete the bucket on the Amazon S3 console. Note that the bucket will contain the name of the application (for example: AmplifyExtension), and it can be used when searching.</p><p>Delete the extension from the Chrome browser.</p><h2><strong>Conclusion</strong></h2><p>We can create Chrome extensions that allow users to consume Amplify resources, such as Amazon S3 storage and AWS Cognito. Furthermore, we can also utilize AppSync API capabilities to retrieve data from an Amazon DynamoDB Database.</p><p>A sample application can be found on Github <a href="https://github.com/ykethan/Amplify-Chrome-extension" target="_blank" rel="noopener noreferrer">here</a>.</p><p><strong>About the author:</strong></p></section>