defineManifest() is a helper function that provides TypeScript type checking and IntelliSense for your Chrome Extension manifest configuration. It validates file paths and ensures your manifest follows the correct structure.
Usage
import { defineManifest } from '@crxjs/vite-plugin'
import pkg from './package.json'
export default defineManifest({
manifest_version: 3,
name: pkg.name,
version: pkg.version,
icons: {
48: 'public/logo.png',
},
action: {
default_icon: {
48: 'public/logo.png',
},
default_popup: 'src/popup/index.html',
},
content_scripts: [{
js: ['src/content/main.tsx'],
matches: ['https://*/*'],
}],
})
Function Signature
function defineManifest<T extends string>(
manifest: ManifestV3Options<T>
): ManifestV3Export
The manifest configuration object, async manifest, or function that returns a manifest.
Parameters
The manifest parameter accepts three forms:
Static Manifest Object
export default defineManifest({
manifest_version: 3,
name: 'My Extension',
version: '1.0.0',
// ... other fields
})
Async Manifest
export default defineManifest(Promise.resolve({
manifest_version: 3,
name: 'My Extension',
version: '1.0.0',
}))
Dynamic Manifest Function
import type { ConfigEnv } from 'vite'
export default defineManifest((env: ConfigEnv) => ({
manifest_version: 3,
name: env.mode === 'production' ? 'My Extension' : 'My Extension (Dev)',
version: '1.0.0',
}))
File Path Validation
defineManifest() provides compile-time validation for file paths using TypeScript’s type system. File paths must:
- Be relative to the Vite project root (where
vite.config.js is located)
- NOT start with
./, /, or \
- Include a file extension
Valid File Paths
export default defineManifest({
manifest_version: 3,
name: 'My Extension',
version: '1.0.0',
action: {
default_popup: 'src/popup.html', // ✓ Valid
},
background: {
service_worker: 'src/background.js', // ✓ Valid
},
content_scripts: [{
js: ['src/content.js'], // ✓ Valid
css: ['assets/content.css'], // ✓ Valid
matches: ['https://*/*'],
}],
})
Invalid File Paths
export default defineManifest({
manifest_version: 3,
name: 'My Extension',
version: '1.0.0',
action: {
default_popup: './src/popup.html', // ✗ Starts with ./
},
background: {
service_worker: '/src/background.js', // ✗ Starts with /
},
})
Supported Manifest Fields
defineManifest() supports all Manifest V3 fields with enhanced type checking for file paths in the following fields:
Extension icons with size keys (16, 48, 128, etc.)icons: {
16: 'assets/icon-16.png',
48: 'assets/icon-48.png',
128: 'assets/icon-128.png',
}
Browser action configurationaction: {
default_icon: {
48: 'assets/icon.png'
},
default_popup: 'src/popup.html',
default_title: 'My Extension'
}
background
ChromeManifestBackground | FirefoxManifestBackground
Background script configurationChrome (Service Worker):background: {
service_worker: 'src/background.js',
type: 'module' // Optional: for ES modules
}
Firefox (Scripts):background: {
scripts: ['src/background.js'],
persistent: false
}
Content script configurationscontent_scripts: [{
matches: ['https://*/*'],
js: ['src/content.js'],
css: ['src/content.css'],
run_at: 'document_end',
all_frames: false,
world: 'ISOLATED' // or 'MAIN' (no HMR support in MAIN)
}]
Content scripts with world: 'MAIN' do NOT support CRXJS HMR.
DevTools page HTML filedevtools_page: 'src/devtools.html'
Options page HTML fileoptions_page: 'src/options.html'
Input method editor componentsinput_components: [{
name: 'My IME',
options_page: 'src/ime-options.html'
}]
Return Type
type ManifestV3Export =
| ManifestV3
| Promise<ManifestV3>
| ((env: ConfigEnv) => ManifestV3 | Promise<ManifestV3>)
The function returns the manifest in the same form it was provided (object, promise, or function), enabling all three usage patterns.
TypeScript Types
ManifestV3Options
type ManifestV3Options<T extends string> =
| ManifestOptions<T>
| Promise<ManifestOptions<T>>
| ManifestV3Define<T>
ManifestV3Define
type ManifestV3Define<T extends string> = (
env: ConfigEnv
) => ManifestOptions<T> | Promise<ManifestOptions<T>>
ManifestFilePath
type ManifestFilePath<T extends string> =
IsStringLiteral<T> extends true
? LiteralManifestFilePath<T>
: T
This type enforces that file paths:
- Don’t start with
., /, or \
- Include a file extension
Environment-Specific Manifests
Use the function form to access Vite’s build environment:
import { defineManifest } from '@crxjs/vite-plugin'
import type { ConfigEnv } from 'vite'
export default defineManifest((env: ConfigEnv) => {
const isDev = env.mode === 'development'
return {
manifest_version: 3,
name: isDev ? 'My Extension (Dev)' : 'My Extension',
version: '1.0.0',
permissions: isDev
? ['tabs', 'storage', 'debugger']
: ['tabs', 'storage'],
action: {
default_popup: 'src/popup.html',
},
}
})