A full-featured, ready-to-use Chrome extension template built with modern technologies - which just works!
preview.mp4
- Library and Components
- Development
- Folder and File Descriptions
- Auto-reload and HRM
- Content Scripts: CSS
- Custom Fonts
- Add New Page
- Setup Your Brand
- Going Minimal
- Contributing
- ⚡ Vite
- 🔒 TypeScript
- ⚛️ React
- 🖌️ Tailwind CSS
- 🌸 shadcn/ui
- 📦 CRX
- 🎭 Playwright
- Clone the repository and
cdto it. - Tested in node version
>=20.18.0. So make sure its updated. -
$ yarn install- Install dependencies
-
$ yarn dev- Runs vite in development mood HMR enabled
- Default port is
5173. - For popup
http://localhost:5173/popup.htm - For options
http://localhost:5173/options.html - For content script, open any web page.
- Auto reload works for all
popup,contentandoptions.
-
$ yarn build- Just builds the extension in production mode.
-
$ yarn build:test- Runs
lint,prettierand the production build. - After build runs the e2e tests.
- Runs
-
$ yarn build:watch- Runs the production build with watch mode.
- Auto reload doesn't work in this mode, needs to manually refresh extension.
public/: Contains all static files that are served as-is, like icons etc.manifest.json: The manifest file that configures the extension’s permissions, background scripts, and other settings. CRXJS Vite Plugin
scripts/: Utility script files.src/: Contains all the source code for the extension.assets/: Holds assets like fonts, images which compiled with vite.components/: Holds user interface components. All the UI designs forpopup,contentandoptions.entryPoints/: Main entry points of chrome extension.background.tsx: The extension's background script.content.tsx: The extension's content script.main.css: Base common css contains tailwind and other global css shared with all parts of extension.options.tsx: The extension's options page.popup.tsx: The extension's popup page.
hooks/: React hooksuseMessage.tsx: A wrapper ofchrome.runtime.onMessageusable in allpopup,contentandoptionspage.useSettings.tsx: Global general settings provider holds theme etc. Its sync withchrome.storageand notify allpopup,contentandoptionspage.
lib/: Contains types, interface, shad cn utils etc.
tests/: Contains all unit and e2e tests.components.json: Generated by shadcn/ui.options.html: The extension's options page entry file.popup.html: The extension's popup page entry file.
With vite and CRX Vite plugin the hot reload works out of the box. The content script also works, except for custom font files can't make it work yet.
Vite generates font-face's url without chrome extension absolute path. For build mode, implemented a workaround.
After running
yarn devoryarn build:watch, make sure to refresh the chrome extension once.
For content scripts Shadow DOM is used to ensure encapsulated styles preventing interference with the content page.
Content script CSS is injected using adoptedStyleSheets when supported or via a <style> tag as a fallback for older browser versions.
- Custom fonts can be used by placing the font files and a @font-face css inside
src/assets/fonts/.- For example, create new folder
Robotoinsidesrc/assets/fonts/. - Put font files (woff/woff2/ttf) and
.cssfile which has@font-face. - Update the
font-familyinsrc/entryPoints/main.css.
- For example, create new folder
The font is ready to use. workaround script will find the css file, resolve the url using chrome.runtime.getURL.
Font files are copied by vite-plugin-static-copy plugin.
You can add new page in chrome extension which will be available at chrome-extension://{chromeExtensionId}/[page].html.
For example you may want to have a welcome page which opens after installing the chrome extension.
- Create a ui component in
src/components/welcome/index.tsx - Create a entry file in
src/entryPoints/welcome.tsxconst element = document.getElementById('welcome-root')!; renderRoot(element, <WelcomeComponent />); - Create a
welcome.htmlfile in root folder.- Make sure to add a id div
<div id="welcome-root"></div>and a script tag<script type="module" src="src/entryPoints/welcome.tsx"></script>in body
- Make sure to add a id div
- Setup entry point for vite in
vite.config.ts"build": { "rollupOptions": { welcome: 'welcome.html' } }
Now you can access it in chrome-extension://{chromeExtensionId}/welcom.html. Or you can open it from background script chrome.tabs.create({ url: chrome.runtime.getURL("welcome.html") });.
- Change
ROOT_CONTAINER_IDin/src/lib/constants.ts - Change
sidebarTagNamein/src/entryPoints/content.tsx - Change
prefixintailwind.config.ts - Change necessary infos like
name,short_nameetc. in/public/manifest.json - Change logo in
/src/assets/images - Change icons in
/public - Delete or update test codes in
/tests
You may want to remove dependencies and clean up demo codes to get started from scratch.
- Remove
src/hooksandsrc/components/uifolders. - Remove
src/lib/types.tsandsrc/lib/utils.tsfiles. - Clean up code inside following files. These are root file of these pages.
src/components/content/index.tsxsrc/components/options/index.tsxsrc/components/popup/index.tsxsrc/entryPoints/background.tsx
shadcn/ui: Remove all@radix-ui/*,cmdk,tailwind-mergedependencies- Delete test codes in
/tests
Now you are ready to go from scratch!
You can also build chrome extension without content/popup/options page.
- To remove options page, delete
"options_ui"and"options_page"frompublic/manifest.json. - To remove content script, delete
"content_scripts"frompublic/manifest.json. - To remove popup page, delete
"default_popup"frompublic/manifest.json.
This is an open-source template. Contributions are welcome! Feel free to open pull requests or raise issues to help improve this project.