### 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 (
Extension Logo

{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.