no cap fr fr, weβre about to build the most bussinβ browser extension using Vite, Tailwind CSS, and some zip magic β¨ this gonna hit different i promise π―
Table of contents
Open Table of contents
- π Download Chrome & Firefox (duh) π¦π
- π¦ Letβs Get This Bread with Vite π
- Pick Your Main Character Energy β‘
- π€οΈ CD Into That Folder Real Quick π
- π¦ Install the Rest of the Squad π€
- π¨ Make It GORGEOUS with Tailwind CSS π β¨
- ποΈ Add Tailwind to Your Popupβs CSS π
- π§© Update Your Popup Component π―
- π¦ Firefox Support Because Weβre Inclusive Like That π«Ά
- πββοΈ Run This Baby in Dev Mode π¨
- π¦ Zip It Up for Distribution ποΈ
- π οΈ Update package.json One Last Time πͺ
- π YEET! You Did That! π―π₯
π Download Chrome & Firefox (duh) π¦π
bestie you literally NEED Chrome and Firefox installed for testing. likeβ¦ how else are you gonna test it??? π no browsers = no vibes = L π
π¦ Letβs Get This Bread with Vite π
okay so run this command and watch the magic happen fr fr β¨
bun create vite-plugin-web-extension(btw bun is goated, npm is giving 2022 energy but do you i guess π)
Pick Your Main Character Energy β‘
when it asks, enter your project name (be creative bestie). then choose your template:
- Vanilla JavaScript
- Vanilla TypeScript
- Vue JavaScript
- Vue TypeScript
- React JavaScript π (this is IT chief)
- React TypeScript
- Svelte JavaScript
- Svelte TypeScript
pick your package manager (iβm team bun but thatβs just me being based π)
π€οΈ CD Into That Folder Real Quick π
if it doesnβt auto-cd for you (ugh so annoying), just do it yourself king/queen π
cd "Project-Name"literally just navigate there manually if you have to, itβs not that deep π
π¦ Install the Rest of the Squad π€
bun add tailwindcss @tailwindcss/vite cross-env zip-a-folder -d npm-run-allπ¨ Make It GORGEOUS with Tailwind CSS π β¨
time to make this extension absolutely SLAY with some styling periodt π
update your vite.config.js (copy-paste this bestie, youβre welcome):
import { defineConfig } from "vite";
import tailwindcss from '@tailwindcss/vite';
import react from "@vitejs/plugin-react";
export default defineConfig({
plugins: [
tailwindcss(),
],
});ποΈ Add Tailwind to Your Popupβs CSS π
open pages/Popup.css and yeet this in there:
@import "tailwindcss";thatβs it. thatβs the tweet. π¦
π§© Update Your Popup Component π―
letβs make this popup absolutely iconic fr fr. update pages/Popup.jsx:
import { useEffect } from "react";
import "./Popup.css";
export default function () {
useEffect(() => {
console.log("Hello from the popup! π");
}, []);
return <h1 className="font-bold text-3xl underline">Hello world! Test π</h1>;
}π¦ Firefox Support Because Weβre Inclusive Like That π«Ά
create src/manifest.chrome.json:
{
"manifest_version": 3,
"icons": {
"16": "icon/16.png",
"32": "icon/32.png",
"48": "icon/48.png",
"96": "icon/96.png",
"128": "icon/128.png"
},
"action": {
"default_popup": "src/popup.html"
},
"background": {
"service_worker": "src/background.js"
}
}create src/manifest.firefox.json:
{
"manifest_version": 2,
"icons": {
"16": "icon/16.png",
"32": "icon/32.png",
"48": "icon/48.png",
"96": "icon/96.png",
"128": "icon/128.png"
},
"browser_action": {
"default_popup": "src/popup.html"
},
"background": {
"scripts": ["src/background.js"]
}
}update vite.config.js (this is where the sauce is at π₯):
import { defineConfig } from "vite";
import tailwindcss from '@tailwindcss/vite'
import react from "@vitejs/plugin-react";
import webExtension, { readJsonFile } from "vite-plugin-web-extension";
const target = process.env.TARGET || "chrome";
function generateManifest() {
const manifestFile = target === "firefox"
? "src/manifest.firefox.json"
: "src/manifest.chrome.json";
const manifest = readJsonFile(manifestFile);
const pkg = readJsonFile("package.json");
return {
name: pkg.name,
description: pkg.description,
version: pkg.version,
...manifest,
};
}
export default defineConfig({
build: {
outDir: `dist-${target}`,
},
plugins: [
tailwindcss(),
react(),
webExtension({
manifest: generateManifest,
browser: target,
}),
],
});update package.json scripts:
"scripts": {
"dev": "vite",
"dev:chrome": "cross-env TARGET=chrome vite",
"dev:firefox": "cross-env TARGET=firefox vite --port 5174",
"dev:both": "npm-run-all --parallel dev:chrome dev:firefox",
},πββοΈ Run This Baby in Dev Mode π¨
okay moment of truth bestie, letβs see this thing pop off π¬
bun dev:bothπ¦ Zip It Up for Distribution ποΈ
ready to share your creation with the world? letβs package this up β¨
create a zipScript.js file:
import { zip } from "zip-a-folder";
await zip("dist", "extension.zip");π οΈ Update package.json One Last Time πͺ
add these scripts so you can build and zip with one command (efficiency queen/king π):
"scripts": {
"dev": "vite",
"dev:chrome": "cross-env TARGET=chrome vite",
"dev:firefox": "cross-env TARGET=firefox vite --port 5174",
"dev:both": "npm-run-all --parallel dev:chrome dev:firefox",
"build": "vite build && node zipScript.js",
"zip": "node zipScript.js"
},π YEET! You Did That! π―π₯
bun buildyou literally just built a whole browser extension that works on BOTH Chrome AND Firefox??? the serve is immaculate π β¨
now go test it, add your own flavor, and make it absolutely iconic. youβre literally a coding icon now no cap π¦ΈββοΈπ»