# Browser Extension Setup with Plasmo
This guide walks through setting up a browser extension using Plasmo framework while reusing existing webapp components and code.
## Overview
We'll use Plasmo (Option 3) which provides:
- Built specifically for modern web extensions
- Excellent TypeScript support
- Hot reloading during development
- Handles Manifest V3 complexities
- Easy component sharing
## Setup Steps
### 1. Install Plasmo
```bash
cd src/webapp
pnpm add -D plasmo
```
### 2. File Structure
Plasmo uses convention over configuration. Extension files go directly in the webapp root:
```
src/
webapp/
app/ # Keep existing Next.js app
components/ # Keep existing components
hooks/ # Keep existing hooks
api-client/ # Keep existing API client
popup.tsx # Extension popup (root level)
options.tsx # Extension options page (root level)
content.ts # Content scripts (root level)
background.ts # Background script (root level)
package.json # Update this
```
### 3. Update package.json Scripts
```json
{
"scripts": {
"dev": "next dev",
"dev:extension": "plasmo dev",
"build": "next build",
"build:extension": "plasmo build",
"package:extension": "plasmo package"
}
}
```
### 4. File Structure
Plasmo uses convention over configuration. Extension files go directly in the webapp root:
```
src/
webapp/
app/ # Keep existing Next.js app
components/ # Keep existing components
hooks/ # Keep existing hooks
api-client/ # Keep existing API client
popup.tsx # Extension popup (root level)
options.tsx # Extension options page (root level)
content.ts # Content scripts (root level)
background.ts # Background script (root level)
package.json # Update this
```
### 5. Create Extension Entry Points
**popup.tsx:**
```typescript
import { useAuth } from "./hooks/useAuth"
import { Button, Center, Title } from "@mantine/core"
import "@mantine/core/styles.css"; // Reuse your styles
function IndexPopup() {
const { isAuthenticated, login } = useAuth()
return (
Your App Extension
{isAuthenticated ? (
Welcome back!
) : (
)}
)
}
export default IndexPopup
```
**content.ts:**
```typescript
import type { PlasmoCSConfig } from 'plasmo';
export const config: PlasmoCSConfig = {
matches: [''],
};
// Add save-to-library functionality to pages
console.log('Content script loaded');
```
### 6. Update Your Auth Hook for Extension
**hooks/useAuth.tsx:**
```typescript
// Add extension-specific storage
const isExtension = typeof chrome !== 'undefined' && chrome.storage;
const useAuth = () => {
// Use chrome.storage for extension, localStorage for webapp
const storage = isExtension ? chrome.storage.local : localStorage;
// Rest of your existing auth logic...
};
```
### 7. Shared Component Configuration
Create **shared/components/** and move reusable components:
```typescript
// Move these to shared/components/
-UrlCard.tsx - ui / components;
```
Update imports in both webapp and extension to use shared components.
### 8. Development Workflow
**Terminal 1 - Webapp:**
```bash
cd src/webapp
pnpm dev
```
**Terminal 2 - Extension:**
```bash
cd src/webapp
pnpm dev:extension
```
### 9. Load Extension in Browser
1. Run `pnpm dev:extension`
2. Open Chrome → Extensions → Developer mode
3. Click "Load unpacked" → Select `src/webapp/build-extension`
4. Extension auto-reloads on code changes!
### 10. Handle Extension-Specific APIs
**background.ts:**
```typescript
import { ApiClient } from './api-client/ApiClient';
// Handle extension-specific functionality
chrome.action.onClicked.addListener((tab) => {
// Save current page to library
});
```
## Key Benefits of This Setup
- ✅ **Live Reloading:** Plasmo provides hot reload for extension development
- ✅ **Code Reuse:** Share components, hooks, and API client
- ✅ **TypeScript:** Full TypeScript support
- ✅ **Separate Builds:** Webapp and extension build independently
- ✅ **Modern Tooling:** Uses your existing build tools
## Development Commands
```bash
# Develop webapp
pnpm dev
# Develop extension (with live reload)
pnpm dev:extension
# Build extension for production
pnpm build:extension
# Package extension as .zip
pnpm package:extension
```
## Notes
- The extension will automatically reload in the browser when you make changes to any extension files
- Use chrome.storage for extension-specific data persistence
- Share as much code as possible between webapp and extension
- Test in both Chrome and Firefox during development