Chrome extension in 20 min
Tags: tutorial, javascript, chrome, extension
Published: 2022-07-19 05:42:48

---
title: Chrome extension in 20 min
published: true
description: How to create a Chrome extension from scratch that turns a new tab into a notepad. 
tags:
  - tutorial
  - javascript
  - chrome
  - extension
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hdbwm3mch70cohdoptzk.png
---

This article is the detailed text version of the video I recently posted:

- [Chrome extension in 20 min - YouTube](https://www.youtube.com/watch?v=B5wdRcv-zQA)

I'll explain how to create a Chrome extension from scratch that turns a new tab into a notepad.

![demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wj7p5vef7bcl4nd5gmde.gif)

I use the following tools in this tutorial, but you don't have to have used these tools before.

- node.js (14.x or later)
- typescript
- css
- vite
- monaco-editor
- types/chrome
- crxjs/vite-plugin

## Create a new vite project

First, create a new vite project by `create-vite` npm package.

```
npm init vite@2.9.0
```

`npm init x` (or `npm create x` as an alias) runs `npm exec create-x`, so in this case you will be running `npm exec create-vite`. See `npm help init` for more detials.

As you may have noticed, I specified the version `2.9.0`. This is because the current latest vite version 3.0.0 doesn't work well with `crxjs/vite-plugin` yet, so we need to choose the older version for now.

After running the command, you are ready to build the default HTML + CSS + JavaScript source.

```
npm install
npm run dev
```

This command will continuously compile the source files and output files into ./dist/ directory, then start http://localhost:3000 as a preview HTTP server.

## Create an empty Chrome extension

To create an empty Chrome extension, you need to write manifest.json.

```json
{
  "name": "newtab-editor",
  "description": "Editor in new tab",
  "manifest_version": 3,
  "version": "0.0.1"
}
```

However, only putting this file won't cause Vite to include manifest.json to build target.

To achieve this, you also need to write vite.config.ts.
The `@crxjs/vite-plugin` does all the tedious work, so all you have to do is to pass manifest.json to it.

```typescript
import { crx } from "@crxjs/vite-plugin";
import manifest from "./src/manifest.json";

export default {
  plugins: [crx({ manifest })],
};
```

To import crx, don't forget to install it:

```
npm install --save-dev @crxjs/vite-plugin
```

After these steps, you can build the extension.
If you are still leaving `npm run dev` on, you should have a built Chrome extension in the ./dist/ directory.

## Install the extension

To install the extension from local files, follow the steps below:

1. open Google Chrome
2. go to Chrome extensions page (chrome://extensions/)
3. enable "Developer mode"
4. click "Load unpacked extension"
5. select the ./dist/ directory

![chrome extensions page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s9t3kfvezd96lshkfhxb.png)

## Override new tab

To override new tab page by our extension, add [chrome_url_overrides](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/chrome_url_overrides) property to manifest.json.

```json
"chrome_url_overrides": {
  "newtab": "index.html"
},
```

After reloading the extension, you should see the index.html in the new tab.

![index.html in new tab](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9ha8t8dx6btnkcupluwo.png)

## Add monaco-editor

This time I will use an editor called [monaco-editor](https://microsoft.github.io/monaco-editor/). This is a Visual Studio Code-based editor, which allows you to achieve roughly the same functionality in your browser.

It is easy to use, just import and mount it on some HTML element and it works.

```
npm install --save monaco-editor
```

```typescript
// src/main.ts
import "./style.css";
import * as monaco from "monaco-editor";

const app = document.querySelector<HTMLDivElement>("#app")!;
monaco.editor.create(app, {
  fontSize: 18,
  language: "markdown",
  lineHeight: 1.6,
  minimap: { enabled: false },
  padding: { bottom: 16, top: 16 },
  theme: "vs-dark",
});
```

After reloading the extension, you should see the editor in the new tab.

![monaco-editor](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uc25odt1shicfbrkrdal.png)

## Save content via storage API

To save editor content, we can use the [storage API](https://developer.chrome.com/docs/extensions/reference/storage/).

Unfortunately, however, it is not possible to call these APIs directly from index.html.
Instead, you need to have a background process to which these APIs are allowed and send requests to it.

First, the editor content is changed, send a request to the background process to save the content.

```typescript
// src/main.ts
editor.onDidChangeModelContent(() => {
  const content = editor.getValue();
  chrome.runtime.sendMessage({ type: "saveContent", content });
});
```

Second, when you opened the new tab, restore the content you saved.

```typescript
chrome.runtime.sendMessage({ type: "loadContent" }, ({ content }) => {
  editor.setValue(content);
});
```

Finally, prepare a backgruond process that accepts requests.

```typescript
// src/background.ts
chrome.runtime.onMessage.addListener((request, _, sendResponse) => {
  switch (request.type) {
    case "loadContent":
      chrome.storage.sync.get("content", ({ content }) => {
        sendResponse({ content });
      });
      return true;
    case "saveContent":
      chrome.storage.sync.set({ content: request.content });
      break;
  }
  return;
});
```

It's done!

![demo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wj7p5vef7bcl4nd5gmde.gif)

---

## Wrapping up 

In this tutorial, I explained how to create a Chrome extension from scratch that turns a new tab into a notepad.

The finished version of this Chrome extension is available on Chrome Web Store.

- [Editabro - Chrome Web Store](https://chrome.google.com/webstore/detail/editabro/eodgdnjgkjjlohklhoaapfhghgcoihmf)

Of course, the source code is also available on GitHub. If you are interested, I'd recommend you to read the source code. It includes techniques such as `debounce` to reduce the amount of communication with background processes, removing unnecessary language functions to reduce bundled code size, and using Worker to improve performance.

- https://github.com/r7kamura/editabro

I learned how to create Chrome extensions these days from @jacksteamdev's excellent article series. I would like to take this opportunity to thank you.

- [Create a Vite-React Chrome Extension in 90 seconds - DEV Community](https://dev.to/jacksteamdev/create-a-vite-react-chrome-extension-in-90-seconds-3df7)

As noted at the beginning of this article, I'm also providing a live coding video version of this tutorial. If you have any questions, don't hesitate to ask, either in the comments of this article or in the comments of the video.

- [Chrome extension in 20 min - YouTube](https://www.youtube.com/watch?v=B5wdRcv-zQA)

I will be posting several other coding videos, so if you are interested, please check out my channel.

- https://www.youtube.com/c/r7kamura

Thanks for reading this far. If you have any questions, please ask anything in the comments.


Good coding!