Skip to main content

Extension Manifest

CRXJS parses the manifest to discover what entry files your extension uses. Because we import the manifest into the Vite config, you can use JSON, JavaScript, or TypeScript.


CRXJS exports a helper function called defineManifest. It's similar to Vite's defineConfig and supports autocompletion and dynamic or async definitions.

Did you know?

Chrome Extensions don't use Semver. Read more about the Chrome Extension version format in the Google Developer Docs.

The following example uses the version from package.json and dynamically sets the name depending on Vite's mode.

import { defineManifest } from '@crxjs/vite-plugin'
import packageJson from './package.json'
const { version } = packageJson

// Convert from Semver (example: 0.1.0-beta6)
const [major, minor, patch, label = '0'] = version
// can only contain digits, dots, or dash
.replace(/[^\d.-]+/g, '')
// split into version parts

export default defineManifest(async (env) => ({
manifest_version: 3,
env.mode === 'staging'
? '[INTERNAL] CRXJS Power Tools'
: 'CRXJS Power Tools',
// up to four numbers separated by dots
version: `${major}.${minor}.${patch}.${label}`,
// semver is OK in "version_name"
version_name: version,

Manifest Paths

Paths inside the manifest are relative to the Vite project root, so the location of the manifest file doesn't matter.

Use paths that start with a letter
"options_page": "options.html",
"devtools_page": "pages/devtools.html"
Don't use relative or absolute paths
"options_page": "./options.html",
"devtools_page": "/root/user/.../devtools.html"

JSON Schema

If you're using a JSON file, consider using a schema like the one at JSON Schema Store to take advantage of autocompletion and validation.

You can configure VSCode to use a JSON schema by adding this to your settings file:

"json.schemas": [
"fileMatch": ["manifest.json"],
"url": ""