Easily Creates a Google Chrome Extension Manifest V3 for Beginners (from scratch)

Are you wondering how to make a Chrome extension from scratch? If you have never done extensions in development before. Or even if you have no developer experience in web technology. It is time to create your first Google Chrome Extension Manifest V3 for Beginners. And that in a few minutes (with copy and paste).

In this post, I will explain to you the anatomy of the Chrome extension. Next, I will walk you through the first steps to make this without any special frameworks (like Node.JS, NPM, or ESlint). Just with a simple text editor or Visual Studio Code. You will then know how to create a Chrome extension in 10 minutes flat. And it includes interactive links to download those files. Such as the image and icon file.

When you create your first Chrome extension, you need to fulfill a single purpose in the Chrome extension. And that it is easy to understand and makes the web experience comfortable. For example, a single purpose is to dim the web page with one click of a button. Or another purpose is to get one click on the current full date and time in the popup window. In addition, the user interfaces should be minimal and have a clear intent for the user.

Development of a Chrome extension

Building blocks of a Chrome browser extension

A Chrome extension is built with many components. Here is an architecture overview of what component can be included in an extension:

  1. Manifest
  2. User Interface Element
  3. Content Script
  4. Background Script
  5. Options Page

Let us discuss each of the components one by one:

Manifest

This is one of the important files of your Chrome extension Manifest V3. Here is an overview of what you can do with this file.

Properties

The manifest.json is a JSON Object Structure format that tells the action of the extension. There are properties required to run this Chrome extension in your Chrome web browser. And there are optional features that all depend on the kind of Chrome extension you want to build for your users.

Required properties

{
    "manifest_version": 3,
    "name": "My name",
    "version": "1.0",
  • name the string name of your Chrome extension and which is limited to up to 45 characters
  • version one to four dot-separated integers identifying the version of this extension. For example, 1.0.0.0
  • manifest_version the version of the manifest technology
  • host_permissions that is the list of URLs where the extension may be running on that website. This is a new property that is for manifest V3

Recommends properties

    "action": {
        "default_icon": {
            "19": "images/icon19.png",
            "38": "images/icon38.png"
        },
        "default_title": "My name",
        "default_popup": "popup.html"
    },
    "default_locale": "en",
    "description": "Screenshot my current screen",
    "icons": {
        "16": "images/icon16.png",
        "24": "images/icon24.png",
        "32": "images/icon32.png",
        "48": "images/icon48.png",
        "96": "images/icon96.png",
        "128": "images/icon128.png"
    },
  • action the property to set your browser button action in your Chrome toolbar. Here you can choose the default icon, title, and default popup page that should be visible when you click this icon
  • default_locale to set your default language of the Chrome extension. When you have a multi-language Chrome extension that includes en (English), nl (Dutch), fr (French), de (German). For example, if your French language file does not have a French-translated string, then it goes to the default language string of the English version.
  • description that describes this extension functionality. In Google Chrome the description text is limited to 132 characters. However, in Safari the description text is limited to 112 characters See this W3 Extension issue I reported.
  • icons showing the different formats to display this extension icon. That can be visible in the extension panel to the extension favicon

Optional properties

These are the optional properties that depend on whether you want to build the extension further for the users.

    "author": "Stefan vd",
    "background": {
        "service_worker": "background.js",
    },
    "permissions": ["storage", "activeTab"],
    "host_permissions": ["https://*.youtube.com/*"],
    "short_name": "S",
  • author this property gives the author name of this extension
  • background this is the script that listens to the event and communicates from your content script and popup page and vice versa. And it is the first script installed to detect the first or updated to a new extension version
  • permissions is the list of actions a chrome extension can do, for example, write your settings to storage, only works on the current tab with activeTab and other permissions. However, keep it to a minimum to get the best and safe experience for the user
  • short_name the string name with a minimum of 1 character and a maximum of 45 characters
    "web_accessible_resources": [
        {
            "resources": [
            "image/add.png",
            "image/edit.png",
            "image/remove.png"
            ],
            "matches": ["https://*.stefanvd.net/*"]
        }
    ],
  • web_accessible_resources this property declares which resources such as images are exposed and that match the website regex URL
    "content_scripts": [
        {
            "matches": ["https://*.stefanvd.net/*"],
            "js": ["content.js"]
        }
    ]
}
  • content_scripts this is an array of scripts that are allowed to manipulate the page DOM and run in the context of a matches website regex URL
Where must I save this manifest.json file?

The manifest.json must be saved in the root of the folder of your extension project.

Example code

In this tutorial, we are going to create a Chrome extension that, with a single click on its icon in the toolbar, will open a popup window and show you the current date and time. And when you visit a particular website, a blue rectangle is added at the top left of the webpage.

So open your Visual Studio Code application and create a new project folder. For example, “Simple-Chrome Extension“. That will be your work folder. In this root folder, create the “manifest.json” file and add the following code:

{
  "manifest_version": 3,
  "name": "__MSG_name__",
  "short_name": "Simple",
  "version": "1.0",
  "description": "__MSG_description__",
  "author": "Stefan vd",
  "homepage_url": "https://www.stefanvd.net/support/",
  "icons": {
    "16": "images/icon16.png",
    "24": "images/icon24.png",
    "32": "images/icon32.png",
    "48": "images/icon48.png",
    "96": "images/icon96.png",
    "128": "images/icon128.png"
  },
  "default_locale": "en",
  "action": {
    "default_icon": {
      "19": "images/icon19.png",
      "38": "images/icon38.png"
    },
    "default_title": "__MSG_name__",
    "default_popup": "popup.html"	
  },
  "content_scripts": [
    {
      "matches": ["https://*.stefanvd.net/*"],
      "js": ["scripts/content.js"],
      "run_at": "document_end"
    }
  ],
  "content_security_policy": {
    "extension_pages": "default-src 'none'; style-src 'self'; media-src 'none'; child-src 'none'; connect-src 'none'; script-src 'self'; img-src 'self'; object-src 'none'"
  },
  "commands": {
    "_execute_browser_action": {
      "suggested_key": {
        "default": "Ctrl+Shift+M",
        "mac": "MacCtrl+Shift+M"
      }
    }
  },
  "minimum_chrome_version": "103",
  "offline_enabled": true,
  "permissions": [ "activeTab" ]
}

In your Visual Studio Code application you will see the code as follows:

Visual Studio Code on the Google Chrome extension Manifest V3 for beginners
Visual Studio Code on the Google Chrome extension Manifest V3 for beginners

Next, create a new folder with the name “images“. Then download and place all these images in this folder: icon16.png, icon19.png, icon24.png, icon32.png, icon38.png, icon48.png, icon96.png, and icon128.png.

message.json

Now create a new folder called “_locales“. This is where all your localization strings are stored according to that language. In this folder “_locales” create a new folder “en“, that is for the English original strings. And then in this “en” create the file name “messages.json“, which will contain all strings with JSON object structure.

{
    "name": {"message": "Simple"},
    "description": {"message": "Chrome extension Manifest V3 Tutorial"}
}

The English messages.json file.

Button Action

Now we are going to get the files ready for when you click the button in your Chrome toolbar.

Example code

popup.html

On the root folder of your work project, create a new file named “popup.html“. That will represent the front web page of the popup panel.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="styles/popup.css">
<script type="text/javascript" src="scripts/popup.js"></script>
<body>
Hello World
<br>
<div id="date"></div>
</body>
</html>

The popup.html file.

To see the contents, go to your project folder and double-click on “popup.html” to open it in your Chrome web browser. Here, the design of this webpage will always be visible, so you can use the Chrome Inspector tool to design and improve the code. Or when the extension is loaded in your developer mode, click on the extension button to open the popup panel. And then click right on this popup panel, and click the menu item Inspect.

popup.js

Now create a folder “scripts“, and then with a new file name “popup.js“. This is the logic that shows the current date in the popup window, only when the Document Object Model (DOM) has been loaded completely. Then the init function will run and find that ID element named “date”, and provide the text content of the current date and time.

document.addEventListener("DOMContentLoaded", init);

function init(){
     document.getElementById("date").textContent = new Date();
}

The popup.js file.

styles.css

In your work project, create a new folder called “styles“. That gives the right design for that popup panel. That includes the font size, background color, and the minimum width and height for that popup panel.

html{min-width:435px;min-height:180px;padding:0;margin:0}
body{background:white;color:black;font-size:12px}
#date{font-size:24px;color:blue}

The styles.css file.

Content script

The content script is whatever the name states, it will add the script with the current web page content. So you can interact with the content of that web page. For example, you can detect the status of the video player or change the color of a text when the page loads.

Example code

Create a new file named “content.js” and place it in your “scripts” folder. This is the vanilla JavaScript code that creates a blue rectangle on the current web page.

var newdiv = document.createElement("div");
newdiv.id = "hellothere";
newdiv.style.background = "blue";
newdiv.style.color = "white";
newdiv.style.zIndex = 1000;
newdiv.style.position = "absolute";
newdiv.style.top = 0;
newdiv.style.left = 0;
newdiv.style.width = "200px";
newdiv.style.height = "100px";
newdiv.style.display = "flex";
newdiv.style.justifyContent = "center";
newdiv.style.alignItems = "center";
newdiv.innerText = "I am here";
document.body.appendChild(newdiv)

The content file.

When you open any of my stefanvd.net pages, you will see this blue rectangle on the top left corner of the web page.

The blue rectangle that is only visible on the top right on the Stefan vd website
The blue rectangle that is only visible on the top right on the Stefan vd website

Events page

The service worker is the heart of your Chrome extension. This ensures that the communication from the popup goes to the background, to the content script, and vice versus.

As I mentioned in my previous blog, there are some limitations when using the service worker with the previous HTML event page (which was for Manifest V2). When migrating to this new background context, keep two important things in mind. First, a service worker is terminated when not in use and restarted when needed (similar to event pages). Second, a service worker does not have access to DOM.

Here in this tutorial, we do not need a background script. But you can use it to make the browser button popup page dynamic, change the button icon, etc.

Complete structure

With a good structure, you can make maintenance of a Chrome extension very easy later and in the future. So this is how your file structures should be. An example structure for folders and files:

  • _locales / en / message.json
  • _locales / nl / message.json
  • _locales / fr / message.json
  • _locales / de / message.json
  • images/ .png or .webp or .jpg files
  • scripts / .js files
  • styles / .css files
  • manifest.json, .html files, and LICENSE

In your first Chrome extension from scratch, you will get this:

The complete tutorial code can be downloaded on the GitHub project page chrome-extension-manifest-v3-get-started.

Loading an unpacked extension

Now it is time to test your unpacked Chrome extension in developer mode. Follow the steps below to do that:

  1. Open your Google Chrome web browser, and go to the Extensions page by entering chrome://extensions in a new tab
    • Alternatively, click on the Extensions menu puzzle button and select Manage Extensions at the bottom of the menu
    • Or, click the 3 dot icon, select the menu item More Tools, and then select Extensions
  2. Toggle the Developer mode switch that is visible on the top right of the web page
  3. Next click on the button Load unpacked and select the extension directory
Google Chrome extension Manifest V3 for beginners - Chrome extension Developer mode
Google Chrome extension Manifest V3 for beginners – Chrome extension Developer mode

Publishing

When everything is ready and tested. You can publish your Chrome extension to the Chrome Web Store. For that, you have to pay a one-time activation fee of $5 to publish your Chrome extension. You can then publish up to 20 Chrome extensions in the Google Chrome Web Store.

To register your first developer account on the Chrome Web Store, just access the developer console. Next, follow the registration screen and agree to the developer agreement and policies. Then pay the registration fee. And you are ready to publish your first Chrome Extension to the Chrome Web Store.

Addition resource

To learn more about Chrome extension APIs and continue to create a creative experience for the users, see these resources:

Final remarks

In my previous post, I provided a good development environment for building a Chrome extension. Manifest V3 has a good template for a quick start to writing consistent and clean code. That with removing the unnecessary “.DS_Store” files and the folder “node_modules”. And with the plugin to write your seamless and concise JSON, HTML, JavaScript, and CSS code. That with automatically beautify your CSS code. And one command to distribute your Chrome extension to a zip file.

In this article, you have learned to create from scratch a Google Chrome extension Manifest V3 for beginners. And that will answer the questions like where should I put my manifest.json, what is the “messages.json” file and how to see the contents of the “popup.html” without running it in the Chrome extension. That with a correct file and folder structure, and knowing where to save your file in your project.

Now the developer is just starting out and trying to create a unique experience for your users like I did with my unique Chrome extension Turn Off the Lights. I hope you enjoyed my new tutorial post. If you would like to support me, consider a small donation to my web community work.