Chrome Extension Boilerplate with React + Vite + Typescript
Chrome Extension Boilerplate with React + Vite + Typescript
[!NOTE] This project is listed in the Awesome Vite
[!TIP] Share storage state between all pages
https://github.com/user-attachments/assets/3b8e189f-6443-490e-a455-4f9570267f8c
This boilerplate helps you create Chrome/Firefox extensions using React and Typescript. It improves the build speed and development experience by using Vite and Turborepo.
git clone https://github.com/Jonghakseo/chrome-extension-boilerplate-react-vite ).nvmrc file, recommend to use nvm/packages/i18n/locales/{your locale(s)}/messages.jsonextensionDescription and extensionName, change the message fields (leave description alone)npm install -g pnpmpnpm installTypescript Workbench version in settings:Typescript: Select Typescript version... -> Use Workbench versionpnpm update-version <version> for change the version to the desired version of your extension.[!IMPORTANT] On Windows, make sure you have WSL enabled and Linux distribution (e.g. Ubuntu) installed on WSL.
Then, depending on the target browser:
pnpm dev (on Windows, you should run as administrator;
see issue#456)pnpm buildchrome://extensionsdist directory from the boilerplate projectpnpm dev:firefoxpnpm build:firefoxabout:debugging#/runtime/this-firefox./dist/manifest.json file from the boilerplate project[!NOTE] In Firefox, you load add-ons in temporary mode. That means they'll disappear after each browser close. You have to load the add-on on every browser launch.
pnpm i <package> -wpnpm i <package> -F <module name>package - Name of the package you want to install e.g. nodemon module-name - You can find it inside each package.json under the key name, e.g. @extension/content-script, you
can use only content-script without @extension/ prefix
Read: Env Documentation
The extension lives in the chrome-extension directory and includes the following files:
manifest.ts - script that outputs the manifest.jsonsrc/background - background script
(background.service_worker in manifest.json)public - icons referenced in the manifest; content CSS for user's page injection[!IMPORTANT] To facilitate development, the boilerplate is configured to "Read and change all your data on all websites". In production, it's best practice to limit the premissions to only the strictly necessary websites. See Declaring permissions and edit
manifest.jsaccordingly.
Code that is transpiled to be part of the extension lives in the pages directory.
content - Scripts injected into specified pages (You can see it in console)content-ui - React Components injected into specified pages (You can see it at the very bottom of pages)content-runtime - injected content scripts
This can be injected from e.g. popup like standard contentdevtools - extend the browser DevTools
(devtools_page in manifest.json)devtools-panel - DevTools panel
for devtoolsnew-tab - override the default New Tab page
(chrome_url_overrides.newtab in manifest.json)options - options page
(options_page in manifest.json)popup - popup shown when
clicking the extension in the toolbar
(action.default_popup in manifest.json)side-panel - sidepanel (Chrome 114+)
(side_panel.default_path in manifest.json)Some shared packages:
dev-utils - utilities for Chrome extension development (manifest-parser, logger)env - exports object which contain all environment variables from .env and dynamically declaredhmr - custom HMR plugin for Vite, injection script for reload/refresh, HMR dev-serveri18n - custom internationalization package; provides i18n function with type safety and other validationshared - shared code for the entire project (types, constants, custom hooks, components etc.)storage - helpers for easier integration with storage, e.g. local/session storagestailwind-config - shared Tailwind config for entire projecttsconfig - shared tsconfig for the entire projectui - function to merge your Tailwind config with the global one; you can save components herevite-config - shared Vite config for the entire projectOther useful packages:
zipper - run pnpm zip to pack the dist folder into extension-YYYYMMDD-HHmmss.zip inside the newly created
dist-zipmodule-manager - run pnpm module-manager to enable/disable modulese2e - run pnpm e2e for end-to-end tests of your zipped extension on different browsersIf saving source files doesn't cause the extension HMR code to trigger a reload of the browser page, try this:
pnpm run dev)grpc error,
kill the
turbo process
and run pnpm dev again.If you are using WSL and imports are not resolving correctly, ensure that you have connected VS Code to WSL remotely using the Remote - WSL extension.
To chat with other community members, you can join the Discord server. You can ask questions on that server, and you can also help others.
Also, suggest new features or share any challenges you've faced while developing Chrome extensions!
If you're debugging one, you can use Brie lets you capture screenshots, errors, and network activity, making it easier for us to help.
This Boilerplate is made possible thanks to all of its contributors.
No open issues yet, or sync has not completed.