Manifest.json
The manifest.json is generated at build-time based on files in the entrypoints/
directory and wxt.config.ts
.
Configuration
While entrypoints are generated and added to the manifest at build-time, you can customize or add to your manifest.json
in the config file.
// wxt.config.ts entrypoint of your extension
import { defineConfig } from 'wxt';
export default defineConfig({
manifest: {
host_permissions: ['*://google.com/*'],
content_security_policy: {
// ...
},
},
});
name
If not provided via the manifest
config, the manifest's name
defaults to your package.json's name
property.
version
and version_name
The manifest's version
and version_name
properties are based on the version
field listed in your package.json
or wxt.config.ts
.
version_name
is the exact string listed in yourpackage.json
orwxt.config.ts
fileversion
is the string cleaned up, with any invalid suffixes removed
If a version is not found, a warning is logged and the version defaults to "0.0.0"
.
Example
// package.json
{
"version": "1.3.0-alpha2"
}
// .output/<dir>/manifest.json
{
"version": "1.3.0",
"version_name": "1.3.0-alpha2"
}
icons
By default, WXT will discover icons in your public
directory and use them for the manifest's icons
.
public/
├─ icon-16.png
├─ icon-24.png
├─ icon-48.png
├─ icon-96.png
└─ icon-128.png
Icon files need to match the following regex to be automatically included in the manifest. Most design software can output icons in one of these formats
const iconRegex = [
/^icon-([0-9]+)\.png$/, // icon-16.png
/^icon-([0-9]+)x[0-9]+\.png$/, // icon-16x16.png
/^icon@([0-9]+)w\.png$/, // icon@16w.png
/^icon@([0-9]+)h\.png$/, // icon@16h.png
/^icon@([0-9]+)\.png$/, // icon@16.png
/^icons?[\/\\]([0-9]+)\.png$/, // icon/16.png | icons/16.png
/^icons?[\/\\]([0-9]+)x[0-9]+\.png$/, // icon/16x16.png | icons/16x16.png
];
If you prefer to use filenames in a different format, you can add the icons manually in your wxt.config.ts
file:
export default defineConfig({
manifest: {
icons: {
16: '/extension-icon-16.png',
24: '/extension-icon-24.png',
48: '/extension-icon-48.png',
96: '/extension-icon-96.png',
128: '/extension-icon-128.png',
},
},
});
permissions
Permissions must be listed in the manifest config.
export default defineConfig({
manifest: {
permissions: ['storage', 'tabs'],
},
});
Localization
Similar to the icon, the _locales
directory should be placed inside the the WXT's public
directory.
public/
└─ _locales/
├─ en/
│ └─ messages.json
├─ es/
│ └─ messages.json
└─ ko/
└─ messages.json
Then you'll need to explicitly override the name
and description
properties in your config for them to be localized.
export default defineConfig({
manifest: {
name: '__MSG_extName__',
description: '__MSG_extDescription__',
default_locale: 'en',
},
});
See the official localization examples for more details:
- Loading...
Per-Manifest Version Config
WXT applies several transformations to your manifest to simplify managing both MV2 and MV3 keys in your wxt.config.ts
file:
- Top level MV2-only or MV3-only keys are stripped from the final manifest when targeting the other manifest version
- Some keys, are automatically converted between versions when possible:
- Define
web_accessible_resources
in it's MV3 style and it will be converted to the MV2 style automatically action
will automatically be converted tobrowser_action
for MV3. To usepage_action
instead, add bothaction
andpage_action
entries to your manifest
- Define
For example, a wxt.config.ts
file that looks like this:
import { defineConfig } from 'wxt';
export default defineConfig({
mainfest: {
action: {
default_title: 'Some Title',
},
web_accessible_resources: [
{
matches: ['*://*.google.com/*'],
resources: ['icon/*.png'],
},
],
},
});
Will be output differently for each manifest version:
{
"manifest_version": 2,
// ...
"browser_action": {
"default_title": "Some Title"
},
"web_accessible_resources": ["icon/*.png"]
}
{
"manifest_version": 3,
// ...
"action": {
"default_title": "Some Title"
},
"web_accessible_resources": [
{
"matches": ["*://*.google.com/*"],
"resources": ["icon/*.png"]
}
]
}
TIP
If this isn't enough control for your use-case, remember you can use a function for the manifest
key and generate it however you'd like, or you can use the build:manifestGenerated
hook to apply additional transformations.
Per-Browser Configuration
The manifest
field can be a function. If you are building and extension for multiple browsers, and need to modify the manifest per browser, using a function instead of an object is very useful.
export default defineConfig({
manifest: ({ browser, manifestVersion, mode, command }) => {
return {
// Your manifest
};
},
});
INFO
The first argument is of type ConfigEnv
. See the API reference for info about each property.
For example, say you use OAuth, and you need to provide a different oauth.client_id
for each browser:
const clientIds = {
chrome: '<your-chrome-client-id>',
edge: '<your-edge-client-id>',
firefox: '<your-firefox-client-id>',
opera: '<your-opera-client-id>',
};
export default defineConfig({
manifest: ({ browser }) => ({
oauth: {
client_id: clientIds[browser],
scopes: [
// ...
],
},
}),
});