### Install UI Package Dependency
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/ui/README.md
Instructions to add the UI package as a dependency in your project's package.json file. This involves navigating to the target page directory and updating the dependencies section, followed by running the package installation command.
```shell
cd pages/options
{
"dependencies": {
"@extension/ui": "workspace:*"
}
}
pnpm install
```
--------------------------------
### Install shadcn/ui dependencies
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/ui/README.md
This command installs the necessary npm packages for shadcn/ui integration into the 'ui' workspace. It includes `tailwindcss-animate`, `class-variance-authority`, `tailwind-merge`, and `lucide-react`.
```shell
pnpm add tailwindcss-animate class-variance-authority tailwind-merge lucide-react -F ui
```
--------------------------------
### Configure shadcn/ui with components.json
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/ui/README.md
This JSON file configures shadcn/ui settings, including the schema, style, Tailwind CSS integration (config, CSS file, base color, prefix), component aliases, and icon library. It's essential for the shadcn/ui setup.
```json
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "lib/global.css",
"baseColor": "zinc",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/lib/components",
"utils": "@/lib/utils",
"ui": "@/lib/components/ui",
"lib": "@/lib",
"hooks": "@/lib/hooks"
},
"iconLibrary": "lucide"
}
```
--------------------------------
### Create a Custom UI Component
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/ui/README.md
Provides an example of creating a custom component using React and the UI package. It includes exporting the component and defining its props based on standard HTML attributes, ensuring compatibility with the UI library.
```typescript
// lib/components/index.ts
export * from './CustomComponent.js';
// lib/components/CustomComponent.tsx
import { cn } from '@/lib/utils.js';
import type { ComponentPropsWithoutRef } from 'react';
type CustomComponentProps = ComponentPropsWithoutRef<'section'>;
export const CustomComponent = ({ children, ...props }: CustomComponentProps) => {
return {children};
}
```
--------------------------------
### Use Custom and Standard UI Components
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/ui/README.md
Illustrates how to import and utilize components from the UI package within a React page. This example shows the usage of `CustomComponent`, `ErrorDisplay`, and `LoadingSpinner`, along with higher-order components for error handling and suspense.
```typescript
import { CustomComponent, ErrorDisplay, LoadingSpinner } from '@extension/ui';
import { withErrorBoundary, withSuspense } from '@/lib/error-boundary'; // Assuming these are available
const Page = () => {
return Hi, I'm a custom component.;
}
export default withErrorBoundary(withSuspense(Page, ), ErrorDisplay);
```
--------------------------------
### Popup Implementation Example - TypeScript
Source: https://context7.com/jonghakseo/chrome-extension-boilerplate-react-vite/llms.txt
This demonstrates a complete popup implementation including theme toggle, content script injection, and Chrome API usage. It uses storage for theme preference and provides button functionality for external links and script injection. Dependencies: `@extension/shared`, `@extension/storage`, `@extension/ui`, `@extension/i18n`, Chrome APIs.
```typescript
import { useStorage } from '@extension/shared';
import { exampleThemeStorage } from '@extension/storage';
import { ToggleButton } from '@extension/ui';
import { t } from '@extension/i18n';
const PROJECT_URL = 'https://github.com/example/repo';
export default function Popup() {
const { isLight } = useStorage(exampleThemeStorage);
// Open new tab
const openGithub = () => {
chrome.tabs.create({ url: PROJECT_URL });
};
// Inject content script dynamically
const injectContentScript = async () => {
const [tab] = await chrome.tabs.query({
currentWindow: true,
active: true
});
if (!tab?.id) return;
try {
await chrome.scripting.executeScript({
target: { tabId: tab.id },
files: [
'/content-runtime/example.iife.js',
'/content-runtime/all.iife.js'
]
});
// Show notification
await chrome.notifications.create('inject-success', {
type: 'basic',
iconUrl: chrome.runtime.getURL('icon-128.png'),
title: t('extensionName'),
message: 'Content script injected successfully'
});
} catch (error) {
console.error('Failed to inject script:', error);
}
};
return (
{t('extensionName')}
{t('toggleTheme')}
);
}
```
--------------------------------
### Background Service Worker Example for Chrome Extension
Source: https://context7.com/jonghakseo/chrome-extension-boilerplate-react-vite/llms.txt
This TypeScript code defines a background service worker for a Chrome extension. It handles extension installation events, manages theme storage, and listens for messages from content scripts for theme-related actions. It also broadcasts theme changes to all active tabs.
```typescript
import 'webextension-polyfill';
import { exampleThemeStorage } from '@extension/storage';
console.log('Background service worker loaded');
// Initialize storage on install
chrome.runtime.onInstalled.addListener(async (details) => {
if (details.reason === 'install') {
console.log('Extension installed');
// Set default values
await exampleThemeStorage.set({
theme: 'light',
isLight: true
});
// Open welcome page
await chrome.tabs.create({
url: chrome.runtime.getURL('new-tab/index.html')
});
}
});
// Listen for messages from content scripts
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
console.log('Message received:', message);
if (message.type === 'GET_THEME') {
exampleThemeStorage.get().then(theme => {
sendResponse({ theme });
});
return true; // Async response
}
if (message.type === 'TOGGLE_THEME') {
exampleThemeStorage.toggle().then(() => {
sendResponse({ success: true });
});
return true;
}
});
// Monitor storage changes
exampleThemeStorage.subscribe(() => {
const snapshot = exampleThemeStorage.getSnapshot();
console.log('Theme changed:', snapshot);
// Broadcast to all tabs
chrome.tabs.query({}, (tabs) => {
tabs.forEach(tab => {
if (tab.id) {
chrome.tabs.sendMessage(tab.id, {
type: 'THEME_UPDATED',
theme: snapshot
}).catch(() => {
// Tab might not have content script
});
}
});
});
});
```
--------------------------------
### Install I18n Package in package.json
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/i18n/README.md
Shows how to add the '@extension/i18n' package as a dependency in your project's package.json file to enable internationalization features.
```json
{
"dependencies": {
"@extension/i18n": "workspace:*"
}
}
```
--------------------------------
### Manifest V3 Configuration for Chrome Extensions
Source: https://context7.com/jonghakseo/chrome-extension-boilerplate-react-vite/llms.txt
Defines the complete manifest configuration for a Chrome extension using Manifest V3. It includes basic information, permissions, background service worker setup, action/popup configuration, options page, new tab override, devtools page, side panel, content scripts, icons, web accessible resources, and Firefox compatibility settings.
```typescript
import type { ManifestType } from '@extension/dev-utils';
import packageJson from './package.json';
const manifest: ManifestType = {
manifest_version: 3,
default_locale: 'en',
// Basic info (uses i18n)
name: '__MSG_extensionName__',
version: packageJson.version,
description: '__MSG_extensionDescription__',
// Permissions
host_permissions: [''],
permissions: [
'storage', // chrome.storage API
'scripting', // Dynamic script injection
'tabs', // Tab management
'notifications', // Show notifications
'sidePanel' // Side panel (Chrome 114+)
],
// Background service worker
background: {
service_worker: 'background.js',
type: 'module'
},
// Popup
action: {
default_popup: 'popup/index.html',
default_icon: 'icon-34.png'
},
// Options page
options_page: 'options/index.html',
// New tab override
chrome_url_overrides: {
newtab: 'new-tab/index.html'
},
// DevTools extension
devtools_page: 'devtools/index.html',
// Side panel (Chrome only)
side_panel: {
default_path: 'side-panel/index.html'
},
// Content scripts
content_scripts: [
{
matches: ['http://*/*', 'https://*/*', ''],
js: ['content/all.iife.js']
},
{
matches: ['https://github.com/*'],
js: ['content/github.iife.js']
},
{
matches: ['http://*/*', 'https://*/*'],
js: ['content-ui/all.iife.js']
},
{
matches: ['http://*/*', 'https://*/*'],
css: ['content.css']
}
],
// Icons
icons: {
'128': 'icon-128.png'
},
// Web accessible resources
web_accessible_resources: [
{
resources: ['*.js', '*.css', '*.svg', '*.png'],
matches: ['*://*/*']
}
],
// Firefox compatibility
browser_specific_settings: {
gecko: {
id: 'extension@example.com',
strict_min_version: '109.0'
}
}
} satisfies ManifestType;
export default manifest;
```
--------------------------------
### Type Safety Example for Missing Translations
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/i18n/README.md
Illustrates a TypeScript error that occurs when a translation key is present in one language's 'messages.json' but missing in another. This helps ensure that all keys are consistently defined across all supported locales.
```json
{
"hello": {
"message": "Hello World!"
}
}
```
```json
{
"helloWorld": {
"message": "안녕하세요, 여러분!"
}
}
```
```typescript
import { t } from '@extension/i18n';
// Error: TS2345: Argument of type "hello" is not assignable to parameter of type
console.log(t('hello'));
```
--------------------------------
### Import Global CSS for ShadowDOM
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/ui/README.md
Imports the UI package's global CSS into the content-ui Tailwind input file. Required for using shadcn components within ShadowDOM.
```CSS
@import '@extension/ui/lib/global.css';
@tailwind base;
@tailwind components;
@tailwind utilities;
```
--------------------------------
### Import Global CSS for UI Package
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/ui/README.md
Shows how to import the global CSS file provided by the UI package into your main CSS file. This ensures that global styles and CSS variables from the UI package are applied across your application.
```css
@import '@extension/ui/global.css';
```
--------------------------------
### Add shadcn Button Component
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/ui/README.md
Command to add the shadcn button component to the UI package. Uses pnpm to execute the shadcn CLI with the specified component and path.
```shell
pnpm dlx shadcn@latest add button -c ./packages/ui
```
--------------------------------
### Configure Tailwind CSS for UI Package
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/ui/README.md
Demonstrates how to integrate the UI package's Tailwind CSS configuration. This involves importing base configuration and using the `withUI` utility to merge settings, specifically targeting HTML and TSX files for content.
```typescript
import baseConfig from '@extension/tailwindcss-config';
import { withUI } from '@extension/ui';
export default withUI({
...baseConfig,
content: ['./index.html', './src/**/*.tsx'],
});
```
--------------------------------
### Discover Content Script Entry Points - getContentScriptEntries()
Source: https://context7.com/jonghakseo/chrome-extension-boilerplate-react-vite/llms.txt
Dynamically discovers content script entry points from a directory structure using '@extension/vite-config'. Generates build configuration for content scripts.
```typescript
import { getContentScriptEntries } from '@extension/vite-config';
import { resolve } from 'path';
const matchesDir = resolve(__dirname, 'src', 'matches');
// Scans directory structure:
// src/matches/
// ├── all/index.ts
// ├── example/index.ts
// └── github/index.ts
const entries = getContentScriptEntries(matchesDir);
// Returns:
// {
// 'all': '/absolute/path/to/matches/all/index.ts',
// 'example': '/absolute/path/to/matches/example/index.ts',
// 'github': '/absolute/path/to/matches/github/index.ts'
// }
// Use in rollup config:
export default {
build: {
rollupOptions: {
input: entries,
output: {
entryFileNames: '[name].iife.js',
format: 'iife'
}
}
}
};
```
--------------------------------
### CSS Variables for Light and Dark Themes
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/ui/README.md
Defines CSS custom properties for both light and dark themes. Includes variables for backgrounds, foregrounds, accents, and destructive colors. Uses HSL color values for better theming control.
```CSS
--secondary-foreground: 222.2 47.4% 11.2%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 100% 50%;
--destructive-foreground: 210 40% 98%;
--ring: 215 20.2% 65.1%;
--radius: 0.5rem;
}
.dark {
--background: 224 71% 4%;
--foreground: 213 31% 91%;
--muted: 223 47% 11%;
--muted-foreground: 215.4 16.3% 56.9%;
--accent: 216 34% 17%;
--accent-foreground: 210 40% 98%;
--popover: 224 71% 4%;
--popover-foreground: 215 20.2% 65.1%;
--border: 216 34% 17%;
--input: 216 34% 17%;
--card: 224 71% 4%;
--card-foreground: 213 31% 91%;
--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 1.2%;
--secondary: 222.2 47.4% 11.2%;
--secondary-foreground: 210 40% 98%;
--destructive: 0 63% 31%;
--destructive-foreground: 210 40% 98%;
--ring: 216 34% 17%;
```
--------------------------------
### Define shadcn/ui global CSS variables and styles
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/ui/README.md
This CSS file defines the base styles and CSS variables for shadcn/ui components. It includes Tailwind CSS directives and sets up custom properties for colors and themes, ensuring consistent UI appearance across the application.
```css
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
:host, :root {
--background: 0 0% 100%;
--foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--popover: 0 0% 100%;
--popover-foreground: 222.2 47.4% 11.2%;
--border: 214.3 31.8% 91.4%;
--input: 214.3 31.8% 91.4%;
--card: 0 0% 100%;
--card-foreground: 222.2 47.4% 11.2%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
```
--------------------------------
### Package Extension into Zip File - TypeScript
Source: https://context7.com/jonghakseo/chrome-extension-boilerplate-react-vite/llms.txt
This snippet demonstrates how to package a Chrome extension into a distributable zip file using the `zipBundle` function. It supports both production builds (without source maps) and debugging builds (with source maps). Dependencies: `@extension/zipper`, `path`.
```typescript
import { zipBundle } from '@extension/zipper';
import { resolve } from 'path';
const rootDir = resolve(__dirname);
// Create production zip
await zipBundle({
distDirectory: resolve(rootDir, 'dist'),
buildDirectory: resolve(rootDir, 'dist-zip'),
archiveName: 'my-extension'
}, false); // withMaps = false for production
// Creates: dist-zip/my-extension-20250112-143022.zip
// Includes: manifest.json, all pages, icons, content scripts
// With source maps for debugging:
await zipBundle({
distDirectory: resolve(rootDir, 'dist'),
buildDirectory: resolve(rootDir, 'dist-zip'),
archiveName: 'my-extension-debug'
}, true); // withMaps = true
```
--------------------------------
### Extend Tailwind CSS configuration with shadcn/ui
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/ui/README.md
This TypeScript function merges shadcn/ui's Tailwind CSS configuration with your project's existing configuration. It ensures proper theme settings, colors, fonts, keyframes, and plugins like `tailwindcss-animate` are applied, while also including UI package content paths.
```typescript
import deepmerge from 'deepmerge';
import { fontFamily } from 'tailwindcss/defaultTheme';
import tailwindAnimate from 'tailwindcss-animate';
import type { Config } from 'tailwindcss';
export function withUI(tailwindConfig: Config): Config {
return deepmerge(
shadcnConfig,
deepmerge(tailwindConfig, {
content: ['./node_modules/@extension/ui/lib/**/*.{tsx,ts,js,jsx}']
})
);
}
const shadcnConfig = {
darkMode: ['class'],
theme: {
container: {
center: true,
padding: '2rem',
screens: {
'2xl': '1400px'
}
},
extend: {
colors: {
border: 'hsl(var(--border))',
input: 'hsl(var(--input))',
ring: 'hsl(var(--ring))',
background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))',
primary: {
DEFAULT: 'hsl(var(--primary))',
foreground: 'hsl(var(--primary-foreground))'
},
secondary: {
DEFAULT: 'hsl(var(--secondary))',
foreground: 'hsl(var(--secondary-foreground))'
},
destructive: {
DEFAULT: 'hsl(var(--destructive))',
foreground: 'hsl(var(--destructive-foreground))'
},
muted: {
DEFAULT: 'hsl(var(--muted))',
foreground: 'hsl(var(--muted-foreground))'
},
accent: {
DEFAULT: 'hsl(var(--accent))',
foreground: 'hsl(var(--accent-foreground))'
},
popover: {
DEFAULT: 'hsl(var(--popover))',
foreground: 'hsl(var(--popover-foreground))'
},
card: {
DEFAULT: 'hsl(var(--card))',
foreground: 'hsl(var(--card-foreground))'
}
},
borderRadius: {
lg: `var(--radius)`,
md: `calc(var(--radius) - 2px)`,
sm: 'calc(var(--radius) - 4px)'
},
fontFamily: {
sans: ['var(--font-sans)', ...fontFamily.sans]
},
keyframes: {
'accordion-down': {
from: { height: '0' },
to: { height: 'var(--radix-accordion-content-height)' }
},
'accordion-up': {
from: { height: 'var(--radix-accordion-content-height)' },
to: { height: '0' }
}
},
animation: {
'accordion-down': 'accordion-down 0.2s ease-out',
'accordion-up': 'accordion-up 0.2s ease-out'
}
}
},
plugins: [tailwindAnimate]
};
```
--------------------------------
### Create Reactive Storage with createStorage() - TypeScript
Source: https://context7.com/jonghakseo/chrome-extension-boilerplate-react-vite/llms.txt
The `createStorage` function generates a reactive storage area that synchronizes across all extension contexts (popup, background, content scripts). It supports various storage types (local, sync, session) and allows for live updates and custom serialization. This function is essential for managing state consistently throughout the browser extension.
```typescript
import { createStorage, StorageEnum } from '@extension/storage';
// Create storage with live sync
const themeStorage = createStorage<{ theme: string; isLight: boolean } >(
'theme-storage-key',
{ theme: 'light', isLight: true },
{
storageEnum: StorageEnum.Local,
liveUpdate: true,
}
);
// Read value
const currentTheme = await themeStorage.get();
console.log(currentTheme); // { theme: 'light', isLight: true }
// Set value
await themeStorage.set({ theme: 'dark', isLight: false });
// Update with function (toggle theme)
await themeStorage.set(prev => ({
theme: prev.theme === 'light' ? 'dark' : 'light',
isLight: prev.theme === 'dark'
}));
// Session storage for temporary data
const tempStorage = createStorage(
'session-key',
{ count: 0 },
{
storageEnum: StorageEnum.Session,
sessionAccessForContentScripts: true
}
);
// Sync storage across devices
const syncStorage = createStorage(
'sync-key',
{ preferences: [] },
{ storageEnum: StorageEnum.Sync }
);
```
--------------------------------
### Tailwind Base Layer Configuration
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/ui/README.md
Applies Tailwind CSS base styles to all elements and the body. Uses @apply directive to set border, font, background, and text colors from CSS variables.
```CSS
@layer base {
* {
@apply border-border;
}
body {
@apply font-sans antialiased bg-background text-foreground;
}
}
```
--------------------------------
### Configure Vite for Extension Pages - withPageConfig()
Source: https://context7.com/jonghakseo/chrome-extension-boilerplate-react-vite/llms.txt
Applies standard Vite configuration for extension pages, including React plugin, HMR, and optimized build settings. Uses '@extension/vite-config'.
```typescript
// pages/popup/vite.config.mts
import { defineConfig } from 'vite';
import { withPageConfig } from '@extension/vite-config';
import { resolve } from 'path';
const rootDir = resolve(__dirname);
const srcDir = resolve(rootDir, 'src');
export default withPageConfig({
resolve: {
alias: {
'@src': srcDir
}
},
publicDir: resolve(rootDir, 'public'),
build: {
outDir: resolve(rootDir, '..', '..', 'dist', 'popup'),
rollupOptions: {
input: {
index: resolve(srcDir, 'index.html')
}
}
}
});
// Includes by default:
// - React plugin with fast refresh
// - HMR plugin for development
// - Node polyfills
// - Source maps in dev mode
// - Minification in production
// - External 'chrome' global
```
--------------------------------
### Export shadcn Button Component
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/ui/README.md
Exports the shadcn button component from the UI package's index file. This makes the component available for import in other parts of the extension.
```TypeScript
export * from './lib/components/ui/button';
```
--------------------------------
### Inject React App with Shadow DOM - initAppWithShadow()
Source: https://context7.com/jonghakseo/chrome-extension-boilerplate-react-vite/llms.txt
Injects a React application into web pages using Shadow DOM for CSS isolation. Prevents style conflicts between the extension and the host page. Requires '@extension/shared'.
```typescript
import { initAppWithShadow } from '@extension/shared';
import inlineCss from '../../../dist/all/index.css?inline';
function MyContentApp() {
const { isLight } = useStorage(exampleThemeStorage);
return (
Extension Panel
);
}
// Inject into page with isolated styles
initAppWithShadow({
id: 'my-extension-root',
app: ,
inlineCss // Inline CSS from Vite build
});
// Shadow DOM prevents host page styles from affecting extension
// and extension styles from leaking to host page
// Works on both Chrome and Firefox (uses fallback for Firefox)
```
--------------------------------
### Convert Chrome Manifest V3 to Firefox - ManifestParser.convertManifestToString()
Source: https://context7.com/jonghakseo/chrome-extension-boilerplate-react-vite/llms.txt
Converts Chrome Manifest V3 to a Firefox-compatible format using '@extension/dev-utils'. Handles differences in background scripts, options pages, and unsupported features.
```typescript
import { ManifestParser } from '@extension/dev-utils';
import manifest from './manifest';
// Convert for Firefox
const firefoxManifest = ManifestParser.convertManifestToString(
manifest,
true // isFirefox = true
);
// Conversions applied:
// Chrome: background.service_worker → Firefox: background.scripts
// Chrome: options_page → Firefox: options_ui with open_in_tab
// Removes: side_panel, sidePanel permission (Chrome-only)
// Adds: Firefox CSP and browser_specific_settings
// Use in build process:
// pnpm build → Chrome manifest
// pnpm build:firefox → Firefox manifest (auto-converted)
// Both builds from single manifest.ts source
```
--------------------------------
### Set Global Environment Variable via CLI
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/env/README.md
Describes how to set environment variables globally via the command-line interface (CLI) using `pnpm set-global-env`. Variables must be prefixed with `CLI_CEB_`.
```bash
pnpm set-global-env CLI_CEB_NEXT_VALUE=new_data
```
--------------------------------
### Access Environment Variables in TypeScript
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/env/README.md
Demonstrates how to access environment variables defined in the .env file using `process.env`. It showcases both bracket notation and dot notation, with preference for bracket notation for IDE autofill support.
```typescript
console.log(process.env['CEB_EXAMPLE']);
```
```typescript
console.log(process.env.CEB_EXAMPLE);
```
--------------------------------
### Content Script with React UI for Chrome Extension
Source: https://context7.com/jonghakseo/chrome-extension-boilerplate-react-vite/llms.txt
This TypeScript code defines a content script that injects a React application into web pages. It utilizes Shadow DOM for style isolation and communicates with the background service worker to fetch and update data. It also listens for theme updates from the background.
```typescript
// pages/content-ui/src/matches/github/index.tsx
import { initAppWithShadow } from '@extension/shared';
import inlineCss from '../../../dist/github/index.css?inline';
import App from './App';
initAppWithShadow({
id: 'github-extension-root',
app: ,
inlineCss
});
// pages/content-ui/src/matches/github/App.tsx
import { useEffect, useState } from 'react';
import { useStorage } from '@extension/shared';
import { exampleThemeStorage } from '@extension/storage';
import { t } from '@extension/i18n';
export default function GitHubEnhancer() {
const { isLight } = useStorage(exampleThemeStorage);
const [repoInfo, setRepoInfo] = useState(null);
useEffect(() => {
// Extract repository info from page
const owner = document.querySelector('[itemprop="author"]')?.textContent;
const name = document.querySelector('[itemprop="name"]')?.textContent;
if (owner && name) {
setRepoInfo({ owner, name });
}
// Listen for theme updates from background
chrome.runtime.onMessage.addListener((message) => {
if (message.type === 'THEME_UPDATED') {
console.log('Theme updated:', message.theme);
}
});
}, []);
const analyzeRepo = async () => {
if (!repoInfo) return;
// Send message to background
const response = await chrome.runtime.sendMessage({
type: 'ANALYZE_REPO',
repo: repoInfo
});
console.log('Analysis result:', response);
};
return (
{t('extensionName')}
{repoInfo && (
Owner: {repoInfo.owner}
Repo: {repoInfo.name}
)}
);
}
// Manifest entry:
// {
// matches: ['https://github.com/*'],
// js: ['content-ui/github.iife.js']
// }
```
--------------------------------
### Import Environment Constants in TypeScript
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/env/README.md
Shows how to import pre-defined environment constants from the `@extension/env` module, enabling easy access to boolean values like `IS_DEV`.
```typescript
import { IS_DEV } from '@extension/env';
```
--------------------------------
### Define Placeholders in messages.json
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/i18n/README.md
Explains how to define placeholders within message strings in 'messages.json' files. Placeholders like '$NAME$' or '$1' allow for dynamic content insertion into translated strings.
```json
{
"greeting": {
"description": "Greeting message",
"message": "Hello, My name is $NAME$",
"placeholders": {
"name": {
"content": "$1",
"example": "John Doe"
}
}
},
"hello": {
"description": "Placeholder example",
"message": "Hello $1"
}
}
```
```json
{
"greeting": {
"description": "인사 메시지",
"message": "안녕하세요, 제 이름은 $NAME$입니다.",
"placeholders": {
"name": {
"content": "$1",
"example": "서종학"
}
}
},
"hello": {
"description": "Placeholder 예시",
"message": "안녕 $1"
}
}
```
--------------------------------
### Manage Translations in messages.json
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/i18n/README.md
Illustrates the structure for managing translations using JSON files within the 'locales' directory. Each language has a 'messages.json' file containing key-value pairs for translatable strings.
```json
{
"helloWorld": {
"message": "Hello, World!"
}
}
```
```json
{
"helloWorld": {
"message": "안녕하세요, 여러분!"
}
}
```
--------------------------------
### Implement Error Boundary HOC - TypeScript
Source: https://context7.com/jonghakseo/chrome-extension-boilerplate-react-vite/llms.txt
This snippet shows how to implement an error boundary using the `withErrorBoundary` higher-order component. It provides a fallback UI and error details when a component crashes, enabling graceful error handling. Dependencies: `@extension/shared`.
```typescript
import { withErrorBoundary } from '@extension/shared';
function ErrorFallback({ error, resetErrorBoundary }) {
return (
Something went wrong
{error.message}
);
}
function MyComponent() {
// Component that might throw errors
return
Content
;
}
// Wrap component with error boundary
export default withErrorBoundary(MyComponent, ErrorFallback);
// Can combine with Suspense:
import { withSuspense } from '@extension/shared';
export default withErrorBoundary(
withSuspense(MyComponent,
Loading...
),
ErrorFallback
);
```
--------------------------------
### Enable Hot Module Reloading with Vite Plugin - watchRebuildPlugin()
Source: https://context7.com/jonghakseo/chrome-extension-boilerplate-react-vite/llms.txt
A Vite plugin for development that enables hot module reloading. Supports both page refresh and full extension reload modes. Automatically reloads the extension when code changes.
```typescript
// In vite.config.ts for extension pages (popup, options, etc.)
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { watchRebuildPlugin } from '@extension/hmr';
export default defineConfig({
plugins: [
react(),
watchRebuildPlugin({
refresh: true // Refresh page on rebuild
})
]
});
// In vite.config.ts for background script
export default defineConfig({
plugins: [
watchRebuildPlugin({
reload: true // Reload entire extension on rebuild
})
]
});
// HMR server runs on ws://localhost:8081
// Development workflow:
// 1. Run: pnpm dev
// 2. Edit any file
// 3. Extension auto-reloads with changes
// 4. No manual reload needed
```
--------------------------------
### Use 't' function with Placeholders in TypeScript
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/i18n/README.md
Demonstrates how to use the 't' function with placeholders in TypeScript. It shows how to pass single values or arrays of values to replace placeholders in translated strings, mirroring the functionality of `chrome.i18n.getMessage`.
```typescript
import { t } from '@extension/i18n';
console.log(t('greeting', 'John Doe')); // Hello, My name is John Doe
console.log(t('greeting', ['John Doe'])); // Hello, My name is John Doe
console.log(t('hello')); // Hello
console.log(t('hello', 'World')); // Hello World
console.log(t('hello', ['World'])); // Hello World
```
--------------------------------
### Subscribe to Storage Changes with useStorage() - React TypeScript
Source: https://context7.com/jonghakseo/chrome-extension-boilerplate-react-vite/llms.txt
The `useStorage` React hook provides a declarative way to subscribe to storage changes, automatically triggering re-renders when storage values are updated. It integrates seamlessly with Suspense for handling asynchronous loading states and ensures data consistency across all extension pages. This hook simplifies state management within React components.
```typescript
import { useStorage } from '@extension/shared';
import { exampleThemeStorage } from '@extension/storage';
function ThemeComponent() {
// Automatically re-renders when storage changes
const { theme, isLight } = useStorage(exampleThemeStorage);
const toggleTheme = async () => {
await exampleThemeStorage.set(prev => ({
theme: prev.theme === 'light' ? 'dark' : 'light',
isLight: prev.theme === 'dark'
}));
};
return (
Current theme: {theme}
);
}
// Wrap with Suspense for loading states
import { withSuspense } from '@extension/shared';
export default withSuspense(
ThemeComponent,
Loading theme...
);
```
--------------------------------
### Translate String using 't' function in TypeScript
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/i18n/README.md
Demonstrates how to import and use the 't' function from the '@extension/i18n' package in TypeScript to translate a given message key. This is useful for simple text translations in your application's logic.
```typescript
import { t } from '@extension/i18n';
console.log(t('loading')); // Loading...
```
--------------------------------
### Type-Safe Internationalization with t() - TypeScript
Source: https://context7.com/jonghakseo/chrome-extension-boilerplate-react-vite/llms.txt
The `t()` function provides type-safe internationalization (i18n) with compile-time validation across all supported locales. It handles translation placeholders and automatically detects the user's browser locale. For optimal performance in production, it leverages Chrome's native i18n API. The locale files are structured in JSON format.
```typescript
import { t } from '@extension/i18n';
// Simple translation
console.log(t('toggleTheme')); // "Toggle theme"
// With single placeholder
console.log(t('greeting', 'John Doe')); // "Hello, My name is John Doe"
// With multiple placeholders
console.log(t('hello', 'World')); // "Hello World"
// Locale files structure:
// packages/i18n/locales/en/messages.json
{
"toggleTheme": {
"description": "Toggle theme button text",
"message": "Toggle theme"
},
"greeting": {
"description": "Greeting with name",
"message": "Hello, My name is $NAME$",
"placeholders": {
"name": {
"content": "$1",
"example": "John Doe"
}
}
}
}
// packages/i18n/locales/ko/messages.json
{
"toggleTheme": {
"message": "테마 전환"
},
"greeting": {
"message": "안녕하세요, 제 이름은 $NAME$입니다"
}
}
```
--------------------------------
### Translate String using 't' function in JSX
Source: https://github.com/jonghakseo/chrome-extension-boilerplate-react-vite/blob/main/packages/i18n/README.md
Shows how to use the 't' function within JSX components to dynamically translate text, such as button labels. This allows for localized UI elements in React applications.
```jsx
import { t } from '@extension/i18n';
const Component = () => {
return (
);
};
```
=== COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.