Front-End Web & Mobile

How to build a Chrome extension that integrates with Amplify resources

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.

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.

Chrome extension

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 Amazon Simple Storage Service (Amazon S3) bucket to store the images and Amplify UI component to display the images.

A GIF that shows the final demonstration of the Chrome extension that displays the image of a cat

A GIF that shows the final demonstration of the Chrome extension that displays the image of a cat

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.

The Chrome extension manifest is an entry point that contains three main components.

  1. The Popup scripts
  2. Content scripts
  3. Background scripts

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.

In this application, we’ll be utilizing the Content script to modify a web page by adding an upload button and display an image.

For detailed information refer to the Chrome Documentation.

AWS Amplify

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.

The Amplify Command Line Interface (CLI) is a unified toolchain to create, integrate, and manage the AWS cloud services for your app.

We’ll utilize Amplify CLI to add Amazon S3 storage and Authentication capabilities. Additionally, we’ll use Amplify UI components to add a picker component.

Architecture

The Architecture diagram for the Amplify application showing the interaction with the S3 bucket and Chrome scripts

Figure 1. The Architecture diagram for the Amplify application showing the interaction with the S3 bucket and Chrome scripts

Walkthrough

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.

The following information outlines the steps needed in creating an Amplify chrome extension:

  • Create a React project and install the necessary packages
  • Create a Post build script and Manifest
  • Add Amplify resources
  • Add code to inject the HTML elements
  • Test the application in the Chrome browser

Find the GitHub repository here.

Prerequisites

The following prerequisites are required for this post:

Setup a new React project

Let’s create a react project and install the necessary packages by running the following commands:

npx create-react-app AmplifyExtension 
cd AmplifyExtension

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.

npm install -g @aws-amplify/cli 
npm install aws-amplify @aws-amplify/ui-react 
npm install tiny-glob

Create a Post build script and Add Manifest

Create a folder named scripts at the root of the React application.

In the scripts folder, create a file called postbuild.js and paste the following code:

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();

Open the package.json file present at the root of the project and add the following to the scripts block:

"postbuild": "node ./scripts/postbuild.js"

The end result should appear as follows:

Picture showing the end result for package.json file

Figure 2. Picture showing the end result for package.json file

Add the following to the manifest.json present in the public folder at the root of the application:

{
  "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>"]
    }
  ]
}

Add Amplify resources

Let’s initialize the application with Amplify CLI. Run the command:

amplify init

Select the prompts.

? Enter a name for the project: AmplifyExtension
The 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

Next let’s add Cognito as the authenticator resource for login. Run the command:

amplify add auth

Select the following prompts:

Do you want to use the default authentication and security configuration? Default configuration
How do you want users to be able to sign in? Username
Do you want to configure advanced settings? No, I am done.

Let’s add an S3 bucket to our application. Run the command:

amplify add storage

Select the Prompts:

Select Content (Images, audio, video, etc.)
for who should have access, select:  Auth users only
What kind of access do you want for Authenticated users? · create/update, read

To create the resources in the cloud, run the following command:

amplify push

Then, select yes when prompted.

Add code to inject the HTML elements

Add the following to the Index.js file present under the src folder:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';

//find the body element
const body = document.querySelector('body');

//create div element
const app = document.createElement('div');

app.id = 'root';

if (body) {
  body.prepend(app);
}

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);

reportWebVitals();

Next add the following to the App.js file in the src folder:

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 component
export default withAuthenticator(App);

Test the Application in a Chrome browser

Run the following command to build the application:

npm run build

To test on a browser

  • Open the Chrome browser.
  • Open extensions in the Chrome settings.
  • In the right side top of the screen, toggle developer mode on.

A GIF showing how you can toggle chrome extension tab from settings

  • 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.
  • Open https://docs.amplify.aws/ in a new tab and observe the following at the top of the page:
Cognito login screen to authenticate a user with email and password

Figure 3. Cognito login screen to authenticate a user with email and password

  • Create an account. Note that you must provide a valid email, as a verification code will be sent.
  • Upon logging in, the page will load a Button at the top.
  • Upon selecting the Pick a file button and selecting a picture from your file system, we’ll observe the output as follows.

A final image of a cat is displayed with a button to pick a file

In the background, the picture is being uploaded to an S3 bucket and then displayed here.

Cleanup resources

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.

amplify delete

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.

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.

Delete the extension from the Chrome browser.

Conclusion

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.

A sample application can be found on Github here.

About the author:

Kethan Sai Yaram

Kethan Sai Yaram is a Developer Support Engineer at AWS Amplify, Kethan sai works on enriching customer experience and solve complex challenges. Passionate on creating unique use cases that evolve and solve problems.

Arundeep Nagaraj

Arundeep (Arun) is a Developer Support Manager for AWS Amplify working on resolving problems and architecture challenges for front-end developers. You can follow Arun on Twitter at @ arun_deepn