This boilerplate is meant to be a minimal quick start for creating chrome/firefox extensions using React, Typescript and Tailwind CSS.
It includes all possible pages such as new tab, dev panel, pop up, etc., as well as corresponding manifest settings by default. You will likely have to customize/delete some of the pages (see docs below).
You can build dist files for both Chrome and Firefox with manifest v3.
If you are looking for a React focused way to access the local storage, I also implemented a chrome local/sync storage hook. The hook works well with this template. Check it out here.
- React 19
- TypeScript
- Tailwind CSS
- i18n (optional)
- Cross browser development with polyfill (optional)
- ESLint
- Chrome Extension Manifest Version 3
- Github Action to build and zip your extension (manual trigger)
This template comes with build configs for both Chrome and Firefox. Running
dev
or build
commands without specifying the browser target will build
for Chrome by default.
- Clone this repository or click "Use this template"
- Change
name
anddescription
inmanifest.json
- Run
yarn
ornpm i
(check your node version >= 16) - Run
yarn dev[:chrome|:firefox]
, ornpm run dev[:chrome|:firefox]
Running a dev
command will build your extension and watch for changes in the
source files. Changing the source files will refresh the corresponding
dist_<chrome|firefox>
folder.
To create an optimized production build, run yarn build[:chrome|:firefox]
, or
npm run build[:chrome|:firefox]
.
For Chrome
- Open - Chrome browser
- Access - chrome://extensions
- Tick - Developer mode
- Find - Load unpacked extension
- Select -
dist_chrome
folder in this project (after dev or build)
For Firefox
- Open - Firefox browser
- Access - about:debugging#/runtime/this-firefox
- Click - Load temporary Add-on
- Select - any file in
dist_firefox
folder (i.e.manifest.json
) in this project (after dev or build)
The template includes source code for all of the extension pages (i.e. New Tab, Dev Tools, Popup, Side Panel etc.). You will likely have to customize it to fit your needs.
E.g. you don't want the newtab page to activate whenever you open a new tab:
- remove the directory
newtab
and its contents insrc/pages
- remove
chrome_url_overrides: { newtab: 'src/pages/newtab/index.html' },
inmanifest.json
Some pages like the "Side Panel" don't work the exact same in Chrome and Firefox. While this template includes the source code for the side panel, it won't automatically be included in the dist file to prevent cross browser build warnings.
To include the side panel for Chrome add the following to the manifest.json
:
{
"manifest_version": 3,
// ...
"permissions": [
"activeTab",
"sidePanel" // <-- permission for sidepanel
],
// ...
"side_panel": {
"default_path": "src/pages/panel/index.html" // <-- tell vite to include it in the build files
},
// ...
}
If you need to declare pages in addition to the manifest pages, e.g. a custom app
page, create a
new folder in the pages
directory and add the corresponding .html
, .tsx
and .css
files (see options/*
for an example to copy). Then include the root html in the vite.config.base.ts
file under build.rollupOptions.input
like so:
// ...
build: {
rollupOptions: {
input: {
app: resolve(pagesDir, "app", "index.html"),
},
output: {
entryFileNames: (chunk) => `src/pages/${chunk.name}/index.js`,
},
},
}
// ...
CSS files in the src/pages/*
directories are not necessary. They are left in there in case you want
to use it in combination with Tailwind CSS. Feel free to delete them.
Tailwind can be configured as usual in the tailwind.config.cjs
file. See doc link below.
To enable internationalization set the localize
flag in the vite.config.base.ts
to true
.
The template includes a directory locales
with a basic setup for english i18n. Enabling i18n
will pull the name and description for your extension from the english translation files instead
of the manifest.
Follow the instructions in the official docs to add other translations and retrieve them in the extension.
If you don't need i18n you can ignore the locales
directory until you need it, as it won't
be copied into the build folder unless the localize
flag is set to true
.
To upload an extension to the Chrome store you have to pack (zip) it and then upload it to your item in the Chrome Web Store.
This repo includes a Github Action Workflow to create a optimized prod build and the zip file.
To run the workflow do the following:
- Go to the "Actions" tab in your forked repository from this template
- In the left sidebar click on "Build and Zip Chrome Extension"
- Click on "Run Workflow" and select the main branch, then "Run Workflow"
- Refresh the page and click the most recent run
- In the summary page "Artifacts" section click on the generated "vite-web-extension-chrome"
- Upload this file to the Chrome Web Store as described here
- Vite
- Vite Plugin
- Chrome Extension with manifest 3
- Chrome Extension i18n
- Cross browser development with webextension-polyfill
- Rollup
- @crxjs/vite-plugin
- Tailwind CSS
Heavily inspired by Jonghakseo's vite chrome extension boilerplate.
It uses SASS instead of TailwindCSS and is slightly a lot less minimalist in case you want to check it out.
Feel free to open PRs or raise issues!