Chrome Extension boilerplate for manifest v3.
This template uses Parcel Web Extension Config and release-it for GitHub releases.
- Click Use this template button on the top of the page.
- After project initialization, change the
name
field in thepackage.json
file. This field will be used as a name for.zip
with production build. - Update
repository
,author
,bugs
,license
, andhomepage
props inpackage.json
according to your needs. - There is configured Dependabot version updates.
If you do not want PRs with your dependency version updates, remove the
.github/dependabot.yml
file.
- Check if your Node.js version is >= 20.
- Run
npm install
to install the dependencies. - Run
npm start
- Load your extension on Chrome following:
- Access
chrome://extensions/
- Check
Developer mode
- Click on
Load unpacked extension
- Select the
dist
folder.
- Access
- Stop the development script (if it is running)
- Run
npm run build
- Load your extension on Chrome following:
- Access
chrome://extensions/
- Check
Developer mode
- Click on
Load unpacked extension
- Select the
dist
folder
- Access
zip
file with the production extension's code will be created in the releases
folder.
This code is ready to be published in the Chrome Web Store.
During the release
script execution you will be asked for a new version number, so there is no need to change the version manually.
The script will bump the version in package.json
and manifest.json
.
This template uses release-it for release on GitHub.
- Generate
personal access token
in GitHub. Go to Github->Settings->DeveloperSettings->PersonalAccessTokens. Onlyrepo
scope is required. - Rename the existing
.env.example
file to.env
and put the generatedpersonal access token
there. It will look like:GITHUB_TOKEN="your generated token"
- Run
npm run release
. Under the hood, it will make a version bump (in bothpackage.json
andmanifest.json
), runnpm run build
steps, commit, push, and make a GitHub release with the generatedzip
file attached.
Parcel Web Extension Config does not support scripting
API
(executeScript
, insertCSS
, etc.)
As a workaround, take a look at the recipe below.
If you need to inject scripts dynamically using chrome.scripting
API, you could add these scripts to manifest.json
as an additional entry point.
For such code
chrome.scripting.executeScript({
target: {tabId},
files: ["checker/index.js"],
})
you could update your scripts in manifest.json
like this:
"start": "parcel watch src/manifest.json src/checker/index.js --host localhost",
"build": "parcel build src/manifest.json src/checker/index.js --no-cache"
If you need to use assets in such a dynamically injected script,
put them in web_accessible_resources
in your manifest.json
:
"web_accessible_resources": [
{
"resources": [
"web-accessible/icon.png"
],
"matches": [
"<all_urls>"
]
}
]
And in your code, you will need to use them like
<image src={chrome.runtime.getURL('web-accessible/icon.png')}/>
Do not use import icon from "./web-accessible/icon.png"
in such scripts.
The same goes for a page(s) not listed in manifest.json
.
You can add it as an additional entry point(s).
Something like that:
"start": "parcel watch src/manifest.json src/panel/panel.html --host localhost",
"build": "parcel build src/manifest.json src/panel/panel.html --no-cache"
In that case panel
folder will be created in dist
and you can reference it from your code like panel/panel.html
.
You can take a look at this example. There is an additional entry point (offscreen.html
) that is not listed in manifest.json
(chrome.offscreen
API usage).
If you do not need to use React in your extension:
npm uninstall react react-dom @types/react @types/react-dom eslint-plugin-react eslint-plugin-react-hooks
React is used only in popup
,
so remove src/popup/App.js
and update src/popup/index.js
to meet your needs.
In the .eslintrc.json
file remove all the strings related to react
(in extends
, plugins
, and rules
props ).