Compare commits

...

781 Commits

Author SHA1 Message Date
github-actions[bot] 9757e2634f chore(release): wxt v0.20.24
📼 VHS / Create VHS (push) Waiting to run
2026-04-17 14:32:45 +00:00
John Wong 42b55f66fb fix: Correct actionKey for Firefox in MV3 (#2274) 2026-04-17 14:12:37 +00:00
aklinker1 e64058bc94 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2026-04-17 00:50:56 +00:00
github-actions[bot] 386503cce0 chore(release): wxt v0.20.23
📼 VHS / Create VHS (push) Waiting to run
2026-04-16 18:00:00 +00:00
Aaron 6224ff49f6 fix: Use correct color name
Addresses
https://github.com/wxt-dev/wxt/issues/2180#issuecomment-4259430737
2026-04-16 12:55:55 -05:00
aklinker1 6578be00ce fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2026-04-15 00:51:40 +00:00
Aaron 2f325d898f docs: Re-structure the WXT Modules documentation (#2260) 2026-04-14 12:28:45 -05:00
github-actions[bot] b039c599c8 chore(release): wxt v0.20.22
📼 VHS / Create VHS (push) Waiting to run
2026-04-14 14:38:40 +00:00
Aaron bec4b73839 fix: Apply expanded env to process.env (#2267) 2026-04-14 09:33:36 -05:00
aklinker1 e67bac0868 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2026-04-14 00:51:06 +00:00
Aaron 24ff92068d ci: Update lockfile with new version during release
Without this, the lockfile becomes out-of-date and CI fails after a
release.
2026-04-13 18:56:52 -05:00
Aaron 6e20036d6c fix: Skip applying esbuild.charset=ascii vite 8 (#2264) 2026-04-13 18:54:14 -05:00
offish b6059cfe4a docs: Add TF2 Trader to the list of extensions (#2213) 2026-04-13 11:31:42 -05:00
Aaron 4a305a2726 feat: Add dev.server.strictPort option (#2261) 2026-04-13 11:31:09 -05:00
Patryk Kuniczak 4ae6d8135f fix: Scripts injection for MV2 (#2232) 2026-04-13 13:47:24 +00:00
Suvesh Moza 225a94199c feat: add support for Firefox data collection permissions (#1976)
Co-authored-by: Patryk Kuniczak <p.kuniczak@gmail.com>
Co-authored-by: Aaron <aaronklinker1@gmail.com>
Co-authored-by: Nick Doan <nickbar01234@gmail.com>
Co-authored-by: Tam Dang <139360620+dahomita@users.noreply.github.com>
2026-04-13 13:34:46 +00:00
GuaGua 35ffa00bae docs: fix Read Frog Firefox showcase link (#2256)
Co-authored-by: frogGuaGuaGuaGua <268840081+frogGuaGuaGuaGua@users.noreply.github.com>
2026-04-13 12:28:53 +00:00
github-actions[bot] 58e11d3c06 chore(release): wxt v0.20.21
📼 VHS / Create VHS (push) Waiting to run
2026-04-13 06:03:28 +00:00
Aaron fddd7c14ee ci: Fix bump-package-version script 2026-04-13 00:59:01 -05:00
Aaron 7d755f215f ci: Add back postinstall scripts 2026-04-13 00:45:54 -05:00
Aaron 7e473375e5 ci: Add warning to debug release script 2026-04-13 00:42:46 -05:00
Aaron 08b9ea6e47 ci: Skip postisntall scripts on windows runner in validate workflow
They're failing 50% of the time for some reason... This is just a test
change.
2026-04-13 00:42:46 -05:00
Aaron 245aea4ce8 ci: Enable bun package manager tests on windows (#2253) 2026-04-13 00:27:13 -05:00
Aaron e1e41c20ea ci: Fix version bump script 2026-04-13 00:24:13 -05:00
Aaron e16052cdc9 docs: Move homepage extensions to separate YAML file (#2255) 2026-04-13 00:12:22 -05:00
Kamer DINC de2b38217a docs: Add AlarmBot extension to the list of extensions (#2251)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-04-13 04:42:59 +00:00
Sullivan b2a099689f docs: Added "SoundCloud Enhanced Pro" to the homepage (#2238)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-04-13 04:39:21 +00:00
Skylar Bolton 42c8a02ef9 docs: Add 5 Whiteboard Works extensions to the homepage (#2207)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-04-13 04:33:50 +00:00
Skylar Bolton 32058027f3 docs: Add Firefox Add-on support to homepage showcase (#2208)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-04-13 04:24:29 +00:00
Aaron 99fc685e14 ci: Don't post thank you message on closed PRs for maintainers and bots (#2250) 2026-04-12 23:16:51 -05:00
Aaron 414117b9e6 chore: Fix flakey test (#2254) 2026-04-12 23:11:19 -05:00
Aaron 799bd92b28 docs: Fix non-replaced {{version}} in CLI reference 2026-04-12 22:50:42 -05:00
Aaron d7cc8dc229 docs: Fix deploy command after bun upgrade 2026-04-12 22:45:54 -05:00
Aaron f4fa36a0ab chore: Use bun run --sequential to simplify package scripts (#2252) 2026-04-12 22:35:20 -05:00
Aaron 4d5eb28cb4 chore: Migrate monorepo to use Bun instead of PNPM (#2009)
Co-authored-by: Okinea Dev <hi@okinea.dev>
2026-04-12 22:17:20 -05:00
Vaughn Bosu a008426317 fix: add Firefox action manifest typings (#2217) 2026-04-12 20:31:16 +00:00
Aaron 2a212790b6 refactor: Rename internal popup mv2Key option to actionType (#2249) 2026-04-12 11:15:43 -05:00
dependabot[bot] 09f27a902a chore(deps): bump actions/setup-go from 6.0.0 to 6.4.0 (#2219)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-12 10:50:17 -05:00
dependabot[bot] 6cbbca9e92 chore(deps): bump hookable from 6.0.1 to 6.1.0 (#2222)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-12 15:50:01 +00:00
dependabot[bot] f1fd8fc38b chore(deps): bump oven-sh/setup-bun from 2.1.2 to 2.2.0 (#2220)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-12 10:49:59 -05:00
dependabot[bot] a67e1b81e1 chore(deps): bump docker/login-action from 3.6.0 to 4.0.0 (#2221)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-12 10:49:38 -05:00
dependabot[bot] 936c5f7fda chore(deps-dev): bump vitepress-plugin-llms from 1.11.0 to 1.12.0 (#2225)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-12 15:49:29 +00:00
dependabot[bot] ab3151f924 chore(deps): bump codecov/codecov-action from 5.5.2 to 6.0.0 (#2223)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-12 10:48:54 -05:00
dependabot[bot] d4fb318381 chore(deps): bump filesize from 11.0.13 to 11.0.15 (#2226)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-12 15:44:49 +00:00
dependabot[bot] 31a7b5892e chore(deps-dev): bump vitepress-plugin-group-icons from 1.7.1 to 1.7.3 (#2227)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-12 10:42:29 -05:00
dependabot[bot] c469f0e85a chore(deps-dev): bump eslint from 10.0.2 to 10.1.0 (#2224)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-04-12 10:42:03 -05:00
SmAsHeD 355d36a838 fix: Support page_action for Firefox MV3 (#2200)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-04-12 10:37:57 -05:00
Patryk Kuniczak 43e46477df chore: Add dev scripts for Firefox in wxt-demo package.json (#2234) 2026-04-12 10:32:12 -05:00
Patryk Kuniczak 34a235fc68 chore: Create content.ts for wxt-demo to test injection (#2233) 2026-04-12 10:12:48 -05:00
eupthere ce9f9af980 fix: Support template literals in prepare:publicPaths (#2248)
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-04-12 13:22:16 +00:00
Ofer Itzhaki 5f799ca23e feat: auto-discover Firefox theme_icons from public assets (#2242)
Co-authored-by: oferitz <oferitz@Ofers-MacBook-Pro.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-04-11 20:37:50 +00:00
Aaron 0159b4315e feat: Add Brave browser to KnownTarget type (#2247) 2026-04-11 15:13:51 -05:00
eupthere 864d7a0bfd chore: replace picocolors with builtins (#2210)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-04-11 19:59:37 +00:00
Ofer Itzhaki fa698266b3 feat: type /_favicon/ paths when favicon permission is declared (#2241)
Co-authored-by: oferitz <oferitz@Ofers-MacBook-Pro.local>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-11 17:33:55 +00:00
Patryk Kuniczak ba96bbd8ff docs: fix undocumented constants link from 0.14.0 -> 0.15.0 migration guide (#2244) 2026-04-11 10:03:50 -05:00
Skylar Bolton 20d5e3310a fix: resolve TS build errors in manifest.ts options_ui (#2237)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Patryk Kuniczak <p.kuniczak@gmail.com>
2026-04-11 09:27:44 +02:00
Aaron 70fdb04db5 docs: Add Artemis II photo to hero section
Because it's cool!
2026-04-10 17:12:00 -05:00
aklinker1 65c3c7eba9 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2026-04-09 00:39:21 +00:00
aklinker1 98e218042d fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2026-04-04 00:42:13 +00:00
alexharding-ux 8a56f73c7c fix: resolve url: imports in Vite 8 (#2218) 2026-04-01 16:47:43 +00:00
Aaron ffdd15e275 chore: Sort cspell ignore list 2026-03-28 11:49:41 -05:00
Aaron 8f71e174cb chore: Use deps.neverBundle instead of external
tsdown has deprecated `external` in favor of `deps.neverBundle`.
2026-03-28 11:49:11 -05:00
Aaron 6621aaf877 chore: Add cspell and fix all typos 2026-03-28 11:45:47 -05:00
Aaron c528361d07 fix: Output content scripts in ascii to avoid utf8 encoding errors (#2204)
Co-authored-by: Jorge Fuentes <jsfuentes@users.noreply.github.com>
2026-03-19 16:18:09 -05:00
Aaron 5376cfd6a9 docs: Simplify storage docs 2026-03-19 11:26:20 -05:00
Aaron 76615b9262 chore: Remove useless engines field from monorepo package.json 2026-03-19 09:31:27 -05:00
Aaron ce551fbdb0 fix: Add engines field to WXT's package.json
Includes the currently supported versions of NodeJS and Bun.

This closes #2198
2026-03-19 09:27:59 -05:00
Aaron 108e790cf8 ci: Fix commit step in VHS workflow 2026-03-19 09:16:19 -05:00
github-actions[bot] 0b5424cadb chore(release): @wxt-dev/module-svelte v2.0.5
📼 VHS / Create VHS (push) Waiting to run
2026-03-19 14:06:34 +00:00
Aaron 48571f5032 fix: Update @sveltejs/vite-plugin-svelte version range to support Vite
8
2026-03-19 09:01:44 -05:00
Aaron c6c9f65040 chore: Remove any from i18n's internal types (#2201)
Co-authored-by: Patryk Kuniczak <p.kuniczak@gmail.com>
2026-03-19 09:22:15 +01:00
Harryson ace6c20164 feat: replace dotenv with native node:util parseEnv (#2181)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-03-18 15:04:45 +00:00
Aditi d64b64f39e chore: replace minimatch with picomatch (#2188)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
Co-authored-by: Rizky Mirzaviandy Priambodo <Xavrir@users.noreply.github.com>
2026-03-18 14:22:38 +00:00
Aaron 41a687a63e docs: Add note about adding the browser package as a dependency for
module augmentation
2026-03-17 17:40:48 -05:00
Aaron f4f6704510 docs: Document augmenting the browser type for Firefox (#2199) 2026-03-17 08:44:33 -05:00
github-actions[bot] 65fc0fadb3 chore(release): wxt v0.20.20
📼 VHS / Create VHS (push) Waiting to run
2026-03-17 13:21:45 +00:00
Aaron 64b686713b chore(deps): Add vite-node 6 support 2026-03-17 08:16:33 -05:00
Joseph Hu 9c6d3e37d4 docs: Add Extension Rank Checker to the list of extensions (#2193)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-03-17 08:00:23 -05:00
FJRG2007 ツ 37abe9db39 docs: Add Dymo extension ID to UsingWxtSection.vue (#2187)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-03-17 12:43:08 +00:00
Yue Yang 9ebef4a268 chore: remove useDefineForClassFields from svelte/tsconfig.json (#2190) 2026-03-17 07:37:38 -05:00
Hampus Tågerud e60f7c7e77 fix: unlisted script return values broken with Vite 8 sourcemaps (#2197) 2026-03-17 12:35:22 +00:00
aklinker1 36aadd0604 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2026-03-17 00:39:30 +00:00
github-actions[bot] e4598a5e37 chore(release): @wxt-dev/module-react v1.2.2
📼 VHS / Create VHS (push) Waiting to run
2026-03-14 23:48:01 +00:00
github-actions[bot] db5c22809c chore(release): wxt v0.20.19
📼 VHS / Create VHS (push) Waiting to run
2026-03-14 23:43:04 +00:00
Aaron c61fa8f858 fix: Add @vitejs/plugin-react v6 support 2026-03-14 18:38:33 -05:00
Florian Metz 5fe4681620 chore: replace fs-extra with node:fs/promises (#2174)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-03-06 09:29:49 -06:00
Aaron 80d384361b chore: Update nano-staged precommit command 2026-03-06 09:17:22 -06:00
dagangtj a1e72c0749 chore: replace lint-staged with nano-staged (#2179)
Co-authored-by: Dean <dagangtj@gmail.com>
2026-03-06 15:13:41 +00:00
Aaron e3a80b8247 ci: Re-enable react template validation 2026-03-06 08:54:08 -06:00
github-actions[bot] c0013acadc chore(release): @wxt-dev/module-react v1.2.1
📼 VHS / Create VHS (push) Waiting to run
2026-03-06 14:51:43 +00:00
Aaron f472c53da7 ci: Temporarily disable react template validation 2026-03-06 08:47:58 -06:00
Aaron 032f7931e8 chore: Add prepack script to all packages 2026-03-06 08:43:51 -06:00
github-actions[bot] 57a12c1711 chore(release): @wxt-dev/module-react v1.2.0
📼 VHS / Create VHS (push) Waiting to run
2026-03-06 14:24:19 +00:00
Aaron d13ca3983f chore(deps): Upgdate fs-extra in browser package 2026-03-06 08:19:54 -06:00
aklinker1 9769ce4ac9 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2026-03-06 00:44:23 +00:00
Aaron 55dc263dc9 fix: List eslint 10 as supported 2026-03-05 10:08:02 -06:00
Aaron e56ae23747 chore(deps): Upgrade deps (#2175) 2026-03-05 10:00:41 -06:00
Aaron bfd4af5d69 feat: Vite 8 support 2026-03-05 08:59:58 -06:00
Patryk Kuniczak 9673604878 perf: Use filter to improve plugin performance with rolldown (#1787)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-03-05 08:55:36 -06:00
Florian Metz ae55aecb0d chore: replace fast-glob and ora with lighter alternatives (#2173) 2026-03-04 14:26:11 -06:00
Martin Broder a14d0b4f2f feat: add vitePluginsBefore option (#2170) 2026-03-04 11:39:00 -06:00
Aaron 301e4a17da chore: Add prettier-plugin-jsdoc to project (#2171) 2026-03-03 08:43:04 -06:00
etoome 19cebbf673 docs: Added "isTrust" to the homepage (#2161) 2026-02-27 00:49:06 +00:00
Kuba ef73c07dfe docs: Added "Scrape Similar" to the homepage (#2158) 2026-02-23 13:57:08 +00:00
Aaron ca5ad7e51b chore: Update codeowners 2026-02-22 18:56:12 -06:00
github-actions[bot] 5dab944abc chore(release): wxt v0.20.18
📼 VHS / Create VHS (push) Waiting to run
2026-02-22 23:45:06 +00:00
Aaron adaae6e1a4 fix: Fix submit command (#2157) 2026-02-22 17:29:53 -06:00
Aaron 4524cbdf76 ci: Fix VHS workflow 2026-02-22 17:29:53 -06:00
github-actions[bot] 1171cf52f0 chore(release): @wxt-dev/analytics v0.5.4
📼 VHS / Create VHS (push) Waiting to run
2026-02-22 17:29:53 -06:00
Aaron c5978b1072 fix: Continue using useAppConfig to support older versions of WXT 2026-02-22 17:29:53 -06:00
Aaron e5ef9367ed ci: Fix VHS action (#2155) 2026-02-22 17:29:53 -06:00
github-actions[bot] 0ca908a6cc chore(release): @wxt-dev/analytics v0.5.3
📼 VHS / Create VHS (push) Waiting to run
2026-02-22 17:29:53 -06:00
github-actions[bot] e20c012eb3 chore(release): @wxt-dev/storage v1.2.8
📼 VHS / Create VHS (push) Waiting to run
2026-02-22 17:29:53 -06:00
github-actions[bot] e88df26d7c chore(release): @wxt-dev/auto-icons v1.1.1
📼 VHS / Create VHS (push) Waiting to run
2026-02-22 17:29:53 -06:00
github-actions[bot] 9491e6845e chore(release): @wxt-dev/i18n v0.2.5
📼 VHS / Create VHS (push) Waiting to run
2026-02-22 17:29:53 -06:00
Aaron e4433c4212 ci: Fix scripts/list_unreleased_commits.sh (#2153) 2026-02-22 17:29:53 -06:00
Jonathan Viney c6fdc5a5d5 feat: Add globalName entrypoint option. (#2017) 2026-02-22 17:29:53 -06:00
Aaron 68dd3fc027 docs: Update section in SECURITY.md around reporting vulnerabilities (#2147) 2026-02-22 17:29:53 -06:00
omerfardemir cd7aec6752 fix: auto icons override default icons (#1616)
Co-authored-by: Florian Metz <me@timeraa.dev>
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-22 17:29:53 -06:00
Smit b80556498d fix: Improve background script detection logic for analytics package (#1808)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-22 17:29:53 -06:00
Aaron 38530cdb39 feat: New @wxt-dev/is-background package (#2152)
Co-authored-by: Smit <sm17p@users.noreply.github.com>
2026-02-22 17:29:53 -06:00
Tam Dang 078fd5990e fix(types): include CSS entrypoints in PublicPath generation (#2150)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-22 17:29:53 -06:00
Aaron b4be5feaa6 ci: Fix auto-labeling workflow for forks 2026-02-22 17:29:53 -06:00
Aaron d982f97bd8 feat(modules): Add support for augumenting entrypoint options (#2149) 2026-02-22 17:29:53 -06:00
Aaron 653608c98c docs: Add deep outline to modules page to show recipes 2026-02-22 17:29:53 -06:00
Aaron d63be2d6f3 ci: Create workflow for labeling and adding authors to PRs (#2148) 2026-02-22 17:29:53 -06:00
Nick Doan 4500ca577f fix(types): Add type safety to browser.runtime.executeScript files option (#2142)
Co-authored-by: nickbar01234 <nickbar01234gmail.com>
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-22 17:29:53 -06:00
Aaron cc935daec0 fix: Allow userId option to return undefined 2026-02-22 17:29:53 -06:00
Patryk Kuniczak 51ff46ec58 chore: Created new types, instead of any for analytics (#2119) 2026-02-22 17:29:53 -06:00
Patryk Kuniczak 206b7731cf chore: Remove @ts-expect-error from manifest.test.ts and fix typo (#2123) 2026-02-22 17:29:53 -06:00
Patryk Kuniczak d16f59d33d chore: Simplify imports in wxt/e2e (#2122) 2026-02-22 17:29:53 -06:00
Patryk Kuniczak a5ec046346 chore: Rename zipdir to zipDir (#2126) 2026-02-22 17:29:49 -06:00
Patryk Kuniczak 51dd803115 chore: Remove unnecessary @ts-ignore of builders/vite index.ts (#2127) 2026-02-21 10:47:39 -06:00
Patryk Kuniczak 6e39424a30 chore: Make type for __ENTRYPOINT__ of vitest.globalSetup.ts (#2128) 2026-02-21 10:46:36 -06:00
Anthony Ciccarello 6ca84782aa fix: enable mv3 dev mode with firefox 147 (#2135) 2026-02-21 16:45:04 +00:00
Henrik Wenz ee1ba6369e docs: Add wxt-local-analytics to community resources (#2141) 2026-02-21 16:41:13 +00:00
Aaron f35d70e6fe fix: Correctly update version metadata when setting a value for the first time (#2139)
Co-authored-by: willow <42willow@pm.me>
Co-authored-by: absdjfh <absdjfh@users.noreply.github.com>
2026-02-21 10:39:21 -06:00
sheng zhang 430a3acfeb fix: Add getAppConfig as an alias to useAppConfig (#2144)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-21 15:38:42 +00:00
aklinker1 395c5841f9 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2026-02-21 00:39:02 +00:00
Oleksii 173161ca4d feat: use Navigation API for location change detection with polling fallback (#2136) 2026-02-19 01:21:48 +00:00
Patryk Kuniczak a1a8e14368 feat: Create tests for all func of network.ts (#2132) 2026-02-18 19:14:36 -06:00
qixing-jk 2379806c61 docs: add All API Hub to showcase extensions (#2137) 2026-02-19 00:58:20 +00:00
Muzammil f604208a8b docs: Added "Glossy New Tab" to the homepage (#2133) 2026-02-15 03:48:59 +00:00
Patryk Kuniczak cf31fbec5d chore: add missing async to network.ts (#2107) 2026-02-13 12:18:37 +00:00
github-actions[bot] 279be8deb7 chore(release): @wxt-dev/storage v1.2.7
📼 VHS / Create VHS (push) Waiting to run
2026-02-13 00:01:40 +00:00
github-actions[bot] 7366d8aab7 chore(release): wxt v0.20.17
📼 VHS / Create VHS (push) Waiting to run
2026-02-12 22:35:05 +00:00
Aaron a7ab409d48 fix: Update left-over CJS require of publish-browser-extension to ESM (#2120) 2026-02-12 16:30:47 -06:00
Aaron 9dea0cf3ae chore: Cleanup type tests 2026-02-12 15:53:41 -06:00
Patryk Kuniczak 50d7c1ec80 chore: Change browser tests to fix deprecated warning (#2117)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-12 21:35:27 +00:00
github-actions[bot] f32cdafdf6 chore(release): @wxt-dev/analytics v0.5.2
📼 VHS / Create VHS (push) Waiting to run
2026-02-12 21:08:03 +00:00
Honwhy Wang 2e2272d07a fix: Allow custom API URL in Google Analytics 4 provider options (#1653)
Co-authored-by: Patryk Kuniczak <p.kuniczak@gmail.com>
2026-02-12 13:34:05 -06:00
github-actions[bot] 27ffff7e0a chore(release): wxt v0.20.16
📼 VHS / Create VHS (push) Waiting to run
2026-02-12 19:16:33 +00:00
Aaron 305cebe0d0 fix: Revert "rename name to names prop of rollup to fix deprecated warning (#2106)"
This reverts commit 9470d2b696.
2026-02-12 13:11:36 -06:00
Aaron 4602a068f8 Update contributor in changelog 2026-02-12 13:06:06 -06:00
Aaron 3a947d72c6 chore: Include doc updates in wxt changelog 2026-02-12 13:03:58 -06:00
Aaron 1940e3530f chore: Speed up E2E tests by skipping pnpm install when possible (#2113) 2026-02-11 12:24:36 -06:00
github-actions[bot] dd549dc686 chore(release): wxt v0.20.15
📼 VHS / Create VHS (push) Waiting to run
2026-02-11 07:13:31 +00:00
Nick Doan 3417bd3ed2 feat: Add log --level cli option (#1973)
Co-authored-by: nickbar01234 <nickbar01234gmail.com>
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-11 04:57:27 +00:00
Patryk Kuniczak 9470d2b696 fix: rename name to names prop of rollup to fix deprecated warning (#2106) 2026-02-10 12:23:19 -06:00
Aaron f523a7d31d docs: Add notes about chrome services and feature flags (#2110) 2026-02-10 12:22:18 -06:00
Patryk Kuniczak ea4c2b035b fix: Remove prepublish script of root package.json (#2109) 2026-02-10 10:11:47 +01:00
willow c5bfba837f fix(storage): Set version number on init (#1996) 2026-02-10 01:41:00 +00:00
aklinker1 c5ad957b25 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2026-02-10 00:47:54 +00:00
Patryk Kuniczak cc849e7cea docs: rename keys name of getMetas() to be proper (#2105) 2026-02-09 22:28:49 +01:00
Patryk Kuniczak 22428da54d chore: simplify imports of cli/__tests__/index.ts (#2104) 2026-02-09 20:59:46 +00:00
Patryk Kuniczak f6071f7e2d fix: Change deprecated function presetUno to presetWind3 (#2103) 2026-02-09 21:55:28 +01:00
Aaron 08e8560865 chore: Upgrade PNPM to 10.29.2 (#2102) 2026-02-09 12:46:47 -06:00
Aaron 75f01db543 refactor: Simplify import paths (#2093)
Co-authored-by: Patryk Kuniczak <p.kuniczak@gmail.com>
2026-02-09 02:09:51 -06:00
Aaron 5a028d2551 chore: Remove unused code (#2087)
Co-authored-by: Patryk Kuniczak <p.kuniczak@gmail.com>
2026-02-09 01:45:11 -06:00
Aaron 07a4ba8bc5 fix: Make ExtensionRunner#closeBrowser optional (#2092)
Co-authored-by: Patryk Kuniczak <p.kuniczak@gmail.com>
2026-02-09 01:44:35 -06:00
Aaron f84921f735 chore: Fix typos (#2086)
Co-authored-by: Patryk Kuniczak <p.kuniczak@gmail.com>
2026-02-09 01:39:46 -06:00
Aaron 872494e490 chore: Update JSDoc to use @internal (#2091)
Co-authored-by: Patryk Kuniczak <p.kuniczak@gmail.com>
2026-02-09 01:39:07 -06:00
Aaron d0848b0be5 chore: Cleanup @ts-* comments (#2094)
Co-authored-by: Patryk Kuniczak <p.kuniczak@gmail.com>
2026-02-09 01:38:42 -06:00
Aaron c848956777 chore: Cleanup comment line lengths (#2090)
Co-authored-by: Patryk Kuniczak <p.kuniczak@gmail.com>
2026-02-09 01:38:09 -06:00
Aaron 296997d10e refactor: Cleanup unnecssary checks (#2089)
Co-authored-by: Patryk Kuniczak <p.kuniczak@gmail.com>
2026-02-09 01:37:47 -06:00
Aaron ffdb22238c refactor: async/await cleanup (#2088)
Co-authored-by: Patryk Kuniczak <p.kuniczak@gmail.com>
2026-02-09 01:37:16 -06:00
Aaron a63c320403 refactor: Code cleanup for storage package (#2085)
Co-authored-by: Patryk Kuniczak <p.kuniczak@gmail.com>
2026-02-09 01:36:40 -06:00
Aaron aa86ed78a3 refactor: Code cleanup in analytics package (#2084)
Co-authored-by: Patryk Kuniczak <p.kuniczak@gmail.com>
2026-02-09 01:36:15 -06:00
wotan-allfather 19456ec855 feat(popup): Add Firefox default_area and theme_icons support (#2097)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-09 07:28:26 +00:00
Aaron 2c57840c44 revert: Use uiContainer to apply position when creating shadow root ui (#2036)
This reverts commit 26b7927f62.
2026-02-09 00:44:07 -06:00
Namu 26b7927f62 fix: Use uiContainer to apply position when creating shadow root ui (#2036)
Co-authored-by: Namu <535248+namukang@users.noreply.github.com>
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-09 06:32:35 +00:00
Eli d4267af725 refactor: cleanup esm (#1950)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-09 04:27:51 +00:00
ariasuni 16a2aedcd0 docs: Small improvements for hooks (#2095)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-09 02:46:40 +00:00
Puzant 755f04f777 docs: Added KeyFloat (#2082)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-09 02:43:58 +00:00
Namu cf9539ddab fix: content script is incorrectly invalidated when injected multiple times (#2035)
Co-authored-by: Namu <535248+namukang@users.noreply.github.com>
2026-02-09 02:38:54 +00:00
Aaron 99d558f33c refactor: Standardize file existence checks to pathExists (#2083)
Co-authored-by: Patryk Kuniczak <p.kuniczak@gmail.com>
2026-02-08 15:21:45 -06:00
Patryk Kuniczak 1fe073004b fix: normalize path for createAnalytics of analytics/index.ts (#2013) 2026-02-08 08:05:09 -06:00
Aaron 6ae5fb5edb docs: Fix JSDoc 2026-02-08 08:03:46 -06:00
Patryk Kuniczak 3a3953edf6 feat: Export normalizePath from wxt module (#2080) 2026-02-08 08:18:49 +00:00
rxliuli c8e788eaf8 docs: Add blog post resource for building browser extensions (#2077) 2026-02-07 13:40:14 +00:00
Aaron 088a44496d docs: Add llms.txt to documentation site (#1725) 2026-02-06 16:38:37 -06:00
Aaron 60a57c5abc chore: Fix markdownlint issues 2026-02-06 16:34:08 -06:00
Aaron 482466bbbf docs: Update MAINTAINERS.md
Added an example of how to ask for a bug reproduction.
2026-02-06 15:10:11 -06:00
Aaron 65deb7317b chore: Upgrade github actions (#2073) 2026-02-06 14:14:19 -06:00
Patryk Kuniczak 00ae061822 chore: fix recognize lack of argument for scripts (#2015) 2026-02-06 14:04:14 -06:00
Aaron 9bd7fc1bd5 chore: Don't report unreleased chore/doc commits 2026-02-06 13:36:04 -06:00
Aaron 98ddb83f1d docs: Add PR guidelines for small and targeted changes 2026-02-06 10:55:00 -06:00
Aaron 6dd8b9d072 docs: Add MAINTAINERS.md file for notes specific to maintainers 2026-02-06 10:41:57 -06:00
github-actions[bot] 1e3482a878 chore(release): wxt v0.20.14
📼 VHS / Create VHS (push) Waiting to run
2026-02-06 15:56:04 +00:00
Aaron 734846843f ci: Update templates when bumping WXT version
This closes #2018
2026-02-06 09:51:10 -06:00
Aaron f1eac66494 chore: Fix markdown lint errors 2026-02-06 09:33:06 -06:00
Aaron b4c3280f58 docs: Add new sections to CONTRIBUTING.md
Added sections on WXT's vision, breaking changes policy, and becoming a maintainer.
2026-02-06 09:31:19 -06:00
Invictus Navarchus b2f2998767 chore: update wxt version to ^0.20.13 in all templates (#2019)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-05 19:36:50 -06:00
blurredart 720eb93c67 docs: add missing import in code sample for configuration (#2057)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-05 17:31:56 -06:00
dareka cdf8611e0b fix: MaxListenersExceededWarning (#2058) 2026-02-05 17:31:44 -06:00
Scan 905d797b65 docs: Add Margin extension to extensions using wxt (#2060)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-05 17:22:09 -06:00
tsubasa-ito 6ca8ccc332 docs: add Lofi BGM Player to example projects (#2056)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-05 17:21:18 -06:00
Nazım Gediz Aydındoğmuş 76496e8865 docs: Added "Teams Chat Exporter" to the homepage (#2050)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-05 17:20:15 -06:00
Muzammil f38fec8588 docs: Added "Capture It - Capture & Edit Screenshots" to the homepage (#2033)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2026-02-05 17:18:40 -06:00
Ilya Kubariev 4351ac9657 fix: Add .jsonc support for locale files to match docs (#2066) 2026-02-05 17:17:26 -06:00
Mark f3834ac0e2 fix(content-script-context): handle undefined browser.runtime (#2042) 2026-02-05 17:17:16 -06:00
ariasuni 48891a7ca5 fix: rename and make firefoxPrefs in web-ext.config.ts work (#2068) 2026-02-05 17:16:58 -06:00
Aaron 3b6a4aa635 chore: Refresh lockfile and upgrade subdependencies (#2071) 2026-02-05 17:10:47 -06:00
Aaron b20f0471c2 chore: Upgrade major deps (#2070) 2026-02-05 16:57:49 -06:00
Aaron 0f9e66e1e8 chore: Update dependencies (#2069) 2026-02-05 16:37:13 -06:00
Aaron 6fb4cee43f fix: Remove failing test 2026-02-05 16:13:03 -06:00
aklinker1 0e8afbbf56 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2026-02-04 00:37:48 +00:00
aklinker1 83decf7bf5 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2026-01-22 00:35:56 +00:00
aklinker1 5c77cf23b8 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2026-01-21 00:35:03 +00:00
aklinker1 606fd3164c fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2026-01-19 00:36:13 +00:00
aklinker1 71308d0d6f fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2026-01-11 00:37:39 +00:00
Patryk Kuniczak 8bbea7cda4 docs: Fix alignment of 2 last comments of regex patterns (#2012) 2025-12-23 09:42:43 -06:00
Aaron a87d3e4809 chore: Move script-only dev dependencies to top-level package.json (#2007) 2025-12-18 00:28:49 -06:00
Aaron 1f3db58254 chore: Use tsdown to build packages (#2006) 2025-12-18 00:02:19 -06:00
Aaron 43f6c06271 Update out-of-date lockfile 2025-12-17 21:30:07 -06:00
aklinker1 04ae542b13 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-12-17 00:32:12 +00:00
bohuslavsemenov f97c81df0d feat: add onBeforeMount callback to createIframeUi options (#1899)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-12-16 17:13:33 -06:00
github-actions[bot] b7b3fc53eb chore(release): wxt v0.20.13
📼 VHS / Create VHS (push) Waiting to run
2025-12-16 23:10:49 +00:00
rxliuli 4b44fb849d fix: Don't return promises from unlisted scripts that do not have an async main function (#1907)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-12-16 16:58:46 -06:00
Dan McGee 5d0a266e9c fix: Add another defineItem signature when init function is passed (#1909) 2025-12-16 16:56:24 -06:00
Sebastian Landwehr 24667861db feat: Support .wxtrc config file (#1833)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-12-16 16:33:37 -06:00
Johan Kiviniemi 25cc403886 refactor: Use script.text instead of innerHTML in injectScript (#1764)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-12-16 16:17:07 -06:00
Johan Kiviniemi 923312c482 feat: Make injectScript return the created script element (#1838)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-12-16 16:09:07 -06:00
Johan Kiviniemi adeef6eb73 fix: Make injectScript wait until script is actually loaded (#1763)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-12-16 15:54:41 -06:00
Johan Kiviniemi 6f84d45960 feat: Add modifyScript option to injectScript (#1762)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-12-16 15:47:40 -06:00
Johan Kiviniemi 938c25cab4 feat: Remove script element immediately in injectScript (#1761)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-12-16 15:42:56 -06:00
github-actions[bot] 0404637da8 chore(release): wxt v0.20.12
📼 VHS / Create VHS (push) Waiting to run
2025-12-16 20:57:58 +00:00
Aaron 98d95e4b7f chore(deps): Upgrade node-forge to address CVE-2025-12816, CVE-2025-66031 (#2003) 2025-12-16 14:50:50 -06:00
Aaron 2687a35781 chore(dev-deps): Upgrade happy-dom to address CVE-2025-61927 (#2002) 2025-12-16 14:41:09 -06:00
Aaron 886dae28fa chore: Upgrade dev and non-major prod dependencies (#2000) 2025-12-16 14:33:59 -06:00
Aaron 8c9bc8cdbc chore: Add support for vite-node v5 (#2001) 2025-12-16 11:46:06 -06:00
Jaguar Zhou 5414a0aa34 fix: wxt prepare fails with the error "__vite_ssr_exportName__ is not defined" when using Vite 7 (#1884)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-12-16 11:04:14 -06:00
K.Utsunomiya 223cf8613b docs: Add note about reviewing project structure in migration guide (#1990) 2025-12-16 08:36:02 -06:00
Alexander Harding 4f1776befc feat: Default to using use_dynamic_url: true for content script css files (#1993)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-12-15 19:04:07 -06:00
Aaron 38473b9f6c chore: Fix formatting 2025-12-15 18:42:23 -06:00
Manabu Nakazawa 41b428c75f docs: Add "Redirect Web" to homepage (#1995)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-12-15 18:32:41 -06:00
yiang231 d8d754658f docs: Add "defineConfig" config to startup examples (#1989) 2025-12-15 18:31:43 -06:00
Shawn e52ebf1d53 docs: Change manifest.title to manifest.name in build:manifestGenerated hook example (#1985) 2025-12-15 18:29:10 -06:00
Nguyen Canh Toan 535c7a5f92 docs: add Zen Virtual Piano & Crypto Pulse to example projects (#1977) 2025-12-15 18:27:21 -06:00
TomvdPeet 99b2bd784a Fix comments for includeSources and excludeSources (#1998)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-12-15 18:19:48 -06:00
Aaron 31ebf966fd chore: Fix other type error after chrome types update 2025-12-15 18:19:25 -06:00
Aaron 6036c6e8e0 chore: Fix type errors after chrome type upgrades 2025-12-15 18:14:29 -06:00
Aaron 597151b5dd ci: Fix browser auto-release workflow 2025-12-15 18:07:44 -06:00
aklinker1 29aeaed223 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-12-11 18:41:00 +00:00
Alex Khrisanfov edf87952c7 ci: Fix update-browser-package action (#1992)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-12-11 12:39:18 -06:00
Aaron 78f8434a06 chore: Use linkedom a test instead of happy-dom (#1957) 2025-10-27 18:11:56 -05:00
Aaron 7eaccad683 chore: Update lockfile 2025-10-27 17:49:24 -05:00
Aaron bfa9c1e1c8 chore: Move PNPM settings to pnpm-workspace.yaml folder 2025-10-27 17:39:59 -05:00
Aaron a2d6577579 docs: Fix syntax error 2025-10-27 17:20:59 -05:00
Ethan Lanting 0e8191488f docs: Added "BetterCampus (prev. BetterCanvas)" to the homepage (#1888)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-10-27 17:08:12 -05:00
Shahil Yadav a1510bb081 docs: Added "Leetcode Fonts" to the homepage (#1889)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-10-27 17:07:05 -05:00
Fantasy 1eaca30f97 docs: Added "sitedata" and "TranslateManga" to homepage (#1902)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-10-27 17:05:52 -05:00
yukidaruma bc79987ed5 docs: Added "Livestream Chat Reader" to the homepage (#1910)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-10-27 17:04:46 -05:00
Alexander Harding 36a501506e feat: Remove data-wxt-* attributes (#1913) 2025-10-27 17:03:01 -05:00
dependabot[bot] e1d47f5f63 chore(deps): bump codecov/codecov-action from 5.5.0 to 5.5.1 (#1920)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-27 16:55:26 -05:00
dependabot[bot] 7faa9b5a64 chore(deps): bump docker/login-action from 3.5.0 to 3.6.0 (#1921)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-27 16:55:00 -05:00
dependabot[bot] 295bee708c chore(deps): bump actions/github-script from 7.0.1 to 8.0.0 (#1922)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-10-27 16:54:32 -05:00
Burak Unver 9e917481c4 docs: Added "ChatGPT Token Counter" to the homepage (#1926)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-10-27 16:53:41 -05:00
anghunk c5a8b9fb3d docs: Add LinuxDo Scripts extension to the list (#1940) 2025-10-27 16:26:46 -05:00
Florian Kühne 3f4e32f8da fix: Optimize splitShadowRootCss (#1934)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-10-27 16:06:01 -05:00
Aaron f630098f1d chore: Upgrade @aklinker1/check to reduce dev dep size 2025-10-27 09:09:20 -05:00
Eli 608d6e2b54 ci: Don't run cron jobs on forks (#1951) 2025-10-26 20:53:35 -05:00
github-actions[bot] fad5ab6c44 chore(release): @wxt-dev/storage v1.2.6
📼 VHS / Create VHS (push) Waiting to run
2025-10-25 16:40:59 +00:00
Aaron d4cb7997fe ci: Publish packages using OIDC with correctly generated package.json
files
2025-10-25 11:34:59 -05:00
Carlos Ortiz 28364b8be1 ci: publish using pnpm instead of npm (#1943) 2025-10-24 21:11:43 -05:00
github-actions[bot] d28a5c7d5e chore(release): @wxt-dev/storage v1.2.5
📼 VHS / Create VHS (push) Waiting to run
2025-10-13 03:09:36 +00:00
Aaron df707aef4c ci: Use correct version of NPM that supports OIDC auth 2025-10-12 22:02:37 -05:00
Aaron 77af2e58ec ci: Log all NPM versions on runner 2025-10-12 21:59:34 -05:00
Aaron f738e56337 ci: Upgrade actions/setup-node to v5 2025-10-12 21:57:24 -05:00
Aaron f2fe2584e0 ci: try out ubuntu-24.04 runner 2025-10-12 21:53:28 -05:00
Aaron 02673ae017 ci: Debug installed NPM versions more 2025-10-12 21:51:37 -05:00
Aaron 8dd294a163 ci: Disable publishing while debugging NPM changes 2025-10-12 21:49:01 -05:00
Aaron 469e735d53 ci: List installed NPM version 2025-10-12 21:47:57 -05:00
github-actions[bot] b02001796e chore(release): @wxt-dev/storage v1.2.4
📼 VHS / Create VHS (push) Waiting to run
2025-10-13 02:46:42 +00:00
Aaron 0d4d2fdd7e ci: Print NPM version 2025-10-12 21:42:15 -05:00
github-actions[bot] b65e5446fa chore(release): @wxt-dev/storage v1.2.3
📼 VHS / Create VHS (push) Waiting to run
2025-10-13 02:00:40 +00:00
Aaron f75fe3ce5b ci: Separate NPM upgrade from publish step 2025-10-12 20:52:54 -05:00
github-actions[bot] 59ba2712cf chore(release): @wxt-dev/storage v1.2.2
📼 VHS / Create VHS (push) Waiting to run
2025-10-13 01:45:12 +00:00
github-actions[bot] fefe601541 chore(release): @wxt-dev/storage v1.2.1
📼 VHS / Create VHS (push) Waiting to run
2025-10-11 17:41:03 +00:00
Aaron 7291c60413 ci: Support NPM OIDC publishing flow and add provenance (#1932) 2025-10-11 12:36:05 -05:00
Jaguar Zhou bb679102b1 fix: wxt normal logs are drowned by dotenv@17.0.0 ads (#1883) 2025-09-09 08:04:18 -05:00
Alexey Karetnikov 16027c8971 chore(templates): Fix typo vite -> wxt (#1885) 2025-09-09 08:02:40 -05:00
github-actions[bot] 84405a33e3 chore(release): wxt v0.20.11
📼 VHS / Create VHS (push) Waiting to run
2025-09-05 13:11:49 +00:00
Aaron bdf795c3f2 chore(deps): Upgrade project subdependencies (#1882) 2025-09-05 08:06:38 -05:00
Qijia Liu ab73084bb5 fix: input_components is supported by mv3 (#1881) 2025-09-05 07:58:09 -05:00
marcellino ornelas e9fb4c5414 fix: Split wxt/testing into separate modules to fix issues with jsdom and happy-dom (#1844)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-09-04 13:56:43 -05:00
github-actions[bot] bc54f525e4 chore(release): @wxt-dev/module-react v1.1.5
📼 VHS / Create VHS (push) Waiting to run
2025-09-04 14:06:52 +00:00
Aaron 9170159bc1 chore(deps): Support @vitejs/plugin-react@5 2025-09-04 09:01:01 -05:00
github-actions[bot] fa657a0366 chore(release): wxt v0.20.10
📼 VHS / Create VHS (push) Waiting to run
2025-09-04 00:03:50 +00:00
Aaron 24920ddd52 chore(deps): publish-browser-extension upgrade (#1880) 2025-09-03 18:59:39 -05:00
Aaron eb0b372113 chore(deps): Upgrade web-ext-run to support CDP (#1879) 2025-09-03 18:51:26 -05:00
Aaron 8f5f4f674e chore(deps): Upgrade non-breaking production dependencies (#1877) 2025-09-03 18:12:54 -05:00
Aaron 38c1dae9c7 ci: Fix fetch depth for notification workflow 2025-09-03 18:08:35 -05:00
Aaron f92bcd1d14 ci: Remove embed from discord notification 2025-09-03 18:07:10 -05:00
Aaron df09b86d23 ci: Fix notification workflow round 4 2025-09-03 18:05:04 -05:00
Aaron bd5cfa10ad ci: Fix notification workflow round 3 2025-09-03 18:00:57 -05:00
github-actions[bot] 94914dd1ad chore(release): wxt v0.20.9
📼 VHS / Create VHS (push) Waiting to run
2025-09-03 22:55:34 +00:00
Aaron dfbb58a2f1 ci: Fix notification workflow round 2 2025-09-03 17:50:13 -05:00
github-actions[bot] 54a1c3576f chore(release): @wxt-dev/storage v1.2.0
📼 VHS / Create VHS (push) Waiting to run
2025-09-03 22:49:56 +00:00
Aaron 9ddf73b4fe ci: Fix notification workflow 2025-09-03 17:44:39 -05:00
github-actions[bot] 4ceec1a6ab chore(release): @wxt-dev/runner v0.1.2
📼 VHS / Create VHS (push) Waiting to run
2025-09-03 22:44:18 +00:00
Aaron ba314d7434 chore: Add manual dispatch to new notification workflow 2025-09-03 17:39:23 -05:00
github-actions[bot] 55fed67067 chore(release): @wxt-dev/module-vue v1.0.3
📼 VHS / Create VHS (push) Waiting to run
2025-09-03 22:39:02 +00:00
Aaron 852390092e ci: Send a weekly notification to discord summarizing the unreleased commits 2025-09-03 17:34:02 -05:00
github-actions[bot] 067be3fed3 chore(release): @wxt-dev/module-svelte v2.0.4
📼 VHS / Create VHS (push) Waiting to run
2025-09-03 22:32:01 +00:00
github-actions[bot] 1aecdbb71c chore(release): @wxt-dev/module-solid v1.1.4
📼 VHS / Create VHS (push) Waiting to run
2025-09-03 22:26:05 +00:00
github-actions[bot] d8e517cb7b chore(release): @wxt-dev/module-react v1.1.4
📼 VHS / Create VHS (push) Waiting to run
2025-09-03 22:17:14 +00:00
github-actions[bot] 9da5b4cacc chore(release): @wxt-dev/analytics v0.5.1
📼 VHS / Create VHS (push) Waiting to run
2025-09-03 22:10:36 +00:00
Aaron 84af32242b ci: Create script to list unreleased commits for each package (#1878) 2025-09-03 17:05:27 -05:00
Aaron 7a81472407 chore(deps): Upgrade all dev dependencies (#1876) 2025-09-03 16:41:00 -05:00
Aaron 9399d8df42 chore: Create script for managing dependency upgrades (#1875) 2025-09-03 16:09:14 -05:00
Aaron 459f73fd5c fix: Add support for @sveltejs/vite-plugin-svelte@6 2025-09-03 10:04:52 -05:00
Aaron c1c3d3b7c5 chore: Upgrade happy-dom to v18.0.1 2025-09-03 09:34:53 -05:00
Aaron 380a9630e5 chore: Upgrade dotenv to v17.2.2 2025-09-03 09:34:09 -05:00
Aaron 984568e00c chore: Upgrade faker to v10 2025-09-03 09:32:07 -05:00
Aaron 5fefd8e083 chore: Upgrade nano-spawn to v1 2025-09-03 09:28:17 -05:00
Aaron a6eef643f6 chore(deps): Upgrade typescript from 5.8.3 to 5.9.2 2025-09-03 09:14:54 -05:00
Aaron a01928e010 chore(deps): Upgrade oxlint from 0.16.8 to 1.14.0 2025-09-03 09:10:47 -05:00
Aaron d901db2316 chore(deps): Upgrade dev dependencies in workspace root (#1874) 2025-09-03 09:05:46 -05:00
Kim Gyeongjae fdda812078 fix: Prevent Unlisted CSS from being excluded in the build when using CSS preprocessor (#1590)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-09-03 08:49:07 -05:00
Atomie CHEN 7c59e9d5b5 fix(types): use TType for DocumentEventMap key in ctx.addEventListener (#1863)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-09-03 08:42:40 -05:00
tanishq-aggarwal c9b0c4da34 feat: Integrate latest measurement protocol changes (#1767)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-09-03 08:22:06 -05:00
TomvdPeet 9f214141b4 docs: Add "Browsely" to homepage (#1850)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-09-03 08:21:39 -05:00
kakuiho 4638e90f02 docs: Added Filmbudd Pro to the homepage (#1853)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-09-03 08:20:27 -05:00
Snow d1c50ab6f8 docs: Add "MultiField CopyCat" to homepage (#1856)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-09-03 08:19:22 -05:00
Abijith Vasanthakumar 489aa0ffd8 docs: Add "ChatSight" to Using WXT section (#1862) 2025-09-03 08:16:54 -05:00
Aaron ebcc605961 chore(deps): Update github actions (#1873) 2025-09-03 08:14:36 -05:00
Aaron bb630049d5 ci: Use node 20 in CI 2025-09-03 07:40:26 -05:00
Aaron 39321adfe1 ci: Use deploy key to bypass branch protection rules (#1861) 2025-08-26 10:48:51 -06:00
aklinker1 ea2b8df906 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-08-15 00:32:30 +00:00
aklinker1 74a9b1aef4 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-08-11 23:42:47 +00:00
github-actions[bot] 8b3e35de94 chore(release): @wxt-dev/auto-icons v1.1.0
📼 VHS / Create VHS (push) Waiting to run
2025-08-11 23:41:58 +00:00
github-actions[bot] 9d4724fa99 chore(release): wxt v0.20.8
📼 VHS / Create VHS (push) Waiting to run
2025-08-11 23:37:18 +00:00
Typed SIGTERM a8379cbd80 docs: Add SVG compatibility note (#1830)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-08-03 09:39:45 -05:00
Sam Carlton bdfb6c5a84 fix(paths): add browser paths for Arc & Dia on macos (#1814)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-08-03 09:24:39 -05:00
sylva 87414d7137 fix: adding missing chromiumPort parameter in web-ext.ts to enable fixed port debugging (#1818)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-08-03 09:16:23 -05:00
Kuba f9d0b64d7a feat: Add overlay option for dev icons (#1825)
Signed-off-by: Kuba Serafinowski <kuba.serafinowski@gmail.com>
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-08-03 09:15:59 -05:00
Aaron 97918710bd docs: Add section on extension API entrypoint limitations (#1743) 2025-08-03 09:14:56 -05:00
btea ac340b3f1e fix: init project should allow the .git folder to exist (#1731)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-08-03 09:14:17 -05:00
Alexander Kachkaev a2097e148b fix: improve Chrome path search (#1823)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-08-03 08:44:06 -05:00
Patryk Kuniczak 190be7f732 fix(rolldown-compat): Only apply footer to content and unlisted scripts via plugin (#1793)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-08-03 08:40:27 -05:00
Aaron 0333ce5c46 chore: Fix type error 2025-08-03 08:02:52 -05:00
Aaron 47df623fd4 docs: Update using WXT section 2025-08-03 07:59:37 -05:00
dependabot[bot] c609efbd9a chore(deps): bump stefanzweifel/git-auto-commit-action from 5 to 6
Bumps [stefanzweifel/git-auto-commit-action](https://github.com/stefanzweifel/git-auto-commit-action) from 5 to 6.
- [Release notes](https://github.com/stefanzweifel/git-auto-commit-action/releases)
- [Changelog](https://github.com/stefanzweifel/git-auto-commit-action/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stefanzweifel/git-auto-commit-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: stefanzweifel/git-auto-commit-action
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-01 18:26:56 -05:00
Johnny Fekete c8cd41a833 fix: add missing comma in extension IDs (#1827) 2025-07-28 18:02:03 +02:00
Yacine Benslimane 02a0110091 docs: add "Epic Games Library Extension" to docs (#1728)
Co-authored-by: Florian Metz <me@timeraa.dev>
2025-07-24 18:37:07 +02:00
Sam Carlton 6c572c56a3 feat(config): add browser path for Zen via Homebrew (#1813)
Co-authored-by: Florian Metz <me@timeraa.dev>
2025-07-24 18:36:29 +02:00
Greg Zajac 2db516ef3b docs: add 2FAS Pass extension (#1790)
Co-authored-by: Florian Metz <me@timeraa.dev>
2025-07-24 18:33:39 +02:00
Michał Warać 9f3787cd95 docs: add "Piwik PRO Tracking Helper" to the home page (#1822) 2025-07-24 18:05:46 +02:00
Nguyen Canh Toan 5511943237 docs: Update UsingWxtSection.vue (#1740)
Co-authored-by: Florian Metz <me@timeraa.dev>
2025-07-24 18:03:10 +02:00
John Valai 626838eba6 fix: correct typos in docs (#1817) 2025-07-18 03:44:33 -05:00
aklinker1 587328f54c fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-07-17 00:32:55 +00:00
aklinker1 1aa88b1fb6 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-07-16 00:32:35 +00:00
ayu e7db119545 chore: wxt & @wxt-dev/module-vue support Vite 7 (#1771) 2025-07-15 19:21:51 -05:00
Thomas Howlett da79536456 docs: correct content script example code (#1811) 2025-07-15 18:56:58 -05:00
aklinker1 aaaff43731 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-07-12 00:32:04 +00:00
Nishu 5d77142758 docs: adding youtube-video-scheduler in docs. (#1736) 2025-07-12 00:18:36 +02:00
wenyuan 586ea0002b docs: add "Quick Prompt" to the homepage (#1785)
Co-authored-by: Florian Metz <me@timeraa.dev>
2025-07-12 00:18:22 +02:00
流浪大法师 e642d6fe76 docs: add "Add QR Code Generator Icon Back To Address Bar" to the home page (#1800) 2025-07-12 00:15:26 +02:00
Achraf M. Bouhamid 7148f288d5 docs: add "PIPX" to the home page (#1798) 2025-07-12 00:15:14 +02:00
aklinker1 40abf3fb5b fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-07-10 00:31:55 +00:00
aklinker1 adea6c7177 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-07-09 00:32:25 +00:00
Aaron 96a307e99f docs: Use proper content type when loading extensions on homepage 2025-07-08 02:22:19 -05:00
aklinker1 f0201f72ef fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-07-02 00:31:40 +00:00
aklinker1 0b1b677b3d fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-06-29 00:35:32 +00:00
aklinker1 b1dcec86cd fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-06-28 00:30:09 +00:00
Mark 7c783fe565 fix: rootDir, not srdDir for public/_locales (#1751) 2025-06-16 16:56:53 -05:00
요술토끼(wizardrabbit) 9a0207d7cf docs: Added "토탐정" to the homepage (#1750) 2025-06-16 07:51:48 -05:00
Honwhy Wang 1b0e047d6b docs: adding wechat reader enhancer in docs. (#1745) 2025-06-15 18:23:56 -05:00
0xHPZ 7ab3c7e5d9 docs: Added "Chatslator" to the homepage (#1739) 2025-06-14 19:51:04 -05:00
Nishu 9ece49d226 fix: Support negation patterns when including/excluding files from ZIP files (#1517)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-06-14 18:08:04 -05:00
Aaron 1272e2ec74 chore: Fix markdown lint errors and add upgrade @aklinker1/check to
include markdownlint
2025-06-10 16:14:58 -05:00
Aaron db16602018 docs: Add missing breaking change to 0.20 migration (#1636) 2025-06-06 11:03:21 -05:00
Aaron 5c202805b9 fix: Fix bundle variable assignment error with rolldown-vite (#1715) 2025-06-06 10:56:06 -05:00
Aaron bfc8866b69 fix: Fix bad regex from #1707 (#1712) 2025-06-05 01:02:21 -05:00
spookyuser 9aedc29289 docs: Update environment-variables.md with info about env.DEV (#1630)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-06-05 01:01:42 -05:00
Hyunbin Seo e1f3d75ac4 docs: fix svelte app unmount code (#1673) 2025-06-05 00:48:37 -05:00
Aaron 030f23d2e9 docs: Update JSDoc with ways to cancel timeouts and intervals set by content script context 2025-06-05 00:38:57 -05:00
Nishu 6be9a4e71b fix: recreating keyboardShortcuts interface on file changes. (#1465)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-06-05 00:35:13 -05:00
Aaron eb0bffb5dd docs: Fix API reference sidebar by naming new module 2025-06-05 00:33:52 -05:00
BrowserLens 240bbb3676 docs: Added "BrowserLens" to the homepage (#1691) 2025-06-05 00:27:14 -05:00
Aaron 7d25110a6e chore: Remove automd 2025-06-05 00:18:43 -05:00
Aaron 598eea703b docs: Simplify README HTML elements 2025-06-04 23:32:24 -05:00
Aaron 8793f7bff4 chore: Manually fix markdownlint errors (#1711) 2025-06-04 18:30:54 -05:00
Aaron c1b3911622 fix: Support http server websocket inside containers (#1707) 2025-06-04 17:40:48 -05:00
Aaron b0bf05109d ci: Use matrix for test jobs (#1708) 2025-06-04 17:40:28 -05:00
Aaron d9cb0ebcc8 chore: Fix auto-fixable markdownlint errors (#1710) 2025-06-04 17:40:00 -05:00
Aaron 1eda21f63f chore: Add markdownlint to repo (#1709) 2025-06-04 17:34:42 -05:00
github-actions[bot] f2dbcde124 chore(release): wxt v0.20.7
📼 VHS / Create VHS (push) Waiting to run
2025-06-02 21:40:42 +00:00
Richard Lee 60f00db2c5 feat: Add DisableLoadExtensionCommandLineSwitch flag to Chromium runner (#1698) 2025-06-02 16:36:24 -05:00
github-actions[bot] a9332453fc chore(release): @wxt-dev/runner v0.1.1
📼 VHS / Create VHS (push) Waiting to run
2025-06-02 20:09:59 +00:00
Aaron b99da14799 feat(runner): Create new @wxt-dev/runner package (#1566)
📼 VHS / Create VHS (push) Waiting to run
2025-06-02 15:01:59 -05:00
aklinker1 f02400a1fb fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-06-01 02:20:17 +00:00
aklinker1 bbcb7f7cdd fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-05-31 01:53:46 +00:00
aklinker1 30cf8e6d54 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-05-30 01:54:08 +00:00
aklinker1 4f772fc0f7 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-05-17 01:52:17 +00:00
Ahmed Rangel 2cf2582138 docs: Added "NetSuite Record Scripts", "VueTracker" to the homepage (#1665)
Co-authored-by: Florian Metz <me@timeraa.dev>
2025-05-14 12:30:19 +02:00
Stepan Rabotkin ad4de4b92c docs: Added CanCopy to homepage (#1667)
Co-authored-by: Florian Metz <me@timeraa.dev>
2025-05-14 12:23:48 +02:00
MengXi 27ed73a6ae docs: Added 'Read Frog' extension to homepage (#1666) 2025-05-14 12:17:18 +02:00
Qiwei Yang a1570c8917 docs: Added "Bilibili Feed History Extension" to the homepage (#1669)
Co-authored-by: Florian Metz <me@timeraa.dev>
2025-05-14 11:59:01 +02:00
ТΞNSΛI 7e419ddd43 docs: Added "NZBDonkey" to the homepage (#1670)
Co-authored-by: Florian Metz <me@timeraa.dev>
2025-05-14 11:54:59 +02:00
Honwhy Wang b045d3616d docs: Added "WeChat Markdown Editor" to the homepage (#1671)
Co-authored-by: Florian Metz <me@timeraa.dev>
2025-05-14 11:53:48 +02:00
𝖆𝖉𝖎𝖙𝖍𝐲𝖆 f6b50e2e77 docs: Added Tab Grab to the homepage (#1672) 2025-05-14 11:45:16 +02:00
aklinker1 9d1381cbb3 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-05-13 01:55:49 +00:00
aklinker1 99b0242d86 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-05-10 01:49:30 +00:00
aklinker1 db27628211 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-05-06 01:53:55 +00:00
aklinker1 9b9d86229a fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-05-05 01:57:09 +00:00
Boris Zabolotskikh 46f830dacf docs: Added "Web to PDF", "Online CSV Viewer", "YouTube Video Transcript" to the homepage (#1655)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-05-04 19:33:35 -05:00
github-actions[bot] 3dd9bc7772 chore(release): @wxt-dev/i18n v0.2.4
📼 VHS / Create VHS (push) Waiting to run
2025-05-04 12:27:20 +00:00
Aaron c7335add19 chore: Change browser workspace dependency to ^ 2025-05-04 07:21:55 -05:00
Aaron c133498208 chore(deps): Update all dependencies (#1648) 2025-05-02 08:53:38 -05:00
Aaron 6a52bb22a3 fix: Use @wxt-dev/browser instead of @types/chrome (#1645) 2025-05-02 08:41:02 -05:00
Aaron 6f970efda5 chore: Upgrade @aklinker1/check to v2 (#1647) 2025-05-02 08:36:46 -05:00
Aaron c69350a0eb fix: Fix bad links to developer.chrome.com 2025-05-02 07:10:25 -05:00
Aaron 4add8820eb chore: Stop using PNPM catalog (#1644) 2025-05-02 06:26:12 -05:00
Aaron 033dd4811e chore(deps): Upgrade dev dependencies (#1642) 2025-05-02 05:52:06 -05:00
Aaron da5cd32502 fix: Improve CSS reset inside shadow roots 2025-05-02 05:14:42 -05:00
aklinker1 edf33fdec9 fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-05-02 01:53:07 +00:00
seaders 448cbf16c9 feat: Add @font-face to be processed by splitShadowRootCss (#1635) 2025-05-01 12:49:54 -05:00
Aaron e45b77b528 chore(deps): Upgrade vite and related dependencies 2025-05-01 12:25:56 -05:00
github-actions[bot] b61fd1716e chore(release): wxt v0.20.6
📼 VHS / Create VHS (push) Waiting to run
2025-04-30 16:22:57 +00:00
Aaron d584b5cc7e chore(deps): Upgrade web-ext-run to v0.2.3 (#1634) 2025-04-30 11:18:30 -05:00
Bang·_· faf9cedfbd docs: Added "[DesignPicker]" to the homepage (#1624) 2025-04-27 07:24:00 -05:00
Aaron 3a38ac9339 Fix changelog contributors 2025-04-26 18:07:17 -05:00
github-actions[bot] 7ea36a3cfc chore(release): wxt v0.20.5
📼 VHS / Create VHS (push) Waiting to run
2025-04-26 13:53:46 +00:00
Aaron 3577c0b47a fix: Don't use crypto.randUUID for shadow root UIs 2025-04-26 08:48:42 -05:00
Aaron d0bef42186 fix: Standardize locale codes and warn about unsupported ones (#1617) 2025-04-26 08:03:22 -05:00
github-actions[bot] d9f10c62ad chore(release): wxt v0.20.4
📼 VHS / Create VHS (push) Waiting to run
2025-04-25 03:03:08 +00:00
aklinker1 35d3c03e4b fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-04-25 01:52:10 +00:00
Yunsup Sim fdd38a1580 fix: Fix CORS error in Firefox (#1607) 2025-04-24 19:01:30 -05:00
ТΞNSΛI 3018801f06 feat: add {{packageVersion}} as template variable (#1604) 2025-04-24 12:06:50 -05:00
Anh71me 8e96bfef06 fix: fix typescript error on defineItem fallback (#1601) 2025-04-24 07:31:48 -05:00
ТΞNSΛI 31071bd11e feat: ignore elements with a vite-ignore or wxt-ignore attribute (#1603)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-04-24 00:34:49 -05:00
Yuan f5619f6be1 chore: Move the public folder outside of src for the default Svelte template (#1602) 2025-04-24 00:26:34 -05:00
Aaron adad1b5a2c chore: Fix formatting 2025-04-24 00:24:49 -05:00
Nishu a6c4e19a5d fix: adding missing "" to PublicPath and browser.runtime.getUrl (#1597) 2025-04-24 00:18:06 -05:00
Jack af6f74c344 docs: Added "[Always Light Mode]" to the homepage (#1608) 2025-04-24 00:05:37 -05:00
Aaron ce45cb8a89 docs: Add warning about --load-extension deprecation 2025-04-23 23:35:28 -05:00
aklinker1 14d4aa202d fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-04-23 01:51:01 +00:00
Nishu 4c35798dba feat: Ignore popup/index.ts instead of erroring (#1520)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-04-20 21:17:05 -05:00
Aaron 656a9b365f docs(Content Script UI): Add additional details about when onRemove is called 2025-04-20 21:15:08 -05:00
Namu 67fa3db921 docs: Fix import in unit-testing.md (#1598) 2025-04-20 20:36:06 -05:00
github-actions[bot] f2d3061e97 chore(release): wxt v0.20.3
📼 VHS / Create VHS (push) Waiting to run
2025-04-19 17:17:39 +00:00
Aaron 760c34e416 feat: Automatically place document-level CSS outside shadow root (#1594) 2025-04-19 12:12:04 -05:00
Bang·_· 48398b315c docs: Added "[Blens - Time Tracker and AI Insight]" to the homepage (#1587) 2025-04-18 21:53:19 -05:00
techlism 45d0d9d7f1 docs: Fix entrypoints.md examples (#1586) 2025-04-18 21:11:04 -05:00
Aaron b0f4ac8221 fix: Fix double hashing of inline script keys
Additionally, update the vite plugin name to better align with purpose
2025-04-18 20:50:02 -05:00
github-actions[bot] 719192b1aa chore(release): wxt v0.20.2
📼 VHS / Create VHS (push) Waiting to run
2025-04-19 00:40:32 +00:00
Yunsup Sim 7eb32bdac8 fix: Fix hashing issue with inline scripts (#1591) 2025-04-18 19:35:18 -05:00
nostro 862756fd5b chore: update docs to point to webExt instead of runner; update config in demo (#1582) 2025-04-16 09:42:55 -05:00
nostro 5ba16e72e0 docs: add radiofrance extension to usingWXT (#1581) 2025-04-16 09:42:20 -05:00
Aaron e43ae0504d docs: Add filenames to startup examples 2025-04-16 08:09:46 -05:00
Aaron acb6cd180c docs: Fix typo in changelog 2025-04-14 17:24:10 -05:00
github-actions[bot] a3301d0413 chore(release): wxt v0.20.1
📼 VHS / Create VHS (push) Waiting to run
2025-04-14 13:29:52 +00:00
7sDream b9e72358ac feat: type-safe import.meta.env.BROWSER with new targetBrowers config (#1574)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-04-14 08:25:04 -05:00
Aaron 61b42ef326 chore: Update comment 2025-04-13 08:55:14 -05:00
aklinker1 da9e27c28d fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-04-12 01:46:11 +00:00
aklinker1 6f80fbabaa fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-04-10 01:48:29 +00:00
Aaron d2308bd45c chore(deps): Update all dependencies (#1568) 2025-04-09 09:46:29 -05:00
nostro d35972d24f fix: add JSDoc type annotation to auto-imports for ESlint (#1558) 2025-04-08 18:10:58 -05:00
Aaron 298a264934 docs: Add not about viewing available options for wxt submit 2025-04-08 17:58:53 -05:00
Khalil Yao ad63b595b4 fix: Don't remove top-level destructured variable definitions when importing entrypoints (#1561) 2025-04-05 11:25:15 -05:00
aklinker1 986a9ceebf fix: Upgrade @wxt-dev/browser to latest @types/chrome version 2025-04-02 01:49:03 +00:00
dependabot[bot] 682b65e723 chore(deps): bump @types/node from 20.17.6 to 20.17.30 (#1552)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-01 16:06:04 -05:00
dependabot[bot] cb661506c0 chore(deps): bump fast-glob from 3.3.2 to 3.3.3 (#1556)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-01 16:04:57 -05:00
dependabot[bot] 505aa06443 chore(deps): bump @commitlint/config-conventional from 19.7.1 to 19.8.0 (#1555)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-04-01 16:04:32 -05:00
Aaron f534a978f1 chore: Upgrade templates to wxt 0.20 (#1551) 2025-03-31 18:22:53 -05:00
Aaron 1293815934 docs: Update unocss import to match latest requirements 2025-03-31 16:17:22 -05:00
Aaron 0c0fd18bf4 docs: Split major and minor version update steps apart 2025-03-31 15:59:03 -05:00
Aaron c49c31813f docs: Add description of modules directory to project structure summaries 2025-03-31 14:24:02 -05:00
Aaron 877ab11bb4 docs: Fix knowledge file generation (#1550) 2025-03-31 13:54:04 -05:00
Alec WM 0d18d8d7e3 feat: enable wxt usage inside of devcontainers (#1406)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-03-31 09:21:56 -05:00
Aaron 5f977857a1 chore: Fix formatting 2025-03-29 09:50:26 -05:00
Aaron a63b21d417 docs: Fix diff highlights after auto-formatting 2025-03-29 09:45:01 -05:00
Aaron e1b7d6090e docs: Refresh entrypoints page with more in-depth examples and documentation 2025-03-28 20:08:53 -05:00
Aaron 1bcc5cdd81 docs: Add link to comments on blog post 2025-03-28 11:44:54 -05:00
Aaron 873fdbc4b3 Update changelogs 2025-03-28 11:10:14 -05:00
Aaron 79128effea ci: Update browser package commit message 2025-03-28 11:06:06 -05:00
Aaron 14ef94fc09 ci: Fix browser sync workflow 2025-03-28 11:05:16 -05:00
aklinker1 759e3e3a4d fix: Upgrade \@wxt-dev/browser\ to latest \@types/chrome\ version 2025-03-28 16:01:49 +00:00
Aaron 5b7b16efba fix(browser): Install latest version of @types/chrome 2025-03-28 11:01:05 -05:00
aklinker1 7fd171acb5 fix: Upgrade \@wxt-dev/browser\ to latest \@types/chrome\ version 2025-03-28 15:59:43 +00:00
Aaron 02ed3f1d44 chore: Fix type check script 2025-03-28 10:58:21 -05:00
Aaron 4f7f3f36a3 chore: Fix type check script 2025-03-28 10:58:09 -05:00
Aaron 73a8cf12a9 docs: Use nicer project structure for v0.20 directory changes 2025-03-28 10:47:36 -05:00
Aaron 5f5eb16705 docs: Add redirect for old upgrade guide 2025-03-28 10:41:24 -05:00
github-actions[bot] f0f4437870 chore(release): @wxt-dev/analytics v0.5.0
📼 VHS / Create VHS (push) Waiting to run
2025-03-28 15:36:33 +00:00
github-actions[bot] 868c042511 chore(release): wxt v0.20.0
📼 VHS / Create VHS (push) Waiting to run
2025-03-28 15:32:11 +00:00
Aaron bdb49c0b3d docs: Final changes to 0.20 upgrade guide 2025-03-28 10:25:56 -05:00
Aaron cc3c43d1bd chore: Remove @types/chrome from project templates 2025-03-28 10:25:56 -05:00
Aaron e47131efc1 docs: Update v0.20 upgrade docs 2025-03-28 10:25:56 -05:00
Aaron 82d8024fb4 docs: Fix broken links 2025-03-28 10:25:56 -05:00
Aaron c662a59d85 docs: Update modules path to new path 2025-03-28 10:25:56 -05:00
Aaron 4e50fb1f92 docs: Update configurable directories in project-structure.md 2025-03-28 10:25:56 -05:00
1natsu fbae370d1e fix: missing browser in shadow-root file (#1317)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-03-28 10:25:56 -05:00
Aaron 9c64c9dd61 feat!: Auto-import types (#1315) 2025-03-28 10:25:56 -05:00
Aaron 8f6dba20d2 docs: Update upgrade guide 2025-03-28 10:25:56 -05:00
Aaron f531fcd5c3 fix: Add back ExtensionRunnerConfig as deprecated (#1311) 2025-03-28 10:25:56 -05:00
Aaron ff1720a4c6 feat: Add @wxt-dev/webextension-polyfill module (#1310) 2025-03-28 10:25:56 -05:00
Aaron d62203dff8 docs: Add upgrade guide for v0.20 (#1270) 2025-03-28 10:25:56 -05:00
Aaron 99b5076d69 docs: Fix api reference for wxt/utils/storage 2025-03-28 10:25:56 -05:00
Aaron 298e7101f7 fix!: Move wxt/storage to wxt/utils/storage (#1271) 2025-03-28 10:25:56 -05:00
Aaron b4ce36b708 docs: Fix broken links 2025-03-28 10:25:56 -05:00
Aaron 5d096a4a92 feat!: Reset inherited styles inside shadow root (#1269) 2025-03-28 10:25:56 -05:00
Aaron e54df0aca8 chore: Remove duplicate test 2025-03-28 10:25:56 -05:00
Aaron 2e8baf0161 fix!: Update min WXT version to 0.20 2025-03-28 10:25:56 -05:00
Aaron c9dca0222c fix: Add support for WXT v0.20.0 2025-03-28 10:25:56 -05:00
Aaron 6044ab73bd feat!: Individual exports and introduce the #imports module (#1258) 2025-03-28 10:25:56 -05:00
Aaron 660945c792 docs: Add blog and first blog post to wxt.dev (#1261) 2025-03-28 10:25:56 -05:00
Aaron bcb20874a8 docs: Fix public path reference 2025-03-28 10:25:56 -05:00
Aaron 83ad0e3ff0 fix!: Make publicDir and modulesDir relative to project root (#1216) 2025-03-28 10:25:56 -05:00
Aaron aad17c8d26 chore: Fix type errors 2025-03-28 10:25:56 -05:00
Aaron b0ef178c9c fix: Remove unnecessary VITE_CJS_IGNORE_WARNING flag 2025-03-28 10:25:56 -05:00
Aaron 0175c430a3 fix!: Remove transformManfiest option (#1181) 2025-03-28 10:25:56 -05:00
Aaron 2776587392 fix!: Rename runner to webExt (#1180) 2025-03-28 10:25:56 -05:00
Aaron b978465d7a fix!: Remove deprecated jiti entrypoint loader (#1087) 2025-03-28 10:25:56 -05:00
Aaron f7989ea1e0 fix!: Add suffix to non-production output directories (#1086) 2025-03-28 10:25:56 -05:00
Aaron 0cf34d3170 feat!: Remove webextension-polyfill (#1084) 2025-03-28 10:25:56 -05:00
Aaron 4fe04c6f8a chore: Add missing type keyword on import 2025-03-28 09:03:40 -05:00
Aaron 1773762d2f chore: Update lockfile 2025-03-21 14:47:11 -05:00
Aaron 9057000e45 docs: Add workflow link 2025-03-21 14:45:43 -05:00
aklinker1 d540233673 fix: Upgrade \@wxt-dev/browser\ to latest \@types/chrome\ version 2025-03-21 19:44:30 +00:00
Aaron 9907290a04 feat: Add new @wxt-dev/browser package (#1530) 2025-03-21 14:39:34 -05:00
Aaron d9fb919580 chore: Use feature issue type instead of label in template 2025-03-21 10:25:04 -05:00
Aaron 17723d5828 chore: Fix bug report template 2025-03-21 10:14:08 -05:00
Aaron c7db2d26b3 chore: Use bug issue type instead of label 2025-03-21 10:13:46 -05:00
Leo 259cec9ea8 docs: add vitepress-plugin-group-icons (#1526) 2025-03-21 09:20:25 -05:00
ergou 2ced9c40d3 feat(storage): Add debug option to enable migration logs (#1513) 2025-03-20 01:11:34 -05:00
ergou 756efc9311 feat(storage): Add onMigrationComplete callback (#1514)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-03-19 19:02:51 -05:00
Eli 17fd2ff0ce chore(deps): Bump unjs ecosystem (#1508) 2025-03-19 11:46:38 -05:00
Christoph Kolb 35833c00f0 Correct "Host permissions" docs showing a code example for "permissions" (#1516) 2025-03-19 11:45:59 -05:00
aianddeng 300c045187 docs: Add "SnapThePrice" to the homepage (#1523) 2025-03-19 11:45:21 -05:00
Aaron 4c05cc19e5 docs: Update LLM FAQ 2025-03-14 08:53:45 -05:00
Leendert de Borst 72dab65a1d docs: Add "AliasVault" to the homepage (#1512) 2025-03-11 20:49:14 +01:00
github-actions[bot] 4e5fb7745a chore(release): @wxt-dev/unocss v1.0.1
📼 VHS / Create VHS (push) Waiting to run
2025-03-09 13:46:17 +00:00
Aaron 2bc92043f8 chore: Upgrade templates to use WXT 0.19.29 2025-03-08 11:27:58 -06:00
github-actions[bot] 3024bd825d chore(release): wxt v0.19.29
📼 VHS / Create VHS (push) Waiting to run
2025-03-06 15:29:12 +00:00
Aaron 0b39774690 Update changelog 2025-03-06 09:23:36 -06:00
github-actions[bot] a461a23845 chore(release): @wxt-dev/storage v1.1.1
📼 VHS / Create VHS (push) Waiting to run
2025-03-06 15:15:17 +00:00
Thomas c0867e3374 fix: Support registration: "runtime" for MV2 (#1431)
Co-authored-by: harmonyharmo <>
2025-03-06 09:09:33 -06:00
ergou 47040277a2 fix: Return early if no migration is needed (#1502) 2025-03-05 09:02:40 -06:00
Aaron 0f0daf378c feat: New @wxt-dev/analytics package (#790)
Co-authored-by: aklinker1 <aklinker1@users.noreply.github.com>
2025-03-03 22:44:40 -06:00
Alec Larson 51b315f23a feat: tolerate syntax errors (#1437)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-03-03 22:10:54 -06:00
Aaron 60f5117bbc docs: Add CRXJS migration docs (#1430) 2025-03-03 22:08:03 -06:00
btea 15634ecb95 chore: update onlyBuiltDependencies (#1498) 2025-03-03 22:04:40 -06:00
btea 0a5007aee0 ci: prevent action running on forks (#1499) 2025-03-03 21:50:28 -06:00
Aaron bc54e1bd63 Fix changelog emails 2025-03-03 18:32:20 -06:00
github-actions[bot] d8a8202e63 chore(release): wxt v0.19.28
📼 VHS / Create VHS (push) Waiting to run
2025-03-04 00:26:31 +00:00
Aaron c9eb3b0ca9 fix: Allow vite 6.0.9+ (#1497) 2025-03-03 18:21:18 -06:00
Aaron 665f5a52c4 chore: Fix typo 2025-03-03 17:57:45 -06:00
Aaron 798f3b8e47 chore(deps): Upgrade to Vite 6 and related dependencies (#1496) 2025-03-03 17:52:52 -06:00
Aaron a886ab28e1 chore(deps-dev): bump happy-dom from 15.11.4 to 17.1.8 (#1495) 2025-03-03 15:06:42 -06:00
Aaron 28cff9c90a chore: Move production dependencies to PNPM 10 catelog (#1494) 2025-03-03 14:57:28 -06:00
Aaron 8ce197b023 chore: Use PNPM 10's new catelog feature (#1493) 2025-03-03 14:50:05 -06:00
dependabot[bot] a5553457c6 chore(deps): bump vite-plugin-solid from 2.10.2 to 2.11.6 (#1491)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-03 14:26:55 -06:00
Saksham Kushwaha 7d9ed777fb docs: Added monochromate to the homepage (#1486)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-03-03 14:26:09 -06:00
Aaron 59362e7274 chore: Upgrade to PNPM 10 (#1492) 2025-03-03 14:23:11 -06:00
Aaron d32d17952c chore: Update workflow emoji 2025-03-03 14:14:03 -06:00
Aaron 6630bca73f chore: Update dependabot config 2025-03-03 14:02:14 -06:00
Okinea Dev befd442075 ci: fix pr-closed.yml workflow (#1470) 2025-03-02 10:50:04 -06:00
Aaron da885ff6c8 docs: Update browser-startup.md 2025-02-27 09:59:29 -06:00
Aaron 349b216439 docs: Update entrypoints.md 2025-02-27 09:58:19 -06:00
Aaron 47b78d66cf docs: Fix typo in auto-imports.md 2025-02-27 09:45:39 -06:00
Aaron fe2baef2b1 chore: Upgrade vitepress-knowledge 2025-02-26 22:01:15 -06:00
Aaron 357bbdaec9 docs: Add AI assistant to https://wxt.dev (#1453) 2025-02-20 23:52:04 -06:00
Stefan Maric a38e3c2733 fix: regression on variable expansion in dotenv files (#1449) 2025-02-18 21:47:47 -06:00
Okinea Dev f17e527d72 chore: improve .gitattributes (#1447) 2025-02-18 07:59:31 -06:00
Okinea Dev e20de4ca0d chore: Add funding links to package.json files (#1446) 2025-02-17 15:35:01 -06:00
Aaron 16ac53e0a1 docs: Fix link to knowledge file index 2025-02-17 11:46:03 -06:00
skube fee978bf25 docs: Uses correct grammar (#1445) 2025-02-16 16:39:21 -06:00
Aaron f80909d63e docs: Host pre-aggregated LLM knowledge files (#1355) 2025-02-16 14:03:18 -06:00
Aaron d5b2503155 ci: Update pkg.pr.new workflow names 2025-02-16 12:40:54 -06:00
Aaron 80ca5760e2 docs: Fix bad alias usage in assets examples (#1443) 2025-02-16 10:12:21 -06:00
Okinea Dev 44dab3726f ci: Add PR title checker workflow and thank-you comment on merge (#1385)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-02-15 18:38:43 -06:00
Aaron c4295a4f4b ci: Improve main check step name 2025-02-15 10:40:51 -06:00
1natsu a6a91250d1 fix: Properly detect and reload changed files when using Vite's ?suffix imports (#1432) 2025-02-13 22:45:52 -06:00
Okinea Dev 1db50ed7a9 ci: Enhance GitHub Actions workflows (#1370)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-02-13 16:06:46 -06:00
Alec Larson 342057b3f5 fix: resolve wxt modules from the root (#1417) 2025-02-12 22:12:48 -06:00
John Wu 151b1392c6 docs: Add comctx to community page (#1422) 2025-02-12 21:37:37 -06:00
John Wu 1d5d0663ac docs: Add comctx to messaging docs (#1421) 2025-02-12 21:36:37 -06:00
Aaron 30b8ba495d fix: Ignore manifest.manifest_version option and warn about incorrect usage (#1419) 2025-02-12 08:43:44 -06:00
Andy Cloke 5775c9ce0f docs: Add "Python Code Runner" to homepage (#1420) 2025-02-12 02:40:59 -06:00
GitHub Actions 4f82dd87fc chore(release): wxt v0.19.27
vhs / vhs (push) Waiting to run
2025-02-12 06:31:38 +00:00
Aaron fab9fa81d1 ci: Add missing permission to release workflow 2025-02-11 23:52:15 -06:00
Jaguar Zhou d6ee4560d8 fix: auto-import does not work when using @vitejs/plugin-vue alone (#1412) 2025-02-11 23:49:59 -06:00
Alec Larson 655ba863a0 fix: respect inlineConfig.mode when setting NODE_ENV (#1416) 2025-02-11 23:44:29 -06:00
Aaron ac92d4019f fix: Support publish-browser-extension v3.0.0 2025-02-11 23:36:49 -06:00
Andy Nguyen 0ff964a04b docs: fix typo you're -> your (#1414) 2025-02-09 15:35:31 -06:00
Malix 89459f0a4d docs: Add "maintenance" to the comparison (#1404) 2025-02-08 13:58:36 -06:00
Aaron 0d56100abb docs: Fix wording around ESM background scripts 2025-02-07 23:28:24 -06:00
Aaron dc770b5952 docs: Update ESM docs to clearify that it covers configuring ESM at runtime 2025-02-07 23:24:00 -06:00
Aaron 8cd2bff67a revert: #1382 - migrate feature request template to YAML form (#1410) 2025-02-07 21:56:28 -06:00
Okinea Dev 11e55e2499 chore: Migrate feature request template to YAML form (#1382) 2025-02-07 21:52:21 -06:00
Okinea Dev 4cab3a5593 chore: Add vscode configuration (#1399) 2025-02-07 21:33:50 -06:00
st3h3n daa0eed851 fix: Use path triple slash directive for types that are referenced via path (#1407)
Co-authored-by: Stefan Hensel <stefan.hensel@varia.media>
2025-02-07 12:00:08 -06:00
Aabid 868a347d40 docs: Fixed an external link in FAQs (#1402) 2025-02-07 02:40:14 -06:00
daichan132 48a87aa352 docs: Add "Youtube Live Chat Fullscreen" to homepage (#1398) 2025-02-04 19:54:54 +01:00
Aaron dfec8a3608 chore: Cleanup CODEOWNERS file, add myself to .github dir 2025-02-01 14:31:30 -06:00
dependabot[bot] 9a71231436 chore(deps-dev): bump solid-js from 1.9.3 to 1.9.4 (#1391)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-01 14:12:44 -06:00
Aaron db4592fbb3 docs: Add community page (#1381) 2025-02-01 14:11:35 -06:00
Solaiman Islam Naiem 8551d6071e docs: Add "Walmart WFS Profit Calculator" to homepage (#1380) 2025-01-30 08:15:09 -06:00
Florian Metz c40285f750 chore(repo): add CODEOWNERS (#1377) 2025-01-29 17:32:34 -06:00
Eli 9238f9fd85 fix: Allow vite-node@^3.0.0 (#1378) 2025-01-29 17:32:14 -06:00
GitHub Actions ba3d8838e3 chore(release): @wxt-dev/module-svelte v2.0.3
vhs / vhs (push) Waiting to run
2025-01-28 21:17:33 +00:00
Eli e9b6f5f97c fix: Upgrade vite-plugin-svelte to support Vite 6 (#1375)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-01-28 15:09:01 -06:00
Aaron 5b6c82d38f chore: Fix formatting 2025-01-28 14:43:38 -06:00
Aaron 5b41b70abe docs: Add SECURITY.md 2025-01-28 14:41:56 -06:00
Okinea Dev 93f624610f chore: add pull request template (#1372)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-01-28 08:03:26 -06:00
Okinea Dev 73bdd49471 chore: simplify FUNDING.yml (#1371) 2025-01-28 07:32:59 -06:00
GitHub Actions 635f3f0898 chore(release): wxt v0.19.26
vhs / vhs (push) Waiting to run
2025-01-28 06:46:49 +00:00
Deniz Uğur a53ee6d590 fix(context): Deduplicate wxt:content-script-started (#1364)
Co-authored-by: DenizUgur <DenizUgur@users.noreply.github.com>
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-01-28 00:41:12 -06:00
GitHub Actions 665b9194cf chore(release): @wxt-dev/storage v1.1.0
vhs / vhs (push) Waiting to run
2025-01-28 06:40:20 +00:00
Gabriel Roldán 4690418c94 Fix: Remove duplicated css rule from vue template (#1369) 2025-01-27 16:00:09 -06:00
Chengxi 20eea2a7d1 feat: Add storage.clear (#1368)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-01-27 07:22:19 -06:00
rxliuli ac7b6760f2 docs: Add missing bracket in example (#1367) 2025-01-25 01:14:48 -06:00
GitHub Actions a593cfbbb6 chore(release): wxt v0.19.25
vhs / vhs (push) Waiting to run
2025-01-22 05:08:46 +00:00
Aaron a205f2a0a8 chore: Update lockfile 2025-01-21 23:03:09 -06:00
Aaron 8e2badc92b fix: Drop support for vite 6.0.9+ until websocket fix is finished 2025-01-21 23:02:22 -06:00
redwoodlid 7c18d9c0b8 docs: Add react language ID to README (#1347) 2025-01-15 10:25:40 -06:00
Aaron 55a1f39450 Update changelog 2025-01-15 10:23:36 -06:00
GitHub Actions d708eca78e chore(release): wxt v0.19.24
vhs / vhs (push) Waiting to run
2025-01-12 22:48:50 +00:00
1natsu 5d7e2516b6 fix: autoMount not working if anchor is already present (#1350) 2025-01-12 16:43:07 -06:00
Eric fb6a29872b docs: Add "HTML to Markdown" to the homepage (#1345) 2025-01-10 11:28:27 -06:00
rxliuli 187206062e docs: Update content script UI examples to use Svelte v5 (#1342) 2025-01-07 23:51:46 -06:00
Aaron 2615e29e52 docs: Add section to FAQ about teleports/portals 2025-01-07 23:37:53 -06:00
Aaron 8ca176d37e docs: Update i18n.md 2025-01-06 17:40:57 -06:00
Aaron cb2bf43f30 docs: Update content-scripts.md 2025-01-06 17:36:43 -06:00
Aaron 1719d17cff docs: Fix typo 2025-01-06 17:28:31 -06:00
Aaron 32afb8d97c docs: Improve manifest docs, mention entrypoint-specific options 2025-01-06 17:28:09 -06:00
Aaron 72b8a29d76 docs: Improve entrypoint docs 2025-01-06 17:09:20 -06:00
Aaron af0a32d478 docs: Add missing tabs in project structure 2025-01-06 16:59:23 -06:00
Nikolay Ponomarev 060e85f90e docs: Add missing web_accessible_resources to injectScript example (#1337) 2025-01-06 16:23:41 -06:00
Aaron 654a54ac79 docs: Update link 2025-01-05 10:14:49 -06:00
ntnyq ef24358942 docs: Fix unocss readme (#1329)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2025-01-04 17:01:43 -06:00
Aaron e5e67e39bd docs: Add paragraph on browser binary auto-discovery 2025-01-01 17:23:04 -06:00
Ahmed Dinar 228304bef9 docs: Added "Blync" to the homepage (#1319) 2025-01-01 08:56:07 -06:00
Paulo Pinto 78f97f32a2 fix(web-ext): Correctly pass browserConsole option to open devtools in Firefox (#1308) 2024-12-29 12:35:38 -06:00
Abhigyan Trips 459662a6c1 docs: Added "ZenGram" to the homepage (#1313) 2024-12-29 12:26:14 -06:00
Aaron b150a52471 fix(init): Remove "experimental" from bun package manager 2024-12-25 12:52:13 -06:00
Aaron 028c601515 chore: Fix typo in CLI docs 2024-12-25 12:51:41 -06:00
Aaron af382ef065 Fix changelog 2024-12-25 09:47:41 -06:00
GitHub Actions 91ef7f2ab5 chore(release): wxt v0.19.23
vhs / vhs (push) Waiting to run
2024-12-25 15:44:50 +00:00
Aaron 0bf7279c8f fix: Properly close readline instance on close (#1278) 2024-12-25 09:40:39 -06:00
Aaron 62525d33c6 fix: Allow runtime registered content scripts to not have matches (#1306) 2024-12-25 09:39:37 -06:00
Aaron 88ff40e301 docs: Fix typo in FAQ 2024-12-23 09:09:08 -06:00
Aaron 1a72a0cdc6 docs: Add paragraph on adding permissions 2024-12-22 09:14:31 -06:00
Amit Yadav 2b07b4bc12 docs: Fix invalid CSS color (#1299) 2024-12-22 09:09:49 -06:00
Abhigyan Trips 06c09e7c87 feat(hooks): Move entrypoints:resolved before debug logs and add entrypoints:found (#1292)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-12-20 21:09:31 -06:00
Amit Yadav 30b96ac87c docs: Added "Strong Password Generator" to the homepage (#1290) 2024-12-19 00:20:09 -06:00
Amit Yadav 2e9b5cffe8 docs: Added "Show IP Extension" to the homepage (#1289) 2024-12-18 17:13:11 -06:00
Aaron 3e1641a6ec docs: Add more comments on entrypoint options 2024-12-17 14:05:37 -06:00
GitHub Actions d64ca52bb0 chore(release): @wxt-dev/module-react v1.1.3
vhs / vhs (push) Waiting to run
2024-12-17 19:07:47 +00:00
Aaron 8c645fa1ce fix: Use react 19 in @wxt-dev/module-react and templates/react (#1285) 2024-12-17 12:57:50 -06:00
Nishu 79c9c89923 chore: Upgrade React to v19 in demo (#1280) 2024-12-17 12:30:48 -06:00
Aaron 11d93fe724 docs: Add pkg.pr.new docs to CONTRIBUTING.md 2024-12-17 12:05:47 -06:00
Aaron 039c561a80 chore: Simplify keyboard shortcuts (#1284) 2024-12-17 11:55:50 -06:00
GitHub Actions 64a704fc72 chore(release): @wxt-dev/module-svelte v2.0.2
vhs / vhs (push) Waiting to run
2024-12-17 16:41:07 +00:00
Aaron 4fbf137d15 fix: Svelte production errors and warnings on resolve conditions (#1283) 2024-12-17 10:35:39 -06:00
Luca Dalli ff065ab88b docs: Added "Cursorful" to the homepage (#1282) 2024-12-17 10:29:43 -06:00
Aaron 7fdf3fb968 docs: Add missing brackets to example 2024-12-16 16:12:00 -06:00
Aaron 7ebd451409 docs: Document how to use WASM 2024-12-16 16:07:16 -06:00
Aaron a7a48a8a75 docs: Add sponsors to wxt.dev homepage 2024-12-16 14:38:30 -06:00
Aaron 27298b7f22 docs: Sync READMEs 2024-12-16 14:35:16 -06:00
Aaron 565ce93a9a docs: Add sponsors section to README 2024-12-16 14:32:46 -06:00
Aaron 0bc6088b6a chore: Fix formatting 2024-12-16 13:48:41 -06:00
Aaron 2fb99e8fbb docs: Add netlify badge to homepage 2024-12-16 13:48:17 -06:00
Aaron cd2050c534 chore: Add code of conduct 2024-12-16 11:25:19 -06:00
aklinker1 5b557d0224 docs: Update wxt init GIF 2024-12-13 00:38:13 +00:00
Aaron 0137d79ba0 docs: Update colors to improve contrast ratio (#1275)
Co-authored-by: aklinker1 <aklinker1@users.noreply.github.com>
2024-12-12 18:36:24 -06:00
GitHub Actions e05fbf4fb5 chore(release): wxt v0.19.22
vhs / vhs (push) Waiting to run
2024-12-10 23:11:47 +00:00
Aaron 72e6ca5063 fix: Exclude entire import.meta.env object from content script output (#1267) 2024-12-10 17:06:25 -06:00
GitHub Actions af9e842fe0 chore(release): wxt v0.19.21
vhs / vhs (push) Waiting to run
2024-12-10 18:05:17 +00:00
Aaron 230962686f fix: Exclude skipped entrypoints from manifest (#1265) 2024-12-10 11:59:44 -06:00
GitHub Actions 413cd9354f chore(release): wxt v0.19.20
vhs / vhs (push) Waiting to run
2024-12-09 20:12:43 +00:00
不游 64a42de31f docs: fix colored-diff in es-modules.md (#1264) 2024-12-09 07:42:54 -06:00
Aaron f7f03e2669 fix: Import entrypoint improvements (#1207) 2024-12-08 12:10:05 -06:00
Aaron 1dc7c34bfd fix: Only show reopen browser shortcut when it can be done (#1263) 2024-12-08 08:55:01 -06:00
Aaron 0fd5c3846c docs: Fix gramar 2024-12-07 08:57:17 -06:00
Aaron e42e92f9df docs: Update "Using WXT" instructions 2024-12-07 08:56:13 -06:00
Kepi e45c91f941 docs: Add "EyeDropper" to homepage (#1260)
Co-authored-by: Aaron Klinker <aaronklinker1@gmail.com>
2024-12-07 08:47:33 -06:00
1natsu 8f71d80f94 feat: autoMount content script UIs (#1210)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-12-07 08:21:52 -06:00
Aaron Klinker 78e896e5fb docs: Remove duplicate section from upgrade docs 2024-12-07 01:12:23 -06:00
GitHub Actions a643852387 chore(release): wxt v0.19.19
vhs / vhs (push) Waiting to run
2024-12-06 00:28:20 +00:00
Nishu e221252325 fix: Exclude skipped entrypoints from Firefox sources zip (#1238)
Co-authored-by: Aaron Klinker <aaronklinker1@gmail.com>
2024-12-05 18:23:00 -06:00
Aaron 88f126e658 fix: Ensure content scripts are registered immediately in dev mode (#1253) 2024-12-05 18:16:38 -06:00
Aaron 17af05acc8 fix: Prevent changing dev server port when reloading config (#1241) 2024-12-05 11:48:49 -06:00
Jeremie Corpinot fd436a0d63 docs: Add "aesthetic Notion, styled" to homepage (#1247) 2024-12-04 16:00:23 -06:00
Nishu 0d796b63c2 feat: Keyboard shortcut to reopen the browser without restarting the dev command (#1211)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
Co-authored-by: Florian Metz <me@timeraa.dev>
2024-12-03 21:42:44 -06:00
GitHub Actions cb143d2bbc chore(release): wxt v0.19.18
vhs / vhs (push) Waiting to run
2024-12-03 23:00:59 +00:00
Aaron f3e7758521 types: Add overloads to ContentScriptContext#addEventListener for different targets (#1245) 2024-12-03 16:55:33 -06:00
Aaron 23ef101954 chore: Refactor findEntrypoints to return all entrypoints with skipped set properly (#1244) 2024-12-03 12:36:11 -06:00
spookyuser c2f5efbde4 docs: Update injectScript docs to match example from examples repo (#1240)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-12-03 12:23:33 -06:00
Takuya HARA 4ce178c592 docs: Changed "Chrome Extension" to "web extension" (#1229)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-12-03 11:07:46 -06:00
dependabot[bot] 7aa30afa7f chore(deps): bump codecov/codecov-action from 4 to 5 (#1237)
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-12-01 16:13:47 -06:00
GitHub Actions 90aaed202c chore(release): @wxt-dev/module-svelte v2.0.1
vhs / vhs (push) Waiting to run
2024-12-01 15:33:52 +00:00
Aaron c92ed13d66 fix: Modify dev vite.resolve.conditions to support Vite 6 + Svelte 5 (#1230) 2024-12-01 09:28:30 -06:00
Jaguar Zhou 0e4953fbfc fix: correct dev.reloadCommand restriction to consider only commands with suggested keys (#1226) 2024-11-29 12:07:09 -06:00
roechsli 799d687061 docs: Add "QA Compass" to homepage (#1223) 2024-11-28 10:34:20 -06:00
Aaron 866eb0694c Cleanup changelog 2024-11-28 08:48:40 -06:00
GitHub Actions e5723aab03 chore(release): wxt v0.19.17
vhs / vhs (push) Waiting to run
2024-11-28 14:42:49 +00:00
Jaguar Zhou f51f5dd19f doc: remove dead links generated by typedoc (#1222) 2024-11-28 08:33:11 -06:00
Aaron aae5f0789d fix: Make content script matches optional (#1220) 2024-11-28 00:00:18 -06:00
1natsu 586fe3950c fix: Correctly remove child elements with integrated UI remove (#1219) 2024-11-27 22:39:25 -06:00
Aaron 241c907c65 fix: Automatically convert MV3 content_security_policy to MV2 (#1168)
Co-authored-by: windmillcode0 <michaelodumosu57@gmail.com>
Co-authored-by: windmillcode0 <shieldmousetower734@gmail.com>
2024-11-27 10:14:32 -06:00
Aaron aab4244d84 fix: Update vite dependency range to support v6 (#1215) 2024-11-26 14:26:11 -06:00
Aaron 767a3a987c chore(vue-template): Fix incompatible typescript and vue-tsc versions (#1208) 2024-11-25 15:25:42 -06:00
Aaron a2924d872a fix: Revert "Validate entrypoints after hooks have modified them (54baf21)"
This reverts commit 54baf21490.
2024-11-25 15:08:55 -06:00
Aaron 54baf21490 fix: Validate entrypoints after hooks have modified them 2024-11-25 09:29:46 -06:00
Nishu 5a3790a7d3 fix: ESLint config being generated when ESLint is not installed. (#1198)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-11-22 08:54:05 -06:00
Aaron 236e099b81 docs: Update windows config for persisting browser profile 2024-11-22 08:53:16 -06:00
GitHub Actions 9b54bc4704 chore(release): @wxt-dev/storage v1.0.1
vhs / vhs (push) Waiting to run
2024-11-22 14:41:52 +00:00
Aaron ffb99af719 fix: use browser for mv2 storage (#1200) 2024-11-22 08:36:29 -06:00
Jaguar Zhou 90bb145d91 chore(vue-template): remove references to Vetur and TypeScript Vue Plugin (Volar) (#1197) 2024-11-22 08:21:06 -06:00
Mira Dobrovolskaya 190c87d120 docs: fix typo in entrypoints options example (#1194) 2024-11-21 11:15:10 -06:00
Tran Ngoc Tan 4c511d5728 docs: Add "YouTube Hider" to homepage (#1193) 2024-11-21 03:07:45 +01:00
Florian Metz b8ecbc5a54 docs: fix analyze typo in type (#1187) 2024-11-20 08:46:42 -06:00
Nithur 8c3d756187 docs: Add "Wandpen" to homepage (#1191)
Co-authored-by: Florian Metz <me@timeraa.dev>
2024-11-20 10:18:15 +01:00
Patato cfdc6b3e6b chore: Update Svelte template to Svelte 5 (#1184)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-11-17 14:58:09 -06:00
Aaron 226e6c9fbe docs: Add FAQ around configuring browser startup 2024-11-16 11:33:58 -06:00
Aaron db41f27072 feat: New server:created, server:started, and server:closed hooks (#1179) 2024-11-16 09:29:32 -06:00
Aaron db025cd3a2 fix: Re-initialize WXT modules correctly during development (#1176) 2024-11-16 08:56:08 -06:00
GitHub Actions 57229c69c1 chore(release): @wxt-dev/module-solid v1.1.3
vhs / vhs (push) Waiting to run
2024-11-15 15:46:51 +00:00
GitHub Actions 8f3a90eeb2 chore(release): @wxt-dev/module-react v1.1.2
vhs / vhs (push) Waiting to run
2024-11-15 15:38:36 +00:00
GitHub Actions a360965d92 chore(release): @wxt-dev/module-vue v1.0.2
vhs / vhs (push) Waiting to run
2024-11-15 15:28:53 +00:00
Aaron eb1ace6d20 fix: Use config:resolved hook to update config instead of ready (#1178) 2024-11-15 09:08:14 -06:00
GitHub Actions 497c902283 chore(release): wxt v0.19.16
vhs / vhs (push) Waiting to run
2024-11-15 14:57:29 +00:00
Aaron 4d4453b830 feat(hooks): Add new config:resolved hook (#1177) 2024-11-15 08:52:22 -06:00
GitHub Actions ef53580ed1 chore(release): wxt v0.19.15
vhs / vhs (push) Waiting to run
2024-11-14 16:41:09 +00:00
Aaron 52e5387d47 fix: Add extension ID to event used to invalidate ContentScriptContext (#1175) 2024-11-14 10:30:51 -06:00
Aaron f5b7f7e0e5 docs: Cleanup changelog 2024-11-14 10:11:39 -06:00
Aaron 592bdbe4d9 chore: Speed up sync-releases workflow by not building packages 2024-11-14 10:09:40 -06:00
Aaron 6fc227bad6 chore: Init changelog for storage package 2024-11-14 10:03:55 -06:00
Aaron d74f6b0735 feat: Extract wxt/storage to its own package, @wxt-dev/storage (#1129)
vhs / vhs (push) Waiting to run
2024-11-14 10:00:08 -06:00
dsrrlldr 62ea796045 docs: Add "Invoice Generator" and "Monthly Bill Tracker" to homepage (#1174) 2024-11-14 08:01:11 -06:00
Nishu 064704c9b7 fix: Add "/" to PublicPath and browser.runtime.getURL (#1171)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-11-14 02:02:00 -06:00
Qiwei Yang c846a1febf docs: Add "Text Search Pro" to homepage (#1172) 2024-11-14 01:07:53 -06:00
Aaron c3959e8427 fix: Respect configOrPath for dev server (#1169) 2024-11-13 16:25:03 -06:00
GitHub Actions e770f9b6b7 chore(release): wxt v0.19.14
vhs / vhs (push) Waiting to run
2024-11-13 15:06:31 +00:00
Aaron 67f35615a2 chore(deps): Bump dev and non-breaking major dependencies (#1167) 2024-11-13 08:32:29 -06:00
Aaron 5c7b6098a2 chore(deps): Upgrade all non-major dependencies (#1164) 2024-11-13 08:19:40 -06:00
Willow f7d12b7486 docs: add missing cd command (#1163) 2024-11-13 08:08:32 -06:00
rxliuli 3481313859 feat: automatically disable 'Show warning about Self-XSS when pasing code' in new chrome (#1159) 2024-11-13 08:07:37 -06:00
Aaron 2f23556893 Update changelog 2024-11-13 08:07:15 -06:00
GitHub Actions 330e39159a chore(release): @wxt-dev/module-svelte v2.0.0
vhs / vhs (push) Waiting to run
2024-11-13 14:04:41 +00:00
kongmoumou aa14676f91 fix: Throw when config file does not exist (#1156)
Co-authored-by: kongmoumou <kongmoumou@users.noreply.github.com>
2024-11-13 07:59:49 -06:00
Goran Nikic 199f330324 docs: Add "propbar.co.uk" to homepage (#1149)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-11-13 07:59:14 -06:00
jasonbla 63dee97ac3 docs: fix incorrect syntax for MatchPattern (#1148) 2024-11-13 07:56:58 -06:00
nirtamir2 b121ed2fe2 docs: Fix solid-js example (#1145) 2024-11-13 07:56:34 -06:00
Johnson Towoju 607e1162e5 docs: Add "YouTube Simple View" to homepage (#1142)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-11-13 07:55:41 -06:00
dsrrlldr b4d569a915 docs: Add "Keyword Rank Checker" to homepage (#1141) 2024-11-13 07:52:30 -06:00
Aaron 4fac364542 feat!: Svelte 5 support (#1104) 2024-11-13 07:48:57 -06:00
Aaron 51c7ee5fa8 chore: Update FUNDING.yml 2024-11-11 17:19:20 -06:00
Aaron 9b780f2d00 docs: Add FAQ about component library styles in content scripts 2024-11-11 16:36:04 -06:00
Aaron f5aec7ec9b chore: Create FUNDING.yml 2024-11-11 15:29:36 -06:00
Florian Metz 5d991eda31 feat(storage): Support storage items in batch functions (#990)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-10-30 23:36:24 -05:00
Bread Grocery 0318a34046 docs: Fix typo in popup and options EntrypointOptions (#1121) 2024-10-29 08:05:13 -05:00
1natsu e7c66304d3 chore: add "@types/chrome" to templates (#1119) 2024-10-28 14:33:21 -05:00
Ayub Kokabi 4603ebb511 docs: Add missing closing bracket (#1112)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-10-28 14:33:10 -05:00
GitHub Actions ea570c12b7 chore(release): @wxt-dev/i18n v0.2.3
vhs / vhs (push) Waiting to run
2024-10-28 13:48:20 +00:00
Bread Grocery c17ce34a27 fix: Prevent app crashes from parse errors due to incomplete file saves (#1114) 2024-10-28 08:43:21 -05:00
Berkin Anik 0e4d3ad8ab docs: fix typo in introduction page (#1117) 2024-10-28 08:30:23 -05:00
Aaron 4304f71df2 docs: Add section about env vars in the manifest 2024-10-23 09:05:07 -05:00
Aaron bb5ea34396 docs: Cleanup typos and broken links 2024-10-23 09:04:43 -05:00
GitHub Actions c30adb409c chore(release): @wxt-dev/i18n v0.2.2
vhs / vhs (push) Waiting to run
2024-10-23 13:44:57 +00:00
Bread Grocery ab83031462 feat: Add support for configuring the locales directory (#1109) 2024-10-23 08:39:30 -05:00
imnaK cd7285c3ef docs: fix wrong anchor to "Environment Variables" (#1107) 2024-10-22 22:58:22 -05:00
Aaron bdb775c88d Update changelog 2024-10-22 09:58:51 -05:00
Aaron d20793d5e6 docs: Use full URLs in README so they work on the docs site 2024-10-22 09:50:57 -05:00
GitHub Actions ae1e276577 chore(release): wxt v0.19.13
vhs / vhs (push) Waiting to run
2024-10-22 13:45:03 +00:00
Craig Slusher c031c6e82e feat(env): Load env from .env.[browser] variants (#1078)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-10-22 08:36:24 -05:00
Malix d06f8128f5 enhance(docs): comparison to real footnotes (#1096)
Co-authored-by: Aaron <aaronklinker1@gmail.com>
2024-10-22 08:35:23 -05:00
465 changed files with 40121 additions and 15619 deletions
+10
View File
@@ -0,0 +1,10 @@
extends:
- '@commitlint/config-conventional'
rules:
subject-case:
- 0
- always
- - sentence-case
- start-case
- pascal-case
- upper-case
+12
View File
@@ -1,5 +1,17 @@
# See https://git-scm.com/docs/gitattributes#_pattern_format for more about `.gitattributes`.
# Normalize EOL for all files that Git considers text files
* text=auto eol=lf
# Mark lock files as generated to avoid diffing
pnpm-lock.yaml linguist-generated
package-lock.json linguist-generated
bun.lockb linguist-generated
bun.lock linguist-generated
yarn.lock linguist-generated
# Exclude templates from language statistics
templates/**/* linguist-vendored
# Other generated files
packages/browser/src/gen/** linguist-generated
+9
View File
@@ -0,0 +1,9 @@
# Set default
* @aklinker1
# Secure Directories
/.github/ @aklinker1
# Creator of specific wxt modules
/packages/auto-icons/ @Timeraa
/packages/unocss/ @Timeraa
+3
View File
@@ -0,0 +1,3 @@
# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/displaying-a-sponsor-button-in-your-repository#about-funding-files
github: wxt-dev
+1
View File
@@ -1,6 +1,7 @@
name: "\U0001F41E Bug report"
description: Report an issue with WXT
labels: [pending-triage]
type: Bug
body:
- type: markdown
attributes:
+1 -1
View File
@@ -2,7 +2,7 @@
name: Feature request
about: Suggest an idea for WXT
title: ''
labels: feature
type: Feature
assignees: ''
---
+11 -10
View File
@@ -1,20 +1,21 @@
name: Basic Setup
description: Install PNPM, Node, and dependencies
description: Install Bun and dependencies
inputs:
install:
default: 'true'
description: Whether or not to run 'pnpm install'
description: Whether or not to run 'bun install'
runs:
using: composite
steps:
- name: Setup PNPM
uses: pnpm/action-setup@v4
- name: Setup NodeJS
uses: actions/setup-node@v4
- name: 🛠️ Setup Bun
uses: oven-sh/setup-bun@735343b667d3e6f658f44d0eca948eb6282f2b76 # v2.0.2
with:
node-version: 18
cache: pnpm
- name: Install Dependencies
bun-version-file: '.tool-versions'
- name: 📦 Install Dependencies
if: ${{ inputs.install == 'true' }}
shell: bash
run: pnpm install
run: bun ci ${{ inputs.installArgs }}
+1 -3
View File
@@ -6,9 +6,7 @@
version: 2
updates:
- package-ecosystem: npm
directories:
- /
- packages/*
directory: /
schedule:
interval: 'monthly'
- package-ecosystem: 'github-actions'
+13
View File
@@ -0,0 +1,13 @@
### Overview
<!-- Describe your changes and why you made them -->
### Manual Testing
<!-- Describe how to test your changes to make sure the PR works as intended -->
### Related Issue
<!-- If this PR is related to an issue, please link it here -->
This PR closes #<issue_number>
+111
View File
@@ -0,0 +1,111 @@
name: ✨ Auto-label PR
on:
pull_request_target:
types: [opened, synchronized, reopened]
jobs:
update-pr:
name: Update PR
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Gather Info
id: check
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const { data: pr } = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number
});
// Check if PR has assignees
const hasAssignees = pr.assignees && pr.assignees.length > 0;
core.setOutput('has_assignees', hasAssignees);
core.setOutput('author', pr.user.login);
// Get list of changed files
const { data: files } = await github.rest.pulls.listFiles({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number
});
// Find all packages that were modified
const packagesRegex = /^packages\/([^\/]+)\//;
const affectedPackages = new Set();
for (const file of files) {
const match = file.filename.match(packagesRegex);
if (match) {
affectedPackages.add(match[1]);
}
}
const labels = Array.from(affectedPackages).map(pkg => `pkg/${pkg}`);
core.setOutput('labels', JSON.stringify(labels));
console.log('Detected package labels:', labels);
// Get current labels on the PR that match pkg/* pattern
const currentPkgLabels = pr.labels
.map(label => label.name)
.filter(name => name.startsWith('pkg/'));
core.setOutput('current_pkg_labels', JSON.stringify(currentPkgLabels));
console.log('Current pkg labels:', currentPkgLabels);
- name: Sync Author
if: steps.check.outputs.has_assignees == 'false'
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
await github.rest.issues.addAssignees({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
assignees: ['${{ steps.check.outputs.author }}']
});
console.log('Assigned PR author: ${{ steps.check.outputs.author }}');
- name: Sync Labels
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
with:
script: |
const newLabels = ${{ steps.check.outputs.labels }};
const currentLabels = ${{ steps.check.outputs.current_pkg_labels }};
// Find labels to add (in newLabels but not in currentLabels)
const labelsToAdd = newLabels.filter(label => !currentLabels.includes(label));
// Find labels to remove (in currentLabels but not in newLabels)
const labelsToRemove = currentLabels.filter(label => !newLabels.includes(label));
// Add new labels
if (labelsToAdd.length > 0) {
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
labels: labelsToAdd
});
console.log('Added labels:', labelsToAdd);
}
// Remove obsolete labels
for (const label of labelsToRemove) {
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
name: label
});
console.log('Removed label:', label);
}
if (labelsToAdd.length === 0 && labelsToRemove.length === 0) {
console.log('No label changes needed');
}
@@ -0,0 +1,36 @@
name: 🔔 Notify Unreleased Commits
on:
workflow_dispatch:
schedule:
- cron: '0 20 * * 1' # Weekly at 8 PM UTC (3 PM CT)
jobs:
notify:
runs-on: ubuntu-22.04
if: github.repository_owner == 'wxt-dev'
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- name: List Commits
id: list-commits
run: |
./scripts/list-unreleased-commits.sh > summary.txt
- name: Discord notification
run: |
PAYLOAD=$(jq -n --arg content "${{ env.MESSAGE }}" '{"content": $content}')
curl -X POST \
-F "payload_json=${PAYLOAD}" \
-F "file1=@summary.txt" \
$DISCORD_WEBHOOK
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_UNRELEASED_COMMITS }}
MESSAGE: |
If a package needs released, please [run the workflow](<https://github.com/wxt-dev/wxt/actions/workflows/release.yml>).
Before running, consider:
- Are there any breaking changes? If so, prepare a list of breaking changes and update the changelog and release notes after the release.
- Are there any PRs open that we wait to release after they're merged?
+22 -5
View File
@@ -1,4 +1,4 @@
name: Continuous Publish
name: ✨ pkg.pr.new
on:
push:
branches:
@@ -7,11 +7,28 @@ on:
branches:
- main
permissions:
contents: read
jobs:
build:
name: Publish Test Packages
runs-on: ubuntu-22.04
if: ${{ github.repository == 'wxt-dev/wxt' }}
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: pnpm buildc all
- run: pnpx pkg-pr-new publish --compact './packages/*'
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup
uses: ./.github/actions/setup
- name: Build All Packages
run: bun run buildc all
- name: Publish
run: bun pkg-pr-new publish --compact --bun './packages/*'
- name: DEBUG
if: always()
run: ls -lhA
working-directory: packages/analytics
+42
View File
@@ -0,0 +1,42 @@
name: 🎉 PR closed
on:
pull_request_target:
types:
- closed
permissions:
contents: read
pull-requests: write
jobs:
thank-you:
runs-on: ubuntu-latest
if: github.event.pull_request.merged == true
steps:
- name: Log PR Author Info
run: |
echo "PR Author Login: ${{ github.event.pull_request.user.login }}"
echo "PR Author ID: ${{ github.event.pull_request.user.id }}"
echo "PR Author Type: ${{ github.event.pull_request.user.type }}"
echo "PR Author Node ID: ${{ github.event.pull_request.user.node_id }}"
- name: Post Thank You Comment
if: >-
github.event.pull_request.user.login != 'aklinker1' &&
github.event.pull_request.user.login != 'Timeraa' &&
github.event.pull_request.user.login != 'PatrykKuniczak' &&
github.event.pull_request.user.login != 'dependabot[bot]' &&
github.event.pull_request.user.login != 'copilot-swe-agent[bot]'
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env:
comment: Thanks for helping make WXT better!
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: process.env.comment
})
+26
View File
@@ -0,0 +1,26 @@
name: 🛡️ Check PR Title
on:
pull_request:
types: [opened, edited]
jobs:
lint-pr-title:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
# Only fetch the config file from the repository
sparse-checkout-cone-mode: false
sparse-checkout: .commitlintrc.yml
- name: Install dependencies
run: npm install --global @commitlint/config-conventional commitlint
- name: Check PR title with commitlint
env:
PR_TITLE: ${{ github.event.pull_request.title }}
HELP_URL: https://github.com/wxt-dev/wxt/blob/main/CONTRIBUTING.md#conventional-pr-titles
run: echo "$PR_TITLE" | npx commitlint --help-url $HELP_URL
+26 -8
View File
@@ -1,4 +1,4 @@
name: Publish Docs
name: 📝 Publish Docs
on:
push:
branches:
@@ -10,20 +10,38 @@ on:
required: true
default: latest
permissions:
contents: read
jobs:
publish:
# Only run if it's the upstream repository, not forks
if: github.repository == 'wxt-dev/wxt'
name: Publish Docs
runs-on: ubuntu-22.04
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- uses: docker/login-action@v3
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup
uses: ./.github/actions/setup
- name: Login to Docker Registry
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with:
registry: https://${{ secrets.DOCKER_REGISTRY_HOSTNAME }}
username: ${{ secrets.DOCKER_REGISTRY_USERNAME }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
- run: pnpm docs:build
- run: docker build docs/.vitepress -t ${{ secrets.DOCKER_REGISTRY_HOSTNAME }}/wxt/docs:${{ github.event.inputs.tag || 'latest' }}
- run: docker push ${{ secrets.DOCKER_REGISTRY_HOSTNAME }}/wxt/docs:${{ github.event.inputs.tag || 'latest' }}
- run: curl -X POST -i ${{ secrets.UPDATE_DOCS_WEBHOOK }}
- name: Build docs
run: |
bun run docs:build
docker build docs/.vitepress -t ${{ secrets.DOCKER_REGISTRY_HOSTNAME }}/wxt/docs:${{ github.event.inputs.tag || 'latest' }}
- name: Push Image
run: docker push ${{ secrets.DOCKER_REGISTRY_HOSTNAME }}/wxt/docs:${{ github.event.inputs.tag || 'latest' }}
- name: Deploy
run: curl -X POST -i ${{ secrets.UPDATE_DOCS_WEBHOOK }}
+34 -14
View File
@@ -1,4 +1,4 @@
name: Release
name: 🚀 Release
on:
workflow_dispatch:
inputs:
@@ -7,47 +7,67 @@ on:
default: wxt
type: choice
options:
- analytics
- auto-icons
- i18n
- is-background
- module-react
- module-solid
- module-svelte
- module-vue
- runner
- storage
- unocss
- webextension-polyfill
- wxt
permissions:
contents: read
jobs:
validate:
name: Validate
uses: './.github/workflows/validate.yml'
secrets: inherit
publish:
runs-on: ubuntu-22.04
name: Publish
runs-on: ubuntu-24.04
permissions:
contents: write # Push version changes
id-token: write # OIDC for NPM publishing
needs:
- validate
steps:
- uses: actions/checkout@v4
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
ssh-key: ${{ secrets.DEPLOY_KEY }} # https://github.com/sbellone/release-workflow-example
- uses: ./.github/actions/setup
- name: Setup
uses: ./.github/actions/setup
- name: Configure Git
run: |
git config user.name 'github-actions[bot]'
git config user.email 'github-actions[bot]@users.noreply.github.com'
git config --global push.followTags true
- name: Bump and Tag
run: |
git config user.email "github-actions@users.noreply.github.com"
git config user.name "GitHub Actions"
pnpm tsx scripts/bump-package-version.ts ${{ inputs.package }}
bun run scripts/bump-package-version.ts ${{ inputs.package }}
git push
git push --tags
- name: NPM
run: |
echo "//registry.npmjs.org/:_authToken=${{ secrets.NPM_AUTH_TOKEN }}" > ~/.npmrc
pnpm build
pnpm publish
- name: Publish to NPM
working-directory: packages/${{ inputs.package }}
run: |
bun pm pack
sudo npm i -g npm@latest
npm publish *.tgz
- name: GitHub Release
run: pnpm tsx scripts/create-github-release.ts ${{ inputs.package }}
- name: Create GitHub release
run: bun run scripts/create-github-release.ts ${{ inputs.package }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+27 -9
View File
@@ -1,4 +1,4 @@
name: Sync Releases
name: 🔄 Sync Releases
on:
workflow_dispatch:
inputs:
@@ -7,20 +7,38 @@ on:
default: wxt
type: choice
options:
- wxt
- module-react
- module-vue
- module-svelte
- module-solid
- analytics
- auto-icons
- i18n
- is-background
- module-react
- module-solid
- module-svelte
- module-vue
- runner
- storage
- webextension-polyfill
- wxt
permissions:
contents: read
jobs:
sync:
name: Sync Releases
runs-on: ubuntu-22.04
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: pnpm tsx scripts/sync-releases.ts ${{ inputs.package }}
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup
uses: ./.github/actions/setup
with:
installArgs: --ignore-scripts
- name: Sync Releases
run: bun run scripts/sync-releases.ts ${{ inputs.package }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,51 @@
name: 🔄 Update @wxt-dev/browser
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * *' # Every day at midnight
permissions:
contents: read
jobs:
sync:
name: 'Sync with @types/chrome'
runs-on: ubuntu-latest
if: github.repository_owner == 'wxt-dev'
permissions:
contents: write # Push version changes
id-token: write # OIDC for NPM publishing
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ssh-key: ${{ secrets.DEPLOY_KEY }}
- name: Setup
uses: ./.github/actions/setup
with:
installArgs: --ignore-scripts
- name: Generate Latest Code
working-directory: packages/browser
run: bun run gen
- name: Run Checks
working-directory: packages/browser
run: bun run check
- name: Commit Changes
id: commit
uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
commit_message: 'fix: Upgrade `@wxt-dev/browser` to latest `@types/chrome` version'
- name: Publish to NPM
if: steps.commit.outputs.changes_detected == 'true'
working-directory: packages/browser
run: |
bun pm pack
sudo npm i -g npm@latest
npm publish *.tgz
+95 -32
View File
@@ -1,4 +1,4 @@
name: Validate
name: 🛡️ Validate
on:
workflow_call:
pull_request:
@@ -6,46 +6,94 @@ on:
branches:
- main
permissions:
contents: read
jobs:
checks:
name: Checks
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: pnpm check
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup
uses: ./.github/actions/setup
- name: Basic Checks
run: bun run check
builds:
name: Builds
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: pnpm buildc all
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup
uses: ./.github/actions/setup
- name: Build All Packages
run: bun run buildc all
build-demo:
name: Build Demo
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: pnpm build:all
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup
uses: ./.github/actions/setup
- name: Build
run: bun run build:all
working-directory: packages/wxt-demo
- run: pnpm wxt zip
- name: ZIP
run: bun run wxt zip
working-directory: packages/wxt-demo
tests:
runs-on: ubuntu-22.04
name: Tests (${{ matrix.title }})
runs-on: ${{ matrix.os }}
strategy:
matrix:
include:
- title: 'Linux'
os: ubuntu-22.04
coverage: true
- title: 'Windows'
os: windows-latest
coverage: false
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- uses: oven-sh/setup-bun@v2
- name: pnpm test:coverage
run: pnpm test:coverage -- --reporter=default --reporter=hanging-process
- uses: codecov/codecov-action@v4
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup
uses: ./.github/actions/setup
- name: Setup PNPM
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
with:
version: latest
- name: Run Tests
if: ${{ ! matrix.coverage }}
run: bun run test
- name: Run Tests (Coverage)
if: matrix.coverage
run: bun run test:coverage --reporter=default --reporter=hanging-process
- name: Upload Coverage
if: matrix.coverage
uses: codecov/codecov-action@57e3a136b779b570ffcdbf80b3bdc90e7fab3de2 # v6.0.0
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
windows-tests:
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: pnpm test
template:
name: Template
runs-on: ubuntu-22.04
strategy:
fail-fast: false
@@ -57,19 +105,34 @@ jobs:
- vanilla
- vue
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- run: pnpm pack
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup
uses: ./.github/actions/setup
- name: Pack WXT package
run: bun pm pack
working-directory: packages/wxt
- run: npm i
- name: Install Dependencies
run: npm i
working-directory: templates/${{ matrix.template }}
- run: npm i -D ../../packages/wxt/wxt-*.tgz
- name: Install Packed WXT
run: npm i -D ../../packages/wxt/wxt-*.tgz
working-directory: templates/${{ matrix.template }}
- run: pnpm compile
- name: Type Check Template
run: bun run compile
if: matrix.template != 'svelte'
working-directory: templates/${{ matrix.template }}
- run: pnpm check
- name: Type Check Template
run: bun run check
if: matrix.template == 'svelte'
working-directory: templates/${{ matrix.template }}
- run: pnpm build
- name: Build Template
run: bun run build
working-directory: templates/${{ matrix.template }}
+39 -10
View File
@@ -1,29 +1,58 @@
name: vhs
name: 📼 VHS
on:
push:
paths:
- 'docs/tapes/*.tape'
workflow_dispatch:
permissions:
contents: read
jobs:
vhs:
runs-on: ubuntu-22.04
name: Create VHS
runs-on: macos-latest
if: ${{ github.repository == 'wxt-dev/wxt' }}
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/setup
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
install: 'false'
- name: Preinstall WXT
ref: ${{ github.ref_name }}
- name: Setup PNPM
uses: pnpm/action-setup@fc06bc1257f339d1d5d8b3a19a8cae5388b55320 # v5.0.0
- name: Setup NodeJS
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5.0.0
with:
cache: pnpm
- name: Setup Go
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c
with:
go-version: '1.25.1'
# This prevents pnpm dlx from downloading WXT in the video
- name: Pre-install WXT
run: |
pnpm store add wxt@latest
pnpm dlx wxt@latest --version
- uses: charmbracelet/vhs-action@v2.1.0
with:
path: 'docs/tapes/init-demo.tape'
- uses: stefanzweifel/git-auto-commit-action@v5
- name: Record VHS
run: |
brew install ttyd ffmpeg
go install github.com/charmbracelet/vhs@517bcda0faf416728bcf6b7fe489eb0e2469d9b5 # v0.10.0
vhs docs/tapes/init-demo.tape
- name: Save recorded GIF
uses: stefanzweifel/git-auto-commit-action@04702edda442b2e678b25b537cec683a1493fcb9 # v7.1.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
commit_message: 'docs: Update `wxt init` GIF'
commit_user_name: github-actions[bot]
commit_user_email: github-actions[bot]@users.noreply.github.com
commit_author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
# https://github.com/charmbracelet/vhs#output
file_pattern: 'docs/assets/*.gif'
+4 -2
View File
@@ -1,13 +1,16 @@
.DS_Store
.env
.env.*
!packages/wxt/src/core/utils/__tests__/fixtures/.env
.idea
.output
.webextrc
.wxt
.wxt-runner
*.log
/.vscode/
*.tgz
/docs/.vitepress/cache
docs/.vitepress/.temp
coverage
dist
node_modules
@@ -19,6 +22,5 @@ templates/*/yarn.lock
templates/*/package-lock.json
docs/api/reference
stats.html
.tool-versions
.cache
*-stats.txt
+6
View File
@@ -0,0 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/DavidAnson/markdownlint/refs/heads/main/schema/markdownlint-config-schema.json",
"line-length": false,
"no-inline-html": false,
"first-line-heading": false
}
+9
View File
@@ -0,0 +1,9 @@
node_modules
.git
.output
dist
# Generated files
packages/wxt/README.md
packages/*/CHANGELOG.md
docs/api
+1
View File
@@ -5,3 +5,4 @@ dist
docs/.vitepress/cache
pnpm-lock.yaml
CHANGELOG.md
packages/browser/src/gen
+2
View File
@@ -1,2 +1,4 @@
singleQuote: true
endOfLine: lf
plugins:
- prettier-plugin-jsdoc
+2
View File
@@ -0,0 +1,2 @@
bun 1.3.12
nodejs 24.14.1
+7
View File
@@ -0,0 +1,7 @@
{
"recommendations": [
"davidanson.vscode-markdownlint",
"esbenp.prettier-vscode",
"github.vscode-github-actions"
]
}
+15
View File
@@ -0,0 +1,15 @@
{
// Set default formatter
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[yaml]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
"[markdown]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
// Additional guidelines for Copilot
"github.copilot.chat.codeGeneration.instructions": [
{ "file": "CONTRIBUTING.md" }
],
"oxc.enable": true
}
+128
View File
@@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
- Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
- The use of sexualized language or imagery, and sexual attention or
advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email
address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
<aaronklinker1@gmail.com>.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
<https://www.contributor-covenant.org/version/2/0/code_of_conduct.html>.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
<https://www.contributor-covenant.org/faq>. Translations are available at
<https://www.contributor-covenant.org/translations>.
+127 -35
View File
@@ -6,24 +6,54 @@ If you are changing the docs or fixing a bug, feel free to fork and open a PR.
If you want to add a new feature, please create an issue or discussion first so we can decide if the feature is inline with the vision for WXT.
## WXT's Vision
WXT is two things:
1. A build tool
2. A set of runtime utilities
The long term goal of WXT is provide an opinionated build tool that keeps WXT projects standard, while providing light-weight runtime utils that simplify a lot of the boilerplate/overhead when setting up a new extension.
I also want to provide a way for developers to use either one of those two things independently, and not require them to use both. This is why all of WXT's runtime utils are shipped as their own NPM packages, most of them not bundled inside the core `wxt` package. If you just want to use the packages, they're available, and if you just want to use WXT's built tool, you don't have to import any of WXT's utilities, you can use your own.
> The few runtime utils shipped inside WXT are things that should be used by 90% of extensions. That said, they're also legacy utils left in from before I started creating separate NPM packages, and in the future, they may be removed from the core package.
## Conventional Commits
This project uses [Conventional Commits](https://www.conventionalcommits.org/en) to automate versioning. If you're a new contributor, don't worry about this. When you open a PR, a maintainer will change the PR's title so it's in the style of conventional commits, but that's all.
This project uses [Conventional Commit format](https://www.conventionalcommits.org/en/v1.0.0/) to automatically generate a changelog and better understand the changes in the project
Maintainers, commits to the `main` branch (either directly or via PRs) must be valid conventional commits.
Here are some examples of conventional commit messages:
- `feat: add new functionality`
- `fix: correct typos in code`
- `ci: add GitHub Actions for automated testing`
## Conventional PR Titles
The title of your pull request should follow the [conventional commit format](#conventional-commits). When a pull request is merged to the main branch, all changes are going to be squashed into a single commit. The message of this commit will be the title of the pull request. And for every release, the commit messages are used to generate the changelog.
## Breaking Changes Policy
A quick word on WXT's breaking changes policy. I am willing to make breaking changes, but they have to be for a good enough reason - they have to make WXT better as a whole, they can't be based on one opinion.
Breaking changes also require a major release. Major releases have happened once or twice a year, so after you merge your PR, you'll have to wait a little bit before it is released.
To make a breaking change:
1. Make sure you're PR is targeting the `major` branch
2. Add `!` after the conventional commit type (`fix!: ...`, `feat!: ...`, `chore!: ...`, etc) to indicate that it is a breaking change
3. At the top of the PR, provide documentation that will inform developers about the breaking change, why it was done, and how to migrate their extension so nothing breaks.
- This documentation will be put ["Upgrading WXT"](https://wxt.dev/guide/resources/upgrading.html) page in the docs, read through previous breaking change docs for an idea of what is required.
## Setup
WXT uses `pnpm`, so make sure you have it installed.
WXT uses Bun for package management and development. Install it from: <https://bun.com/>
Then install dependencies:
```sh
corepack enable
```
Then, simply run the install command:
```sh
pnpm i
bun install
```
## Development
@@ -31,47 +61,68 @@ pnpm i
Here are some helpful commands:
```sh
# Build WXT package
pnpm build
# Build WXT package and workspace dependencies
bun run --filter wxt build
```
```sh
# Build WXT package, then build demo extension
cd packages/wxt-demo
pnpm build
```
```sh
# Build WXT package, then start the demo extension in dev mode
cd packages/wxt-demo
pnpm dev
# Build workspace dependencies, then start the demo extension in dev mode
bun run --filter wxt-demo dev
```
```sh
# Run unit and E2E tests
pnpm test
bun run test
```
```sh
# Start the docs website locally
pnpm docs:dev
bun run docs:dev
```
> Above, we used bun's `--filter` flag to choose which package to run a command in, but there are other ways:
>
> ```sh
> bun run -F @wxt-dev/i18n build
> # or
> bun run --cwd packages/i18n build
> # or
> cd packages/i18n
> bun run build
> ```
>
> Pick your poison!
## Profiling
```sh
# Build the latest version
pnpm --filter wxt build
bun run --filter wxt build
# CD to the demo directory
cd packages/wxt-demo
# 1. Generate a flamechart with 0x
pnpm dlx 0x node_modules/wxt/bin/wxt.mjs build
# 2. Inspect the process with chrome @ chrome://inspect
pnpm node --inspect node_modules/wxt/bin/wxt.mjs build
```
Then there are a few different ways to profile WXT commands:
- Generate a flamechart with 0x:
```sh
bunx 0x node_modules/wxt/bin/wxt.mjs build
```
- Create a CPU profile:
```sh
bun run --cpu-prof node_modules/wxt/bin/wxt.mjs build
```
- Debug the process:
```sh
bun run --inspect node_modules/wxt/bin/wxt.mjs build
```
## Updating Docs
Documentation is written with VitePress, and is located in the `docs/` directory.
@@ -87,7 +138,7 @@ WXT has unit and E2E tests. When making a change or adding a feature, make sure
To run tests for a specific file, add the filename at the end of the test command:
```sh
pnpm test manifest-contents
bun run --filter wxt test manifest-contents
```
All test (unit and E2E) for all packages are ran together via [Vitest workspaces](https://vitest.dev/guide/#workspaces-support).
@@ -96,7 +147,7 @@ If you want to manually test a change, you can modify the demo project for your
## Templates
Each directory inside `templates/` is it's own standalone project. Simply `cd` into the directory you're updating, install dependencies with `npm` (NOT `pnpm`), and run the relevant commands
Each directory inside `templates/` is it's own standalone project. Simply `cd` into the directory you're updating, install dependencies with `npm` (NOT `bun`), and run the relevant commands
```sh
cd templates/vue
@@ -112,7 +163,7 @@ Note that templates are hardcoded to a specific version of `wxt` from NPM, they
"typescript": "^5.3.2",
"vite-plugin-solid": "^2.7.0",
- "wxt": "^0.8.0"
+ "wxt": "../.."
+ "wxt": "../../packages/wxt"
}
```
@@ -137,10 +188,51 @@ Releases are done with GitHub actions:
## Upgrading Dependencies
Use [`taze`](https://www.npmjs.com/package/taze) to upgrade dependencies throughout the entire monorepo.
WXT has custom rules around what dependencies can be upgraded. Use the `scripts/upgrade-deps.ts` script to upgrade dependencies and follow these rules.
```sh
pnpm dlx taze -r
bun run scripts/upgrade-deps.ts
```
Configuration is in [`taze.config.ts`](./taze.config.ts).
To see all the options, run:
```sh
bun run scripts/upgrade-deps.ts --help
```
## Install Unreleased Versions
This repo uses <https://pkg.pr.new> to publish versions of all it's packages for almost every commit. You can install them via:
```sh
npm i https://pkg.pr.new/[package-name]@[ref]
```
Or use one of the shorthands:
```sh
# Install the latest build of `wxt` from a PR:
npm i https://pkg.pr.new/wxt@1283
# Install the latest build of `@wxt-dev/module-react` on the `main` branch
npm i https://pkg.pr.new/@wxt-dev/module-react@main
# Install `@wxt-dev/storage` from a specific commit:
npm i https://pkg.pr.new/@wxt-dev/module-react@426f907
```
## Blog Posts
Anyone is welcome to submit a blog post on <https://wxt.dev/blog>!
> [!NOTE]
> Before starting on a blog post, please message Aaron on Discord or start a discussion on GitHub to get permission to write about a topic, but most topics are welcome: Major version updates, tutorials, etc.
- **English only**: Blog posts should be written in English. Unfortunately, our maintainers don't have the bandwidth right now to translate our docs, let alone blog posts. Sorry 😓
- **AI**: Please only use AI to translate or proof-read your blog post. Don't generate the whole thing... We don't want to publish that.
## Become a Maintainer
If you're interested in becoming a maintainer, send an email to Aaron at <aaronklinker1@gmail.com> with your github username saying you're interested. The process is very informal, I will add you quickly if you've contributed code or answered questions and helped out the community!
Maintainers don't have to just write code - they can manage issues, answer questions, review PRs, organize and prioritize work - there's lots of ways for you to help out.
+90
View File
@@ -0,0 +1,90 @@
# Maintainers
A couple of things for you to consider before merging a PR or giving the go-ahead on a feature proposal.
## Be picky about new features and packages
We are responsible for maintaining them and fixing related bugs after the PR is merged. The community can always release their own WXT modules or packages, not everything needs to be built into WXT.
## Prefer standards over customization
Don't merge PRs that just add another way to do something, like [this one](https://github.com/wxt-dev/wxt/pull/2053#issuecomment-3857010196).
WXT is opinionated, if you have questions about what is WXT's opinion or we need to create a new one, create an issue and @ me to discuss.
## PRs should be small and targeted
A PR should make one change. They should not make any unrelated changes outside of accomplishing the one thing. This makes PRs easier to review and they get merged more quickly - a win-win for everyone.
## `@wxt-dev/*` packages are separate
We can't make changes to these packages assuming people are using them only with WXT. For example, I almost missed [this PR](https://github.com/wxt-dev/wxt/pull/2049#issuecomment-3861251599).
I want these packages to be usable on their own so if people don't like WXT's build tool, they can still use our other awesome packages.
## Minimize dependencies
I don't like how heavy lots of frameworks are. It's unavoidable to a certain extent, but if you can do something without another dependency, try to.
If you need a dependency, look for one with zero dependencies and that's respectable.
## Look at milestones
I've organized WXT's long term plans into [milestones](https://github.com/wxt-dev/wxt/milestones), check those out to get an idea of my priorities for some of the larger features.
## Require tests
If someone opens a PR to fix a bug but doesn't include tests, don't merge the PR. Tests are required to prevent regressions and maintain a codebase long term.
## Ask for reproductions for bugs
You don't need to triage bugs if someone doesn't give you enough information. You can always ask for a repo with a reproduction or wait for more details.
If there's not an easy way to reproduce a bug, you're wasting your time triaging it. Just be mindful of your own time!
Here's an example of how to ask for a reproduction: <https://github.com/wxt-dev/wxt/issues/2064#issuecomment-3862579110>. You could be more blunt than this.
## Add yourself as a code owner
If you want to be responsible for a specific package or directory, add yourself to the [`.github/CODEOWNERS`](https://github.com/wxt-dev/wxt/blob/main/.github/CODEOWNERS) file to get added as a reviewer to PRs automatically. You can also add yourself to the default list to be added as a reviewer on all PRs.
## Releasing Package Updates
Releases are done with GitHub actions:
- Use the [Release workflow](https://github.com/wxt-dev/wxt/actions/workflows/release.yml) to release a single package in the monorepo. This automatically detects the version change with conventional commits, builds and uploads the package to NPM, and creates a GitHub release.
- Use the [Sync Releases workflow](https://github.com/wxt-dev/wxt/actions/workflows/sync-releases.yml) to sync the GitHub releases with changes to the changelog. To change a release, update the `CHANGELOG.md` file and run the workflow. It will sync the releases of a single package in the monorepo.
## Creating New Packages
Example PR: <https://github.com/wxt-dev/wxt/pull/2152>
1. Create the package.
2. Update CI workflow inputs.
3. Add docs page and version for "Other Packages" dropdown.
4. Merge the PR.
5. Tag the commit (look at other tags for pattern):
```sh
git tag <dir-name>-v<version>
git push --tags
```
6. Publish the package to NPM:
```sh
cd packages/<dir-name>
bun publish --access public
```
7. Create a basic release on GitHub mentioning the new package is available.
A couple of things to note:
- pkg.pr.new will fail on the original PR. It's fine to ignore and merge your PR as long as it fails due to your new package not being published to NPM yet.
- The regular release workflow DOES NOT WORK for new packages. You have to have at least one `<dir-name>-v<version>` tag created before you can run that workflow for your new package.
- You don't need to create a CHANGELOG.md file for the package, it will be created automatically after future changes are released via the normal release workflow.
+23 -43
View File
@@ -1,50 +1,32 @@
<h1 align="center">
<img align="top" width="44" src="https://raw.githubusercontent.com/wxt-dev/wxt/HEAD/docs/public/hero-logo.svg" alt="WXT Logo">
<span>WXT</span>
</h1>
<div align="center">
<p align="center">
<a href="https://www.npmjs.com/package/wxt" target="_blank"><img alt="npm version" src="https://img.shields.io/npm/v/wxt?labelColor=black&color=%234fa048"></a>
<span> </span>
<a href="https://www.npmjs.com/package/wxt" target="_blank"><img alt="downloads" src="https://img.shields.io/npm/dm/wxt?labelColor=black&color=%234fa048"></a>
<span> </span>
<a href="https://github.com/wxt-dev/wxt/blob/main/LICENSE" target="_blank"><img alt="license | MIT" src="https://img.shields.io/npm/l/wxt?labelColor=black&color=%234fa048"></a>
<span> </span>
<a href="https://codecov.io/github/wxt-dev/wxt" target="_blank"><img alt="coverage" src="https://img.shields.io/codecov/c/github/wxt-dev/wxt?labelColor=black&color=%234fa048"></a>
</p>
# <img align="top" width="44" src="https://raw.githubusercontent.com/wxt-dev/wxt/HEAD/docs/public/hero-logo.svg" alt="WXT Logo"> WXT
<p align="center">
<span>Next-gen framework for developing web extensions.</span>
<br/>
<span>⚡</span>
<br/>
<q><i>It's like Nuxt, but for Web Extensions</i></q>
</p>
[![npm version](https://img.shields.io/npm/v/wxt?labelColor=black&color=%234fa048)](https://www.npmjs.com/package/wxt)
[![downloads](https://img.shields.io/npm/dm/wxt?labelColor=black&color=%234fa048)](https://www.npmjs.com/package/wxt)
[![license | MIT](https://img.shields.io/npm/l/wxt?labelColor=black&color=%234fa048)](https://github.com/wxt-dev/wxt/blob/main/LICENSE)
[![coverage](https://img.shields.io/codecov/c/github/wxt-dev/wxt?labelColor=black&color=%234fa048)](https://codecov.io/github/wxt-dev/wxt)
<p align="center">
<a href="https://wxt.dev/guide/installation.html" target="_blank">Get Started</a>
&bull;
<a href="https://wxt.dev/api/config.html" target="_blank">Configuration</a>
&bull;
<a href="https://wxt.dev/examples.html" target="_blank">Examples</a>
&bull;
<a href="https://github.com/wxt-dev/wxt/blob/main/packages/wxt/CHANGELOG.md" target="_blank">Changelog</a>
&bull;
<a href="https://discord.gg/ZFsZqGery9" target="_blank">Discord</a>
</p>
Next-gen framework for developing web extensions.<br/>⚡<br/><q><i>It's like Nuxt, but for Web Extensions</i></q>
[Get Started](https://wxt.dev/guide/installation.html) •
[Configuration](https://wxt.dev/api/config.html) •
[Examples](https://wxt.dev/examples.html) •
[Changelog](https://github.com/wxt-dev/wxt/blob/main/packages/wxt/CHANGELOG.md) •
[Discord](https://discord.gg/ZFsZqGery9)
</div>
![Example CLI Output](https://raw.githubusercontent.com/wxt-dev/wxt/HEAD/docs/assets/cli-output.png)
## Demo
https://github.com/wxt-dev/wxt/assets/10101283/4d678939-1bdb-495c-9c36-3aa281d84c94
<https://github.com/wxt-dev/wxt/assets/10101283/4d678939-1bdb-495c-9c36-3aa281d84c94>
## Quick Start
Bootstrap a new project:
<!-- automd:pm-x version="latest" name="wxt" args="init" -->
```sh
# npm
npx wxt@latest init
@@ -56,8 +38,6 @@ pnpm dlx wxt@latest init
bunx wxt@latest init
```
<!-- /automd -->
Or see the [installation guide](https://wxt.dev/guide/installation.html) to get started with WXT.
## Features
@@ -75,15 +55,15 @@ Or see the [installation guide](https://wxt.dev/guide/installation.html) to get
- 📏 Bundle analysis
- ⬇️ Download and bundle remote URL imports
## Contributors
## Sponsors
<!-- automd:contributors author="aklinker1" license="MIT" github="wxt-dev/wxt" -->
WXT is a [MIT-licensed](https://github.com/wxt-dev/wxt/blob/main/LICENSE) open source project with its ongoing development made possible entirely by the support of these awesome backers. If you'd like to join them, please consider [sponsoring WXT's development](https://github.com/sponsors/wxt-dev).
[![WXT Sponsors](https://raw.githubusercontent.com/wxt-dev/static/refs/heads/main/sponsorkit/sponsors.svg)](https://github.com/sponsors/wxt-dev)
## Contributors
Published under the [MIT](https://github.com/wxt-dev/wxt/blob/main/LICENSE) license.
Made by [@aklinker1](https://github.com/aklinker1) and [community](https://github.com/wxt-dev/wxt/graphs/contributors) 💛
<br><br>
<a href="https://github.com/wxt-dev/wxt/graphs/contributors">
<img src="https://contrib.rocks/image?repo=wxt-dev/wxt" />
</a>
<!-- /automd -->
[![WXT contributors](https://contrib.rocks/image?repo=wxt-dev/wxt)](https://github.com/wxt-dev/wxt/graphs/contributors)
+11
View File
@@ -0,0 +1,11 @@
# Security Policy
While WXT is in prerelease, only the latest version will receive security updates. The latest version is:
<img alt="npm version" src="https://img.shields.io/npm/v/wxt?labelColor=black&color=%234fa048">
## Reporting a Vulnerability
If you discover a security vulnerability, please email me at <aaronklinker1@gmail.com>. I will respond within a few days to acknowledge receipt of your report.
If the vulnerability is accepted, I will open a public issue to track the fix. If the vulnerability is not accepted, no further action will be taken.
Generated
+3033
View File
File diff suppressed because it is too large Load Diff
+118
View File
@@ -0,0 +1,118 @@
version: '0.2'
ignorePaths:
- pnpm-lock.yaml
- '**/node_modules/**'
- '**/dist/**'
- '**/coverage/**'
- docs/api/**
- '**/CHANGELOG.md'
- docs/public/_redirects
- packages/browser/src/gen/**
- patches/**
- '**/*.snap'
- docs/assets/extension-showcase.yml
words:
- Aabid
- aabidk
- aklinker
- automount
- avenir
- bidi
- buildc
- bunx
- cachable
- charmbracelet
- chromedriver
- Cira
- comctx
- confbox
- configfile
- consolas
- Cpath
- crbug
- crunchyroll
- cssinjs
- CSUI
- Csvg
- defu
- deinit
- dequal
- dtrace
- duckduckgo
- esbuild
- esque
- extglob
- favicons
- fieldtrials
- firefoxdeveloperedition
- flamechart
- Florian
- focusring
- frontmatter
- giget
- grayscale
- greyscale
- gtag
- hckhakegfgenefhikdcfkaaonnclljmf
- hookable
- iconify
- jsons
- Kenobi
- keystyle
- klinker
- linkedom
- llms
- locationchange
- magicast
- Menlo
- menupanel
- metas
- mktemp
- mycompany
- nacl
- nanospinner
- natsu
- newtab
- njsproj
- nodebuffer
- Noto
- ntvs
- nypm
- ohash
- oklab
- oxlint
- pbbf
- personaltoolbar
- portaling
- prebundled
- prefs
- proxified
- pWXLO
- repost
- rxliuli
- sandboxed
- scule
- Segoe
- sidepanel
- sidepanels
- solidjs
- styl
- subdependency
- tabstrip
- teleporting
- treemap
- triaging
- umami
- ungh
- unimport
- unocss
- unrun
- unstub
- unwatch
- USSS
- vitepress
- webext
- webextension
- webextrc
- xcrun
- xlink
+70
View File
@@ -0,0 +1,70 @@
<script lang="ts" setup>
import { computed } from 'vue';
// @ts-expect-error: Vitepress data-loader magic, this import is correct
import { data } from '../loaders/blog.data';
import BlogPostPreview from './BlogPostPreview.vue';
const posts = computed(() =>
data
.map((post) => ({
...post,
...post.frontmatter,
date: new Date(post.frontmatter.date),
}))
.sort((a, b) => b.date.getTime() - a.date.getTime()),
);
</script>
<template>
<div class="container">
<div>
<div class="vp-doc">
<h1>Blog</h1>
</div>
<ul>
<BlogPostPreview v-for="post of posts" :key="post.url" :post />
</ul>
</div>
</div>
</template>
<style scoped>
.container {
display: flex;
flex-direction: column;
align-items: center;
}
.container > div {
padding: 32px;
max-width: 900px;
width: 100%;
min-width: 0;
}
h1 {
padding-bottom: 16px;
}
ul {
display: flex;
flex-direction: column;
list-style: none;
}
ul,
li {
padding: 0;
margin: 0;
}
ul li {
padding-top: 16px;
margin-top: 16px;
border-top: 1px solid var(--vp-c-default);
}
ul li:last-child {
padding-bottom: 16px;
margin-bottom: 16px;
border-bottom: 1px solid var(--vp-c-default);
}
</style>
+76
View File
@@ -0,0 +1,76 @@
<script lang="ts" setup>
import useBlogDate from '../composables/useBlogDate';
import { useData } from 'vitepress';
const { frontmatter } = useData();
const date = useBlogDate(() => frontmatter.value.date);
</script>
<template>
<div class="vp-doc">
<main class="container-content">
<h1 v-html="$frontmatter.title" />
<p class="meta-row">
<a
class="author"
v-for="author of $frontmatter.authors"
:key="author.github"
:href="`https://github.com/${author.github}`"
>
<img :src="`https://github.com/${author.github}.png?size=96`" />
<span>{{ author.name }}</span>
</a>
<span>&bull;</span>
<span>{{ date }}</span>
</p>
<Content />
</main>
</div>
</template>
<style scoped>
vp-doc {
display: flex;
}
main {
max-width: 1080px;
padding: 32px;
margin: auto;
}
@media (min-width: 768px) {
main {
padding: 64px;
}
}
.meta-row {
display: flex;
color: var(--vp-c-text-2);
gap: 16px;
overflow: hidden;
padding-bottom: 32px;
}
.meta-row > * {
flex-shrink: 0;
}
.author {
display: flex;
gap: 8px;
align-items: center;
color: var(--vp-c-text-2);
font-weight: normal;
text-decoration: none;
}
.author img {
width: 24px;
height: 24px;
border-radius: 100%;
}
.author span {
padding: 0;
margin: 0;
}
.author:hover {
text-decoration: underline;
color: var(--vp-c-text-2);
}
</style>
@@ -0,0 +1,72 @@
<script lang="ts" setup>
import useBlogDate from '../composables/useBlogDate';
const props = defineProps<{
post: {
title: string;
description?: string;
date: Date;
url: string;
authors: Array<{ name: string; github: string }>;
};
}>();
const date = useBlogDate(() => props.post.date);
</script>
<template>
<li class="blog-list-item">
<a :href="post.url">
<div class="vp-doc">
<h3 class="title" v-html="post.title" />
<p class="description" v-html="post.description" />
<p class="meta">
{{ post.authors.map((author) => author.name).join(', ') }}
&bull;
{{ date }}
</p>
</div>
</a>
</li>
</template>
<style scoped>
li {
padding: 0;
margin: 0;
}
p {
margin: 0;
}
h3 {
margin: 0;
padding: 0;
border: none;
}
li > a > div {
display: flex;
flex-direction: column;
margin: 0 -16px;
padding: 16px;
border-radius: 16px;
}
li > a > div:hover {
background: var(--vp-c-default);
}
li .title {
color: var(--vp-c-text);
margin-bottom: 12px;
}
li .description {
font-size: 16px;
color: var(--vp-c-text-2);
margin-bottom: 8px;
}
li .meta {
font-weight: 400;
font-size: 12px;
color: var(--vp-c-text-2);
}
</style>
+182 -112
View File
@@ -1,101 +1,120 @@
<script lang="ts" setup>
import { computed } from 'vue';
import useListExtensionDetails, {
ChromeExtension,
} from '../composables/useListExtensionDetails';
import useListExtensionDetails from '../composables/useListExtensionDetails';
import _extensionEntries from '../../assets/extension-showcase.yml';
// Add extension IDs here. Order doesn't matter, will be sorted by weekly active users
// During the transition from chrome.google.com/webstore to
// chromewebstore.google.com, queue.wxt.dev might return null for your
// extension. If it does, use "<slug>/<id>" instead of just the ID. The slug
// can be retrieved from the URL of the item on chromewebstore.google.com
const chromeExtensionIds = [
'ocfdgncpifmegplaglcnglhioflaimkd', // GitHub: Better Line Counts
'mgmdkjcljneegjfajchedjpdhbadklcf', // Anime Skip Player
'bfbnagnphiehemkdgmmficmjfddgfhpl', // UltraWideo
'elfaihghhjjoknimpccccmkioofjjfkf', // StayFree - Website Blocker & Web Analytics
'okifoaikfmpfcamplcfjkpdnhfodpkil', // Doozy: Ai Made Easy
'lknmjhcajhfbbglglccadlfdjbaiifig', // tl;dv - Record, Transcribe & ChatGPT for Google Meet
'youtube中文配音/oglffgiaiekgeicdgkdlnlkhliajdlja', // Youtube中文配音
'agjnjboanicjcpenljmaaigopkgdnihi', // PreMiD
'aiakblgmlabokilgljkglggnpflljdgp', // Markdown Sticky Notes
'nomnkbngkijpffepcgbbofhcnafpkiep', // DocVersionRedirector
'ceicccfeikoipigeghddpocceifjelph', // Plex Skipper
'aelkipgppclpfimeamgmlonimflbhlgf', // GitHub Custom Notifier
'djnlaiohfaaifbibleebjggkghlmcpcj', // Fluent Read
'nhclljcpfmmaiojbhhnkpjcfmacfcian', // Facebook Video Controls
'mblkhbaakhbhiimkbcnmeciblfhmafna', // ElemSnap - Quick capture of webpage elements and conversion to images,
'oajalfneblkfiejoadecnmodfpnaeblh', // MS Edge TTS (Text to Speech)
'nedcanggplmbbgmlpcjiafgjcpdimpea', // YTBlock - Block any content from YouTube™
'oadbjpccljkplmhnjekgjamejnbadlne', // demo.fun - Interactive product demos that convert
'iopdafdcollfgaoffingmahpffckmjni', // SmartEReply: Elevate Your LinkedIn™ Engagement with AI 🚀📈
'khjdmjcmpolknpccmaaipmidphjokhdf', // WorkFlowy MultiFlow
'fencadnndhdeggodopebjgdfdlhcimfk', // 香草布丁🌿🍮- https://github.com/Xdy1579883916/vanilla-pudding
'bnacincmbaknlbegecpioobkfgejlojp', // MaxFocus: Link Preview
'bcpgdpedphodjcjlminjbdeejccjbimp', // 汇率转换-中文版本
'loeilaonggnalkaiiaepbegccilkmjjp', // Currency Converter Plus
'npcnninnjghigjfiecefheeibomjpkak', // Respond Easy
'cfkdcideecefncbglkhneoflfnmhoicc', // mindful - stay focused on your goals
'lnhejcpclabmbgpiiomjbhalblnnbffg', // 1Proompt
'fonflmjnjbkigocpoommgmhljdpljain', // NiceTab - https://github.com/web-dahuyou/NiceTab
'fcffekbnfcfdemeekijbbmgmkognnmkd', // Draftly for LinkedIn
'nkndldfehcidpejfkokbeghpnlbppdmo', // YouTube Summarized - Summarize any YouTube video
'dbichmdlbjdeplpkhcejgkakobjbjalc', // 社媒助手 - https://github.com/iszhouhua/social-media-copilot
'opepfpjeogkbgeigkbepobceinnfmjdd', // Dofollow Links for SEO
'pdnenlnelpdomajfejgapbdpmjkfpjkp', // ChatGPT Writer: Use AI on Any Site (GPT-4o, Claude, Gemini, and More)
'jobnhifpphkgoelnhnopgkdhbdkiadmj', // discord message translator
'ncokhechhpjgjonhjnlaneglmdkfkcbj', // Habit Tracker app widget for daily habit tracking
'lnjaiaapbakfhlbjenjkhffcdpoompki', // Catppuccin for GitHub File Explorer Icons
'cpaedhbidlpnbdfegakhiamfpndhjpgf', // WebChat: Chat with anyone on any website
'fcphghnknhkimeagdglkljinmpbagone', // YouTube Auto HD + FPS
'lpomjgbicdemjkgmbnkjncgdebogkhlb', // MultiViewer Companion
'ggiafipgeeaaahnjamgpjcgkdpanhddg', // Sync Watch - Watch videos together on any site
interface StoreLink {
label: string;
url: string;
}
interface ListedExtension {
id: string;
name: string;
iconUrl: string;
shortDescription: string;
users: number;
rating: number | undefined;
stores: StoreLink[];
}
const extensionEntries = _extensionEntries as Array<{
chromeId?: string;
firefoxSlug?: string;
}>;
const chromeIds = extensionEntries.flatMap((e) =>
e.chromeId ? [e.chromeId] : [],
);
const firefoxSlugs = [
...new Set(
extensionEntries.flatMap((e) => (e.firefoxSlug ? [e.firefoxSlug] : [])),
),
];
const { data, err, isLoading } = useListExtensionDetails(chromeExtensionIds);
const sortedExtensions = computed(() => {
if (!data.value?.length) return [];
const { data, isLoading } = useListExtensionDetails(chromeIds, firefoxSlugs);
return [...data.value]
.filter((item) => item != null)
.map((item) => ({
...item,
// Sort based on the user count weighted by the rating
sortKey: ((item.rating ?? 5) / 5) * item.weeklyActiveUsers,
}))
.filter((item) => !!item)
.sort((l, r) => r.sortKey - l.sortKey);
});
function getStoreUrl(extension: ChromeExtension) {
const url = new URL(extension.storeUrl);
function addUtmSource(storeUrl: string): string {
const url = new URL(storeUrl);
url.searchParams.set('utm_source', 'wxt.dev');
return url.href;
}
const sortedExtensions = computed((): ListedExtension[] => {
if (!data.value) return [];
const chromeById = new Map(
(data.value.chrome ?? []).filter(Boolean).map((e) => [e.id, e]),
);
const firefoxBySlug = new Map(
(data.value.firefox ?? []).filter(Boolean).map((e) => [e.id, e]),
);
const results: ListedExtension[] = [];
for (const entry of extensionEntries) {
const chrome = entry.chromeId ? chromeById.get(entry.chromeId) : undefined;
const firefox = entry.firefoxSlug
? firefoxBySlug.get(entry.firefoxSlug)
: undefined;
if (!chrome && !firefox) continue;
const primary = chrome ?? firefox!;
const users = (chrome?.users ?? 0) + (firefox?.users ?? 0);
const rating = chrome?.rating ?? firefox?.rating;
const stores: StoreLink[] = [];
if (chrome) {
stores.push({ label: 'Chrome', url: addUtmSource(chrome.storeUrl) });
}
if (firefox) {
stores.push({ label: 'Firefox', url: addUtmSource(firefox.storeUrl) });
}
results.push({
id: entry.chromeId ?? `firefox:${entry.firefoxSlug}`,
name: primary.name,
iconUrl: primary.iconUrl,
shortDescription: primary.shortDescription,
users,
rating,
stores,
});
}
const score = (e: ListedExtension) => ((e.rating ?? 5) / 5) * e.users;
return results.sort((a, b) => score(b) - score(a));
});
function formatUsers(n: number): string {
return `${n.toLocaleString()} users`;
}
function formatStars(r: number): string {
const rounded = Math.round(r * 10) / 10;
return `${rounded % 1 === 0 ? rounded.toFixed(0) : rounded.toFixed(1)} stars`;
}
</script>
<template>
<p v-if="isLoading" style="text-align: center; opacity: 50%">Loading...</p>
<p
v-else-if="err || sortedExtensions.length === 0"
v-else-if="sortedExtensions.length === 0"
style="text-align: center; opacity: 50%"
>
Failed to load extension details.
</p>
<ul v-else>
<li
v-for="extension of sortedExtensions"
:key="extension.id"
class="relative"
>
<ul v-else class="extension-grid">
<li v-for="extension of sortedExtensions" :key="extension.id">
<img
:src="extension.iconUrl"
:alt="`${extension.name} icon`"
referrerpolicy="no-referrer"
/>
<div class="relative">
<div class="card-content">
<a
:href="getStoreUrl(extension)"
:href="extension.stores[0]?.url ?? '#'"
target="_blank"
:title="extension.name"
class="extension-name"
@@ -104,19 +123,40 @@ function getStoreUrl(extension: ChromeExtension) {
<p class="description" :title="extension.shortDescription">
{{ extension.shortDescription }}
</p>
<div v-if="extension.stores.length > 0" class="store-stats">
<span class="store-stats-info">
<span>{{ formatUsers(extension.users) }}</span>
<template v-if="extension.rating">
<span class="store-stats-sep" aria-hidden="true">,</span>
<span>{{ formatStars(extension.rating) }}</span>
</template>
</span>
<span class="store-stats-sep" aria-hidden="true">&middot;</span>
<span class="store-links">
<a
v-for="(store, i) of extension.stores"
:key="store.label"
:href="store.url"
target="_blank"
class="store-link"
:title="store.label"
>
{{ store.label
}}<span
v-if="i < extension.stores.length - 1"
class="store-stats-sep"
aria-hidden="true"
>,&nbsp;</span
>
</a>
</span>
</div>
</div>
<p class="user-count">
<span>{{ extension.weeklyActiveUsers.toLocaleString() }} users</span
><template v-if="extension.rating != null"
>,
<span>{{ extension.rating }} stars</span>
</template>
</p>
</li>
</ul>
<p class="centered pr">
<a
href="https://github.com/wxt-dev/wxt/edit/main/docs/.vitepress/components/UsingWxtSection.vue"
href="https://github.com/wxt-dev/wxt/edit/main/docs/assets/extension-showcase.yml"
target="_blank"
>Open a PR</a
>
@@ -125,7 +165,7 @@ function getStoreUrl(extension: ChromeExtension) {
</template>
<style scoped>
li img {
.extension-grid > li > img {
width: 116px;
height: 116px;
padding: 16px;
@@ -133,7 +173,7 @@ li img {
background-color: var(--vp-c-default-soft);
}
ul {
.extension-grid {
display: grid;
grid-template-columns: repeat(1, 1fr);
align-items: stretch;
@@ -143,12 +183,12 @@ ul {
padding: 0;
}
@media (min-width: 960px) {
ul {
.extension-grid {
grid-template-columns: repeat(2, 1fr);
}
}
li {
.extension-grid > li {
margin: 0 !important;
padding: 16px;
display: flex;
@@ -156,28 +196,68 @@ li {
border-radius: 12px;
flex: 1;
gap: 24px;
align-items: center;
align-items: stretch;
}
.centered {
text-align: center;
}
li a,
li .user-count,
li .description {
.extension-grid > li .description {
padding: 0;
margin: 0;
}
li .user-count {
opacity: 70%;
font-size: small;
position: absolute;
bottom: 12px;
right: 16px;
.extension-grid > li .card-content {
flex: 1;
min-width: 0;
display: flex;
flex-direction: column;
gap: 6px;
padding-right: 0;
}
li a {
.store-stats {
margin-top: auto;
padding-top: 6px;
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
align-items: baseline;
column-gap: 6px;
row-gap: 4px;
text-align: right;
font-size: 12px;
line-height: 1.45;
opacity: 0.72;
color: var(--vp-c-text-2);
}
.store-stats-info {
display: inline;
}
.store-stats-sep {
opacity: 0.45;
user-select: none;
}
.store-links {
display: inline;
}
.store-link {
text-decoration: none;
color: inherit;
cursor: pointer;
}
.store-link:hover {
color: var(--vp-c-text-1);
text-decoration: underline;
}
.extension-grid > li .extension-name {
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
@@ -186,33 +266,23 @@ li a {
padding: 0;
margin: 0;
text-decoration: none;
font-size: large;
}
li a:hover {
.extension-grid > li .extension-name:hover {
text-decoration: underline;
}
li div {
flex: 1;
}
li .description {
.extension-grid > li .description {
opacity: 90%;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
margin-bottom: 16px;
}
li .extension-name {
font-size: large;
margin-bottom: 0 !important;
}
.pr {
opacity: 70%;
}
.relative {
position: relative;
}
</style>
@@ -0,0 +1,15 @@
import { computed, toValue, MaybeRefOrGetter } from 'vue';
const MONTH_FORMATTER = new Intl.DateTimeFormat(
globalThis?.navigator?.language,
{
month: 'long',
},
);
export default function (date: MaybeRefOrGetter<Date | string>) {
return computed(() => {
const d = new Date(toValue(date));
return `${MONTH_FORMATTER.format(d)} ${d.getDate()}, ${d.getFullYear()}`;
});
}
@@ -1,47 +1,70 @@
import { ref } from 'vue';
export interface ChromeExtension {
export interface Extension {
id: string;
name: string;
iconUrl: string;
weeklyActiveUsers: number;
shortDescription: string;
storeUrl: string;
rating: number | undefined;
users: number;
}
export interface ExtensionResults {
chrome: Extension[];
firefox: Extension[];
}
const operationName = 'WxtDocsUsedBy';
const query = `query ${operationName}($ids:[String!]!) {
chromeExtensions(ids: $ids) {
const query = `query ${operationName}($chromeIds: [String!]!, $firefoxIds: [String!]!) {
chromeExtensions(ids: $chromeIds) {
id
name
iconUrl
weeklyActiveUsers
shortDescription
storeUrl
rating
...ExtensionData
}
firefoxAddons(ids: $firefoxIds) {
id: slug
...ExtensionData
}
}
fragment ExtensionData on Extension {
name
iconUrl
shortDescription
storeUrl
rating
users
}`;
export default function (ids: string[]) {
const data = ref<ChromeExtension[]>();
export default function (chromeIds: string[], firefoxSlugs: string[]) {
const data = ref<ExtensionResults>();
const err = ref<unknown>();
const isLoading = ref(true);
if (chromeIds.length === 0 && firefoxSlugs.length === 0) {
data.value = { chrome: [], firefox: [] };
isLoading.value = false;
return { data, err, isLoading };
}
fetch('https://queue.wxt.dev/api', {
method: 'POST',
body: JSON.stringify({
operationName,
query,
variables: { ids },
variables: { chromeIds, firefoxIds: firefoxSlugs },
}),
headers: {
'Content-Type': 'application/json',
},
})
.then(async (res) => {
isLoading.value = false;
const {
data: { chromeExtensions },
} = await res.json();
data.value = chromeExtensions;
const { data: responseData } = await res.json();
data.value = {
chrome: responseData.chromeExtensions ?? [],
firefox: responseData.firefoxAddons ?? [],
};
err.value = undefined;
})
.catch((error) => {
@@ -51,9 +74,5 @@ export default function (ids: string[]) {
err.value = error;
});
return {
data,
err,
isLoading,
};
return { data, err, isLoading };
}
+132 -16
View File
@@ -1,5 +1,25 @@
import { defineConfig } from 'vitepress';
import { Feed } from 'feed';
import footnote from 'markdown-it-footnote';
import fs, { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { DefaultTheme, defineConfig } from 'vitepress';
import addKnowledge from 'vitepress-knowledge';
import {
groupIconMdPlugin,
groupIconVitePlugin,
localIconLoader,
} from 'vitepress-plugin-group-icons';
import llmstxt from 'vitepress-plugin-llms';
import { version as analyticsVersion } from '../../packages/analytics/package.json';
import { version as autoIconsVersion } from '../../packages/auto-icons/package.json';
import { version as i18nVersion } from '../../packages/i18n/package.json';
import { version as runnerVersion } from '../../packages/runner/package.json';
import { version as storageVersion } from '../../packages/storage/package.json';
import { version as unocssVersion } from '../../packages/unocss/package.json';
import { version as wxtVersion } from '../../packages/wxt/package.json';
import { version as isBackgroundVersion } from '../../packages/is-background/package.json';
import typedocSidebar from '../api/reference/typedoc-sidebar.json';
import { meta, script } from './utils/head';
import {
menuGroup,
menuItem,
@@ -7,31 +27,104 @@ import {
navItem,
prepareTypedocSidebar,
} from './utils/menus';
import { meta, script } from './utils/head';
import { version as wxtVersion } from '../../packages/wxt/package.json';
import { version as i18nVersion } from '../../packages/i18n/package.json';
import { version as autoIconsVersion } from '../../packages/auto-icons/package.json';
import { version as unocssVersion } from '../../packages/unocss/package.json';
const origin = 'https://wxt.dev';
const title = 'Next-gen Web Extension Framework';
const titleSuffix = ' WXT';
const description =
"WXT provides the best developer experience, making it quick, easy, and fun to develop chrome extensions for all browsers. With built-in utilities for building, zipping, and publishing your extension, it's easy to get started.";
"WXT provides the best developer experience, making it quick, easy, and fun to develop web extensions. With built-in utilities for building, zipping, and publishing your extension, it's easy to get started.";
const ogTitle = `${title}${titleSuffix}`;
const ogUrl = 'https://wxt.dev';
const ogImage = 'https://wxt.dev/social-preview.png';
const ogUrl = origin;
const ogImage = `${origin}/social-preview.png`;
const otherPackages = {
analytics: analyticsVersion,
'auto-icons': autoIconsVersion,
i18n: i18nVersion,
storage: storageVersion,
unocss: unocssVersion,
runner: runnerVersion,
'is-background': isBackgroundVersion,
};
const knowledge = addKnowledge<DefaultTheme.Config>({
serverUrl: 'https://knowledge.wxt.dev',
paths: {
'/': 'docs',
'/api/': 'api-reference',
'/blog/': 'blog',
},
layoutSelectors: {
blog: '.container-content',
},
pageSelectors: {
'examples.md': '#VPContent > .VPPage',
'blog.md': '#VPContent > .VPPage',
},
});
// https://vitepress.dev/reference/site-config
export default defineConfig({
extends: knowledge,
titleTemplate: `:title${titleSuffix}`,
title: 'WXT',
description,
vite: {
clearScreen: false,
plugins: [
llmstxt(),
groupIconVitePlugin({
customIcon: {
'wxt.config.ts': localIconLoader(
import.meta.url,
'../public/logo.svg',
),
},
}),
{
name: 'yaml-loader',
load: {
handler: async (id) => {
if (id.endsWith('.yml') || id.endsWith('.yaml')) {
const obj = Bun.YAML.parse(await readFile(id, 'utf8'));
return `export default ${JSON.stringify(obj)}`;
}
},
},
},
],
},
lastUpdated: true,
sitemap: {
hostname: 'https://wxt.dev',
hostname: origin,
},
async buildEnd(site) {
// @ts-expect-error: knowledge.buildEnd is not typed, but it exists.
await knowledge.buildEnd(site);
// Only construct the RSS document for production builds
const { default: blogDataLoader } = await import('./loaders/blog.data');
const posts = await blogDataLoader.load();
const feed = new Feed({
copyright: 'MIT',
id: 'wxt',
title: 'WXT Blog',
link: `${origin}/blog`,
});
posts.forEach((post) => {
feed.addItem({
date: post.frontmatter.date,
link: new URL(post.url, origin).href,
title: post.frontmatter.title,
description: post.frontmatter.description,
});
});
// console.log('rss.xml:');
// console.log(feed.rss2());
await fs.writeFile(join(site.outDir, 'rss.xml'), feed.rss2());
},
head: [
@@ -47,6 +140,16 @@ export default defineConfig({
}),
],
markdown: {
config: (md) => {
md.use(footnote);
md.use(groupIconMdPlugin);
},
languageAlias: {
mjs: 'js',
},
},
themeConfig: {
// https://vitepress.dev/reference/default-theme-config
logo: {
@@ -54,6 +157,16 @@ export default defineConfig({
alt: 'WXT logo',
},
footer: {
message: [
'<a class="light-netlify" href="https://www.netlify.com"> <img src="https://www.netlify.com/v3/img/components/netlify-color-bg.svg" alt="Deploys by Netlify" style="display: inline;" /></a>',
'<a class="dark-netlify" href="https://www.netlify.com"> <img src="https://www.netlify.com/v3/img/components/netlify-color-accent.svg" alt="Deploys by Netlify" style="display: inline;" /></a>',
'Released under the <a href="https://github.com/wxt-dev/wxt/blob/main/LICENSE">MIT License</a>.',
].join('<br/>'),
copyright:
'Copyright © 2023-present <a href="https://github.com/aklinker1">Aaron Klinker</a>',
},
editLink: {
pattern: 'https://github.com/wxt-dev/wxt/edit/main/docs/:path',
},
@@ -71,6 +184,7 @@ export default defineConfig({
navItem('Guide', '/guide/installation'),
navItem('Examples', '/examples'),
navItem('API', '/api/reference/wxt'),
navItem('Blog', '/blog'),
navItem(`v${wxtVersion}`, [
navItem('wxt', [
navItem(`v${wxtVersion}`, '/'),
@@ -79,12 +193,12 @@ export default defineConfig({
'https://github.com/wxt-dev/wxt/blob/main/packages/wxt/CHANGELOG.md',
),
]),
navItem('Other Packages', [
navItem(`wxt/storage — ${wxtVersion}`, '/storage'),
navItem(`@wxt-dev/auto-icons — ${autoIconsVersion}`, '/auto-icons'),
navItem(`@wxt-dev/i18n${i18nVersion}`, '/i18n'),
navItem(`@wxt-dev/unocss — ${unocssVersion}`, '/unocss'),
]),
navItem(
'Other Packages',
Object.entries(otherPackages).map(([name, version]) =>
navItem(`@wxt-dev/${name}${version}`, `/${name}`),
),
),
]),
],
@@ -121,6 +235,7 @@ export default defineConfig({
menuItem('Storage', 'storage.md'),
menuItem('Messaging', 'messaging.md'),
menuItem('I18n', 'i18n.md'),
menuItem('Favicons', 'favicons.md'),
menuItem('Scripting', 'scripting.md'),
menuItem('WXT Modules', 'wxt-modules.md'),
menuItem('Frontend Frameworks', 'frontend-frameworks.md'),
@@ -134,6 +249,7 @@ export default defineConfig({
menuGroup('Resources', '/guide/resources/', [
menuItem('Compare', 'compare.md'),
menuItem('FAQ', 'faq.md'),
menuItem('Community', 'community.md'),
menuItem('Upgrading WXT', 'upgrading.md'),
menuItem('Migrate to WXT', 'migrate.md'),
menuItem('How WXT Works', 'how-wxt-works.md'),
+3
View File
@@ -0,0 +1,3 @@
import { createContentLoader } from 'vitepress';
export default createContentLoader('blog/*.md');
+8 -6
View File
@@ -1,6 +1,7 @@
import { resolve } from 'node:path';
import consola from 'consola';
import spawn from 'nano-spawn';
import { resolve } from 'node:path';
import { version } from '../../../packages/wxt/package.json';
const cliDir = resolve('packages/wxt/src/cli/commands');
const cliDirGlob = resolve(cliDir, '**');
@@ -38,19 +39,20 @@ export default {
async function getHelp(command: string): Promise<string> {
const args = command.split(' ');
const res = await spawn(args[0], [...args.slice(1), '--help'], {
const result = await spawn(args[0], [...args.slice(1), '--help'], {
cwd: 'packages/wxt',
});
return res.stdout;
return result.stdout;
}
function getWxtHelp(command: string): Promise<string> {
return getHelp(`pnpm -s wxt ${command}`.trim());
async function getWxtHelp(command: string): Promise<string> {
const res = await getHelp(`bun run --silent wxt ${command}`.trim());
return res.replaceAll('{{version}}', version);
}
async function getPublishExtensionHelp(command: string): Promise<string> {
const res = await getHelp(
`./node_modules/.bin/publish-extension ${command}`.trim(),
`bun run --silent publish-extension ${command}`.trim(),
);
return res.replace(/\$ publish-extension/g, '$ wxt submit');
}
+51 -56
View File
@@ -1,72 +1,28 @@
/* Colors */
:root {
--wxt-c-green: #53bc4a;
--wxt-c-green-1: #0b8a00;
--wxt-c-green-2: #096600;
--wxt-c-green-3: #096600;
--wxt-c-green-soft: rgba(11, 138, 0, 0.14);
}
.dark {
--wxt-c-green-1: #67d45e;
--wxt-c-green-2: #4fa048;
--wxt-c-green-3: #447e3f;
--wxt-c-green-2: #329929;
--wxt-c-green-3: #21651b;
--wxt-c-green-soft: rgba(103, 212, 94, 0.14);
}
/* https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css */
:root {
--vp-c-brand: var(--wxt-c-green);
--vp-c-brand-1: var(--wxt-c-green-1);
--vp-c-brand-2: var(--wxt-c-green-2);
--vp-c-brand-3: var(--wxt-c-green-3);
--vp-button-brand-bg: var(--wxt-c-green);
--vp-button-brand-hover-bg: var(--wxt-c-green-2);
--vp-button-brand-active-bg: var(--wxt-c-green-3);
--vp-code-link-color: var(--wxt-c-green);
/* --vp-c-text-1: var(--wxt-c-green-1); */
--vp-button-brand-text: var(--vp-c-black);
--vp-button-brand-hover-text: var(--vp-c-black);
--vp-button-brand-active-text: var(--vp-c-black);
--vp-custom-block-tip-border: var(--wxt-c-green);
--vp-custom-block-tip-text: var(--wxt-c-green);
/* --vp-code-block-bg: #222422;
--vp-code-copy-code-bg: #313431;
--vp-code-copy-code-hover-bg: #3c403c; */
--vp-custom-block-tip-bg: var(--vp-code-block-bg);
--vp-custom-block-info-bg: var(--vp-code-block-bg);
--vp-code-color: #476582;
--vp-c-brand-soft: var(--wxt-c-green-soft);
}
.vp-doc a {
color: var(--wxt-c-green);
}
.dark {
--vp-c-bg: #131413;
--vp-c-bg-soft: #1a1b1a;
--vp-c-bg-soft-up: #1f201f;
--vp-c-bg-soft-down: #262926;
--vp-c-bg-soft-mute: #242424;
--vp-c-bg-alt: #171817;
--vp-c-default: #313136;
--vp-c-default-1: #3a3a3c;
--vp-c-default-2: #505053;
--vp-c-default-3: #2c2c30;
--vp-c-default-soft: #252529;
--vp-code-block-bg: #191a19;
--vp-code-copy-code-bg: #212321;
--vp-code-copy-code-hover-bg: #292d29;
--vp-custom-block-info-bg: #191a19;
--vp-code-color: #c9def1;
}
/* Customize Individual Components */
.vp-doc .no-vertical-dividers th,
.vp-doc .no-vertical-dividers td {
@@ -97,3 +53,42 @@ body {
vertical-align: middle;
background-color: var(--vp-c-default-2);
}
.light-netlify {
display: inline;
}
.dark .light-netlify {
display: none;
}
.dark-netlify {
display: none;
}
.dark .dark-netlify {
display: inline;
}
/* Add Aaron's favorite pic from Artemis II to the hero section because it's cool. */
.dark .VPHome::before {
content: '';
background-image: url('/assets/art002e009298.jpg');
opacity: 50%;
position: absolute;
width: 100vw;
height: 110vh;
background-size: cover;
background-position: 90%;
pointer-events: none;
}
.dark .VPHome::after {
content: '';
position: absolute;
width: 100vw;
height: 10vh;
top: 100vh;
background: linear-gradient(to bottom, transparent, var(--vp-c-bg));
pointer-events: none;
z-index: 0;
}
.item {
z-index: 1;
}
+8 -4
View File
@@ -3,14 +3,18 @@ import Icon from '../components/Icon.vue';
import EntrypointPatterns from '../components/EntrypointPatterns.vue';
import UsingWxtSection from '../components/UsingWxtSection.vue';
import ExampleSearch from '../components/ExampleSearch.vue';
import BlogLayout from '../components/BlogLayout.vue';
import './custom.css';
import 'virtual:group-icons.css';
export default {
extends: DefaultTheme,
enhanceApp(ctx) {
ctx.app.component('Icon', Icon);
ctx.app.component('EntrypointPatterns', EntrypointPatterns);
ctx.app.component('UsingWxtSection', UsingWxtSection);
ctx.app.component('ExampleSearch', ExampleSearch);
ctx.app
.component('Icon', Icon)
.component('EntrypointPatterns', EntrypointPatterns)
.component('UsingWxtSection', UsingWxtSection)
.component('ExampleSearch', ExampleSearch)
.component('blog', BlogLayout);
},
};
+3 -5
View File
@@ -28,13 +28,13 @@ export function menuRoot(items: SidebarItem[]) {
export function menuGroup(
text: string,
items: SidebarItem[],
collapsable?: boolean,
collapsible?: boolean,
): SidebarItem;
export function menuGroup(
text: string,
base: string,
items: SidebarItem[],
collapsable?: boolean,
collapsible?: boolean,
): SidebarItem;
export function menuGroup(
text: string,
@@ -77,9 +77,7 @@ export function menuItem(
return { text, link };
}
/**
* Clean up and add badges to typedoc leaf sections
*/
/** Clean up and add badges to typedoc leaf sections */
export function prepareTypedocSidebar(items: SidebarItem[]) {
// skip contents file
const filtered = items.slice(1);
+1
View File
@@ -0,0 +1 @@
<!--@include: ../packages/analytics/README.md-->
Binary file not shown.

After

Width:  |  Height:  |  Size: 237 KiB

+438
View File
@@ -0,0 +1,438 @@
# Add extension entries to end of the list. On the website, extensions will be sorted by a combination of users and rating.
#
# Change the commit message or PR title to:
#
# > "docs: Added "[extension name]" to showcase"
#
# Use:
#
# - `chromeId` for the Chrome Web Store listing,
# - `firefoxSlug` for Firefox Add-ons (slug from https://addons.mozilla.org/firefox/addon/{slug}/)
#
# You may include one or more of these fields for your extension.
- # GitHub: Better Line Counts
chromeId: ocfdgncpifmegplaglcnglhioflaimkd
firefoxSlug: github-better-line-counts
- # Anime Skip Player
chromeId: mgmdkjcljneegjfajchedjpdhbadklcf
firefoxSlug: anime-skip
- # UltraWideo
chromeId: bfbnagnphiehemkdgmmficmjfddgfhpl
firefoxSlug: ultrawideo
- # StayFree - Website Blocker & Web Analytics
chromeId: elfaihghhjjoknimpccccmkioofjjfkf
firefoxSlug: stayfree
- # Doozy: Ai Made Easy
chromeId: okifoaikfmpfcamplcfjkpdnhfodpkil
- # tl;dv - Record, Transcribe & ChatGPT for Google Meet
chromeId: lknmjhcajhfbbglglccadlfdjbaiifig
- # Youtube中文配音
chromeId: oglffgiaiekgeicdgkdlnlkhliajdlja
- # PreMiD
chromeId: agjnjboanicjcpenljmaaigopkgdnihi
- # Markdown Sticky Notes
chromeId: aiakblgmlabokilgljkglggnpflljdgp
firefoxSlug: markdown-sticky-notes
- # DocVersionRedirector
chromeId: nomnkbngkijpffepcgbbofhcnafpkiep
- # Plex Skipper
chromeId: ceicccfeikoipigeghddpocceifjelph
firefoxSlug: plex-skipper
- # GitHub Custom Notifier
chromeId: aelkipgppclpfimeamgmlonimflbhlgf
firefoxSlug: github-custom-notifier
- # Fluent Read
chromeId: djnlaiohfaaifbibleebjggkghlmcpcj
- # Facebook Video Controls
chromeId: nhclljcpfmmaiojbhhnkpjcfmacfcian
firefoxSlug: facebook-video-controls
- # ElemSnap - Quick capture of webpage elements and conversion to images,
chromeId: mblkhbaakhbhiimkbcnmeciblfhmafna
- # MS Edge TTS (Text to Speech)
chromeId: oajalfneblkfiejoadecnmodfpnaeblh
firefoxSlug: ms-edge-tts-text-to-speech
- # YTBlock - Block any content from YouTube™
chromeId: nedcanggplmbbgmlpcjiafgjcpdimpea
- # demo.fun - Interactive product demos that convert
chromeId: oadbjpccljkplmhnjekgjamejnbadlne
- # SmartEReply: Elevate Your LinkedIn™ Engagement with AI 🚀📈
chromeId: iopdafdcollfgaoffingmahpffckmjni
- # WorkFlowy MultiFlow
chromeId: khjdmjcmpolknpccmaaipmidphjokhdf
- # 香草布丁🌿🍮- https://github.com/Xdy1579883916/vanilla-pudding
chromeId: fencadnndhdeggodopebjgdfdlhcimfk
- # MaxFocus: Link Preview
chromeId: bnacincmbaknlbegecpioobkfgejlojp
firefoxSlug: maxfocus-link-preview
- # 汇率转换-中文版本
chromeId: bcpgdpedphodjcjlminjbdeejccjbimp
- # Currency Converter Plus
chromeId: loeilaonggnalkaiiaepbegccilkmjjp
firefoxSlug: currency-converter-plus
- # Respond Easy
chromeId: npcnninnjghigjfiecefheeibomjpkak
- # mindful - stay focused on your goals
chromeId: cfkdcideecefncbglkhneoflfnmhoicc
- # 1Proompt
chromeId: lnhejcpclabmbgpiiomjbhalblnnbffg
- # NiceTab - https://github.com/web-dahuyou/NiceTab
chromeId: fonflmjnjbkigocpoommgmhljdpljain
- # Draftly for LinkedIn
chromeId: fcffekbnfcfdemeekijbbmgmkognnmkd
- # YouTube Summarized - Summarize any YouTube video
chromeId: nkndldfehcidpejfkokbeghpnlbppdmo
- # 社媒助手 - https://github.com/iszhouhua/social-media-copilot
chromeId: dbichmdlbjdeplpkhcejgkakobjbjalc
- # Dofollow Links for SEO
chromeId: opepfpjeogkbgeigkbepobceinnfmjdd
- # ChatGPT Writer: Use AI on Any Site (GPT-4o, Claude, Gemini, and More)
chromeId: pdnenlnelpdomajfejgapbdpmjkfpjkp
- # discord message translator
chromeId: jobnhifpphkgoelnhnopgkdhbdkiadmj
- # Habit Tracker app widget for daily habit tracking
chromeId: ncokhechhpjgjonhjnlaneglmdkfkcbj
- # Catppuccin for GitHub File Explorer Icons
chromeId: lnjaiaapbakfhlbjenjkhffcdpoompki
firefoxSlug: catppuccin-web-file-icons
- # WebChat: Chat with anyone on any website
chromeId: cpaedhbidlpnbdfegakhiamfpndhjpgf
- # YouTube Auto HD + FPS
chromeId: fcphghnknhkimeagdglkljinmpbagone
firefoxSlug: youtube-auto-hd-fps
- # MultiViewer Companion
chromeId: lpomjgbicdemjkgmbnkjncgdebogkhlb
firefoxSlug: multiviewer-companion
- # Sync Watch - Watch videos together on any site
chromeId: ggiafipgeeaaahnjamgpjcgkdpanhddg
firefoxSlug: syncwatch
- # Keyword Rank Checker
chromeId: nmldnjcblcihmegipecakhmnieiofmgl
firefoxSlug: keyword-rank-checker-sa
- # YouTube Simple View - Hide distractions & more
chromeId: gppllamhaciichleihemgilcpledblpn
firefoxSlug: youtube-simple-view
- # Propbar - Property Data Enhancer
chromeId: pccbghdfdnnkkbcdcibchpbffdgednkf
- # Text Search Pro - Search by case and whole-word match!
chromeId: lfknakglefggmdkjdfhhofkjnnolffkh
firefoxSlug: text-search-pro-ext
- # Invoice Generator
chromeId: mbenhbocjckkbaojacmaepiameldglij
firefoxSlug: quick-invoice-generator
- # Monthly Bill Tracker
chromeId: phlfhkmdofajnbhgmbmjkbkdgppgoppb
- # Wandpen - Instantly improve your writing with AI
chromeId: macmkmchfoclhpbncclinhjflmdkaoom
- # YouTube Hider - Remove Comments By Keywords, Usernames & Tools
chromeId: lhmgechokhmdekdpgkkemoeecelcaonm
- # QA Compass - Record standardized bug reports easily
chromeId: imgheieooppmahcgniieddodaliodeeg
- # aesthetic Notion, styled
chromeId: npgghjedpchajflknnbngajkjkdhncdo
- # Eye Dropper
chromeId: hmdcmlfkchdmnmnmheododdhjedfccka
firefoxSlug: eye_dropper
- # Cursorful - Screen Recorder with Auto Zoom
chromeId: eihpmapodnppeemkhkbhikmggfojdkjd
- # Show IP Live View of Website IPs for Developers
chromeId: hjjkgbibknbahijglkffklflidncplkn
- # Strong Password Generator
chromeId: ilbikcehnpkmldojkcmlldkoelofnbde
firefoxSlug: strongpasswordgenerator
- # ZenGram: Mindful Instagram, Your Way
chromeId: ocllfkhcdopiafndigclebelbecaiocp
- # Blync: Preview Links, Selection Search, AI Assistant
chromeId: odffpjnpocjfcaclnenaaaddghkgijdb
- # HTML to Markdown - Convert webpages to markdown
chromeId: kofbbilhmnkcmibjbioafflgmpkbnmme
- # Walmart WFS Profit Calculator
chromeId: boecmgggeigllcdocgioijmleimjbfkg
firefoxSlug: walmart-wfs-profit-calculator
- # Youtube Live Chat Fullscreen
chromeId: dlnjcbkmomenmieechnmgglgcljhoepd
firefoxSlug: youtube-live-chat-fullscreen
- # Python Code Runner
chromeId: keiealdacakpnbbljlmhfgcebmaadieg
firefoxSlug: code-runner-manager
- # Monochromate
chromeId: hafcajcllbjnoolpfngclfmmgpikdhlm
- # AliasVault - Open-Source Password & (Email) Alias Manager
chromeId: bmoggiinmnodjphdjnmpcnlleamkfedj
- # SnapThePrice: AI-Powered Real-time Lowest Price Finder
chromeId: hlnhhamckimoaiekbglafiebkfimhapb
- # radiofrance - news & broadcasts (French), music (international)
chromeId: gdjampjdgjmbifnhldgcnccdjkcoicmg
- # Blens - Time Tracker and AI Insight
chromeId: jlnhphlghikichhgbnkepenehbmloenb
firefoxSlug: blens-timetracker-ai-insight
- # Always Light Mode - Setting website always in light mode
chromeId: njnammmpdodmfkodnfpammnpdcbhnlcm
- # DesignPicker - Color Picker & Font Detector
chromeId: lblmfclcfniabobmamfkdogcgdagbhhb
firefoxSlug: design-colorpicker-fontdetect
- # Web to PDF
chromeId: pamnlaoeobcmhkliljfaofekeddpmfoh
firefoxSlug: export-web-to-pdf
- # Online CSV Viewer
chromeId: jmbcbeepjfenihlocplnbmbhimcoooka
firefoxSlug: csv-viewer
- # YouTube Video Transcript
chromeId: nkjcoophmpcmmgadnljnlpbpfdfacgbo
firefoxSlug: youtube-transcript-copy
- # NetSuite Record Scripts
chromeId: lcaieahkjgeggeiihblhcjbbjlppgieh
firefoxSlug: netsuite-scripts-manager
- # VueTracker
chromeId: gmocfknjllodfiomnljmaehcplnekhlo
- # CanCopy - A web extension that allow you to copy any content from website
chromeId: ggcfemmoabhhelfkhknhbnkmeahloiod
- # Read Frog
chromeId: modkelfkcfjpgbfmnbnllalkiogfofhb
firefoxSlug: read-frog-open-ai-translator
- # Bilibili Feed History Helper
chromeId: npfopljnjbamegincfjelhjhnonnjloo
- # NZBDonkey - The ultimate NZB file download tool
chromeId: edkhpdceeinkcacjdgebjehipmnbomce
- # WeChat Markdown Editor(微信 Markdown 编辑器)
chromeId: cckggnbnimdbbpmdinkkgbbncopbloob
- # Tab Grab
chromeId: jcblcjolcojmfopefcighfmkkefbaofg
firefoxSlug: tab-grab
- # BrowserLens - https://browserlens.com/
chromeId: eehmoikadcijkapfjocnhjclpbaindlb
firefoxSlug: browserlens
- # Epic Games Library Extension
chromeId: hfhellofkjebbchcdffmicekjdomkcmc
firefoxSlug: epic-games-library-extension
- # Zen Analytics Pixel Tracker - zapt.web.app
chromeId: gknigcbhlammoakmmdddkblknanpjiac
- # Crypto Pulse - Compose your newtab with nature images, widgets & realtime Crypto Price & Bitcoin RSS.
chromeId: cnklededohhcbmjjdlbjdkkihkgoggol
- # Youtube Video Scheduler
chromeId: miponnamafdenpgjemkknimgjfibicdc
firefoxSlug: youtube-video-scheduler
- # Chatslator: Livestream Chat Translator
chromeId: nhmbcmalgpkjbomhlhgdicanmkkaajmg
firefoxSlug: chatslator
- # 公众号阅读增强器 - https://wxreader.honwhy.wang
chromeId: mbamjfdjbcdgpopfnkkmlohadbbnplhm
- # 토탐정
chromeId: hannhecbnjnnbbafffmogdlnajpcomek
firefoxSlug: 토탐정
- # 2FAS Pass - https://2fas.com/
chromeId: ehboaofjncodknjkngdggmpdinhdoijp
firefoxSlug: 2fas-pass-browser-extension
- # Quick Prompt - https://github.com/wenyuanw/quick-prompt
chromeId: hnjamiaoicaepbkhdoknhhcedjdocpkd
firefoxSlug: quick-prompt
- # Add QR Code Generator Icon Back To Address Bar
chromeId: kacblhilkacgfnkjfodalohcnllcgmjd
- # Piwik PRO Tracking Helper
chromeId: fkbdlogfdjmpfepbbbjcgcfbgbcfcnne
firefoxSlug: piwik-pro-tracking-helper
- # PIPX - Take Control of Picture-in-Picture, Automatically
chromeId: nkbikckldmljjiiajklecmgmajgapbfl
- # Browsely - AI-powered browser extension
chromeId: hgppdobcpkfkmiegekaglonjajeojmdd
- # Filmbudd Pro - Simple, private and synced ratings and watch notes across all your devices
chromeId: ehmoihnjgkdimihkhokkmfjdgomohjgm
- # MultiField CopyCat - Copy, Paste & Autofill Web Forms Instantly
chromeId: alglchohmdikgdjhafiicilegegieafa
- # ChatSight - Add Table of Contents to ChatGPT
chromeId: aamihahiiogceidpbnfgehacgiecephe
- # BetterCampus (prev. BetterCanvas)
chromeId: cndibmoanboadcifjkjbdpjgfedanolh
firefoxSlug: better-canvas
- # Leetcode Fonts - Change fonts in leetcode effortlessly
chromeId: hinfimgacobnellbncbcpdlpaapcofaa
- # TranslateManga - Manga Translator & Manga Tracker
chromeId: kbkbfefhhabpkibojinapkkgciiacggg
- # SiteData - Free Website Traffic Checker & Reverse AdSense Tool
chromeId: emeakbgdecgmdjgegnejpppcnkcnoaen
firefoxSlug: sitedata
- # Livestream Chat Reader - Text-to-Speech for YouTube/Twitch chat
chromeId: gpnckbhgpnjciklpoehkmligeaebigaa
- # ChatGPT Token Counter - Count tokens in real time on chatgpt conversation
chromeId: fjlalaedpfcojcfpkgkglbjjbbkofgnl
firefoxSlug: chatgpt-token-counter
- # LinuxDo Scripts - 为 linux.do 用户提供了一些增强功能
chromeId: fbgblmjbeebanackldpbmpacppflgmlj
firefoxSlug: linux_do-scripts
- # Zen Virtual Piano - https://zen-piano.web.app/
chromeId: dfacnjidgbagicaekenjgclfnhdnjjdi
- # Crypto Pulse price tracker - https://get-crypto-pulse.web.app/
chromeId: naeibcegmgpofimedkmfgjgphfhfhlab
- # Redirect Web - Automatically redirect pages or open them in another app
chromeId: ffglckbhfbfmdkefdmjbhpnffkcmlhdh
- # Capture It - Capture & Edit Screenshots
chromeId: eglpfhbhmelampoihamjomgkeobgdofl
- # Teams Chat Exporter
chromeId: jmghclbfbbapimhbgnpffbimphlpolnm
firefoxSlug: teams-chat-exporter
- # Lofi BGM Player - Free lofi focus music for work & study
chromeId: jdcppdokgfbnhiacbeplahgnciahnhck
firefoxSlug: lofi-bgm-player
- # Margin - Annotate and highlight any webpage, with your notes saved to the decentralized AT Protocol.
chromeId: cgpmbiiagnehkikhcbnhiagfomajncpa
- # KeyFloat - Floating multilingual keyboard with native key mappings, drag, dark mode, sounds, and dynamic layouts for macOS & Windows
chromeId: mfjdonmgmgcijagclnkfhmjiblbfjaid
- # Glossy New Tab - Say Goodbye to Boring Tabs with live wallpapers
chromeId: dhiekgdaipindoapjmcnpompdknjeijf
firefoxSlug: glossy-new-tab
- # All API Hub AI Relay & New API Manager - https://github.com/qixing-jk/all-api-hub
chromeId: lapnciffpekdengooeolaienkeoilfeo
firefoxSlug: all-api-hub
- # Scrape Similar - Extract data from websites into spreadsheets - https://github.com/zizzfizzix/scrape-similar
chromeId: bhgobenflkkhfcgkikejaaejenoddcmo
- # isTrust - https://github.com/Internet-Society-Belgium/isTrust/
chromeId: kinlknncggaihnhdcalijdmpbhbflalm
- # Dymo
chromeId: ojpakgiekphppgkcdihbjpafobhnhlkp
- # Extension Rank Checker - Extension Ranker
chromeId: pmgehhllikbjmadpenhabejhpemplhmd
firefoxSlug: rank-checker
- # PlayFaster - Enhanced playback speed control for online videos and audio
chromeId: fppcbkhpahkbgijkdcpjgjmhpfbmfiih
firefoxSlug: playfaster
- # LatTab - Learn Latin With Every New Tab
chromeId: eiocjaocpmackhbaffoejkcmnfbdpgpj
firefoxSlug: lattab-learn-latin-new-tabs
- # Vim What? - Interactive Vim command reference
chromeId: ngbehgnlcdjkbnihgpkgdangbhemidge
firefoxSlug: vim-what
- # FRED - Fraud Recognition Easy Detection
chromeId: bjdbcabacnlmbpcmiapcdfancfgcakfn
firefoxSlug: fred
- # Clear Wisdom - Gems of wisdom from James Clear's 3-2-1 newsletter
chromeId: jijfmgoijddfmlcdghopbkdpelbpmjdm
firefoxSlug: clear-wisdom
- # Soundcloud Enhanced Pro
chromeId: ggplcohodggmdfpopelnpplhgfjclomi
- # AlarmBot: ULTIMATE Web Monitoring & Smart Price Alerts
chromeId: mpckalcodookackleecihhnngdibelif
- # TF2 Trader - TF2 & Steam Trading Extension - https://github.com/offish/tf2-trader
chromeId: gmicpekfpbikhibodgokfpghadkclhoe
Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

After

Width:  |  Height:  |  Size: 136 KiB

+9
View File
@@ -0,0 +1,9 @@
---
layout: page
---
<script lang="ts" setup>
import BlogHome from './.vitepress/components/BlogHome.vue';
</script>
<BlogHome />
@@ -0,0 +1,12 @@
---
layout: blog
title: Real World Messaging
description: |
The extension messaging APIs are difficult to learn. Let's go beyond the simple examples from Chrome and Firefox's documentation to build our own simple messaging system from scratch.
authors:
- name: Aaron Klinker
github: aklinker1
date: 2024-10-20T04:54:23.601Z
---
Test content **bold** _italic_
@@ -0,0 +1,76 @@
---
layout: blog
title: Introducing <code>#imports</code>
description: Learn how WXT's new <code>#imports</code> module works and how to use it.
authors:
- name: Aaron Klinker
github: aklinker1
date: 2024-12-06T14:39:00.000Z
---
WXT v0.20 introduced a new way of manually importing its APIs: **the `#imports` module**. This module was introduced to simplify import statements and provide more visibility into all the APIs WXT provides.
<!-- prettier-ignore -->
```ts
import { browser } from 'wxt/browser'; // [!code --]
import { createShadowRootUi } from 'wxt/utils/content-script-ui/shadow-root'; // [!code --]
import { defineContentScript } from 'wxt/utils/define-content-script'; // [!code --]
import { injectScript } from 'wxt/utils/inject-script'; // [!code --]
import { // [!code ++]
browser, createShadowRootUi, defineContentScript, injectScript // [!code ++]
} from '#imports'; // [!code ++]
```
The `#imports` module is considered a "virtual module", because the file doesn't actually exist. At build-time, imports are split into individual statements for each API:
:::code-group
```ts [What you write]
import { defineContentScript, injectScript } from '#imports';
```
```ts [What the bundler sees]
import { defineContentScript } from 'wxt/utils/define-content-script';
import { injectScript } from 'wxt/utils/inject-script';
```
:::
Think of `#imports` as a convenient way to access all of WXT's APIs from one place, without impacting performance or bundle size.
This enables better tree-shaking compared to v0.19 and below.
:::tip Need to lookup the full import path of an API?
Open up your project's `.wxt/types/imports-module.d.ts` file.
:::
## Mocking
When writing tests, you might need to mock APIs from the `#imports` module. While mocking these APIs is very easy, it may not be immediately clear how to accomplish it.
Let's look at an example using Vitest. When [configured with `wxt/testing`](/guide/essentials/unit-testing#vitest), Vitest sees the same transformed code as the bundler. That means to mock an API from `#imports`, you need to call `vi.mock` with the real import path, not `#imports`:
```ts
import { injectScript } from '#imports';
import { vi } from 'vitest';
vi.mock('wxt/utils/inject-script')
const injectScriptMock = vi.mocked(injectScript);
injectScriptMock.mockReturnValueOnce(...);
```
## Conclusion
You don't have to use `#imports` if you don't like - you can continue importing APIs from their submodules. However, using `#imports` is the recommended approach moving forwards.
- As more APIs are added, you won't have to memorize additional import paths.
- If breaking changes are made to import paths in future major versions, `#imports` won't break.
Happy Coding 😄
> P.S. Yes, this is exactly how [Nuxt's `#imports`](https://nuxt.com/docs/guide/concepts/auto-imports#explicit-imports) works! We use the exact same library, [`unimport`](https://github.com/unjs/unimport).
---
[Discuss this blog post on Github](https://github.com/wxt-dev/wxt/discussions/1543).
+113 -7
View File
@@ -16,7 +16,8 @@ img.src = imageUrl;
```
```html [HTML]
<img src="~/assets/image.png" />
<!-- In HTML tags, you must use the relative path --->
<img src="../assets/image.png" />
```
```css [CSS]
@@ -25,11 +26,27 @@ img.src = imageUrl;
}
```
```vue [Vue]
<script>
import image from '~/assets/image.png';
</script>
<template>
<img :src="image" />
</template>
```
```jsx [JSX]
import image from '~/assets/image.png';
<img src={image} />;
```
:::
## `/public` Directory
Files inside `<srcDir>/public/` are copied into the output folder as-is, without being processed by WXT's bundler.
Files inside `<rootDir>/public/` are copied into the output folder as-is, without being processed by WXT's bundler.
Here's how you access them:
@@ -52,6 +69,20 @@ img.src = imageUrl;
}
```
```vue [Vue]
<template>
<img src="/image.png" />
</template>
```
```jsx [JSX]
<img src="/image.png" />
```
:::
:::warning
Assets in the `public/` directory are **_not_** accessible in content scripts by default. To use a public asset in a content script, you must add it to your manifest's [`web_accessible_resources` array](/api/reference/wxt/type-aliases/UserManifest#web-accessible-resources).
:::
## Inside Content Scripts
@@ -62,8 +93,7 @@ But, inside content scripts, the hostname is whatever the tab is set to. So if y
To fix this, you need to convert the image to a full URL using `browser.runtime.getURL`:
```ts
// entrypoints/content.ts
```ts [entrypoints/content.ts]
import iconUrl from '/icon/128.png';
export default defineContentScript({
@@ -77,6 +107,82 @@ export default defineContentScript({
## WASM
:::warning 🚧 Under construction
These docs will be coming soon!
:::
How a `.wasm` file is loaded varies greatly between packages, but most follow a basic setup: Use a JS API to load and execute the `.wasm` file.
For an extension, that means two things:
1. The `.wasm` file needs to be present in output folder so it can be loaded.
2. You must import the JS API to load and initialize the `.wasm` file, usually provided by the NPM package.
For an example, let's say you have a content script needs to parse TS code into AST. We'll use [`@oxc-parser/wasm`](https://www.npmjs.com/package/@oxc-parser/wasm) to do it!
First, we need to copy the `.wasm` file to the output directory. We'll do it with a [WXT module](/guide/essentials/wxt-modules):
```ts
// modules/oxc-parser-wasm.ts
import { resolve } from 'node:path';
export default defineWxtModule((wxt) => {
wxt.hook('build:publicAssets', (_, assets) => {
assets.push({
absoluteSrc: resolve(
'node_modules/@oxc-parser/wasm/web/oxc_parser_wasm_bg.wasm',
),
relativeDest: 'oxc_parser_wasm_bg.wasm',
});
});
});
```
Run `wxt build`, and you should see the WASM file copied into your `.output/chrome-mv3` folder!
Next, since this is in a content script and we'll be fetching the WASM file over the network to load it, we need to add the file to the `web_accessible_resources`:
```ts [wxt.config.ts]
export default defineConfig({
manifest: {
web_accessible_resources: [
{
// We'll use this matches in the content script as well
matches: ['*://*.github.com/*'],
// Use the same path as `relativeDest` from the WXT module
resources: ['/oxc_parser_wasm_bg.wasm'],
},
],
},
});
```
And finally, we need to load and initialize the `.wasm` file inside the content script to use it:
```ts [entrypoints/content.ts]
import initWasm, { parseSync } from '@oxc-parser/wasm';
export default defineContentScript({
matches: '*://*.github.com/*',
async main(ctx) {
if (!location.pathname.endsWith('.ts')) return;
// Get text from GitHub
const code = document.getElementById(
'read-only-cursor-text-area',
)?.textContent;
if (!code) return;
const sourceFilename = document.getElementById('file-name-id')?.textContent;
if (!sourceFilename) return;
// Load the WASM file:
await initWasm({
module_or_path: browser.runtime.getURL('/oxc_parser_wasm_bg.wasm'),
});
// Once loaded, we can use `parseSync`!
const ast = parseSync(code, { sourceFilename });
console.log(ast);
},
});
```
This code is taken directly from `@oxc-parser/wasm` docs with one exception: We manually pass in a file path. In a standard NodeJS or web project, the default path works just fine so you don't have to pass anything in. However, extensions are different. You should always explicitly pass in the full URL to the WASM file in your output directory, which is what `browser.runtime.getURL` returns.
Run your extension, and you should see OXC parse the TS file!
+19 -13
View File
@@ -11,19 +11,7 @@ export default defineConfig({
});
```
By default, WXT automatically setups up auto-imports for all of it's own APIs:
- [`browser`](/api/reference/wxt/browser/variables/browser) from `wxt/browser`
- [`defineContentScript`](/api/reference/wxt/sandbox/functions/defineContentScript) from `wxt/sandbox`
- [`defineBackground`](/api/reference/wxt/sandbox/functions/defineBackground) from `wxt/sandbox`
- [`defineUnlistedScript`](/api/reference/wxt/sandbox/functions/defineUnlistedScript) from `wxt/sandbox`
- [`createIntegratedUi`](/api/reference/wxt/client/functions/createIntegratedUi) from `wxt/client`
- [`createShadowRootUi`](/api/reference/wxt/client/functions/createShadowRootUi) from `wxt/client`
- [`createIframeUi`](/api/reference/wxt/client/functions/createIframeUi) from `wxt/client`
- [`fakeBrowser`](/api/reference/wxt/testing/variables/fakeBrowser) from `wxt/testing`
- And more!
WXT also adds some project directories as auto-import sources automatically:
By default, WXT automatically sets up auto-imports for all of it's own APIs and some of your project directories:
- `<srcDir>/components/*`
- `<srcDir>/composables/*`
@@ -32,6 +20,8 @@ WXT also adds some project directories as auto-import sources automatically:
All named and default exports from files in these directories are available everywhere else in your project without having to import them.
To see the complete list of auto-imported APIs, run [`wxt prepare`](/api/cli/wxt-prepare) and look at your project's `.wxt/types/imports-module.d.ts` file.
## TypeScript
For TypeScript and your editor to recognize auto-imported variables, you need to run the [`wxt prepare` command](/api/cli/wxt-prepare).
@@ -110,3 +100,19 @@ export default defineConfig({
imports: false, // [!code ++]
});
```
## Explicit Imports (`#imports`)
You can manually import all of WXT's APIs via the `#imports` module:
```ts
import {
createShadowRootUi,
ContentScriptContext,
MatchPattern,
} from '#imports';
```
To learn more about how the `#imports` module works, read the [related blog post](/blog/2024-12-06-using-imports-module).
If you've disabled auto-imports, you should still use `#imports` to import all of WXT's APIs from a single place.
+58 -15
View File
@@ -4,9 +4,9 @@ outline: deep
# Browser Startup
> See the [API Reference](/api/reference/wxt/interfaces/ExtensionRunnerConfig) for a full list of config.
> See the [API Reference](/api/reference/wxt/interfaces/WebExtConfig) for a full list of config.
During development WXT uses [`web-ext` by Mozilla](https://www.npmjs.com/package/web-ext) to automatically open a browser window with your extension installed.
During development, WXT uses [`web-ext` by Mozilla](https://www.npmjs.com/package/web-ext) to automatically open a browser window with your extension installed.
## Config Files
@@ -14,15 +14,15 @@ You can configure browser startup in 3 places:
1. `<rootDir>/web-ext.config.ts`: Ignored from version control, this file lets you configure your own options for a specific project without affecting other developers
```ts
import { defineRunnerConfig } from 'wxt';
```ts [web-ext.config.ts]
import { defineWebExtConfig } from 'wxt';
export default defineRunnerConfig({
export default defineWebExtConfig({
// ...
});
```
2. `<rootDir>/wxt.config.ts`: Via the [`runner` config](/api/reference/wxt/interfaces/InlineConfig#runner), included in version control
2. `<rootDir>/wxt.config.ts`: Via the [`webExt` config](/api/reference/wxt/interfaces/InlineConfig#webext), included in version control
3. `$HOME/web-ext.config.ts`: Provide default values for all WXT projects on your computer
## Recipes
@@ -31,8 +31,10 @@ You can configure browser startup in 3 places:
To set or customize the browser opened during development:
```ts
export default defineRunnerConfig({
```ts [web-ext.config.ts]
import { defineWebExtConfig } from 'wxt';
export default defineWebExtConfig({
binaries: {
chrome: '/path/to/chrome-beta', // Use Chrome Beta instead of regular Chrome
firefox: 'firefoxdeveloperedition', // Use Firefox Developer Edition instead of regular Firefox
@@ -41,28 +43,46 @@ export default defineRunnerConfig({
});
```
```ts [wxt.config.ts]
export default defineConfig({
webExt: {
binaries: {
chrome: '/path/to/chrome-beta', // Use Chrome Beta instead of regular Chrome
firefox: 'firefoxdeveloperedition', // Use Firefox Developer Edition instead of regular Firefox
edge: '/path/to/edge', // Open MS Edge when running "wxt -b edge"
},
},
});
```
By default, WXT will try to automatically discover where Chrome/Firefox are installed. However, if you have chrome installed in a non-standard location, you need to set it manually as shown above.
### Persist Data
By default, to keep from modifying your browser's existing profiles, `web-ext` creates a brand new profile every time you run the `dev` script.
Right now, Chromium based browsers are the only browsers that support overriding this behavior and persisting data when running the `dev` script multiple times.
To persist data, set the `--user-data-dir` flag:
To persist data, set the `--user-data-dir` flag in any of the config files mentioned above:
:::code-group
```ts [Mac/Linux]
export default defineRunnerConfig({
import { defineWebExtConfig } from 'wxt';
export default defineWebExtConfig({
chromiumArgs: ['--user-data-dir=./.wxt/chrome-data'],
});
```
```ts [Windows]
import { resolve } from 'node:path';
import { defineWebExtConfig } from 'wxt';
export default defineRunnerConfig({
export default defineWebExtConfig({
// On Windows, the path must be absolute
chromiumArgs: [`--user-data-dir="${resolve(".wxt/chrome-data")}"`
chromiumProfile: resolve('.wxt/chrome-data'),
keepProfileChanges: true,
});
```
@@ -71,15 +91,38 @@ export default defineRunnerConfig({
Now, next time you run the `dev` script, a persistent profile will be created in `.wxt/chrome-data/{profile-name}`. With a persistent profile, you can install devtools extensions to help with development, allow the browser to remember logins, etc, without worrying about the profile being reset the next time you run the `dev` script.
:::tip
You can use any directory you'd like for `--user-data-dir`, the examples above create a persistent profile for each WXT project. To create a profile for all WXT projects, you can put the `chrome-data` directory inside you're user's home directory.
You can use any directory you'd like for `--user-data-dir`, the examples above create a persistent profile for each WXT project. To create a profile for all WXT projects, you can put the `chrome-data` directory inside your user's home directory.
:::
### Disable Opening Browser
If you prefer to load the extension into your browser manually, you can disable the auto-open behavior:
```ts
export default defineRunnerConfig({
```ts [web-ext.config.ts]
import { defineWebExtConfig } from 'wxt';
export default defineWebExtConfig({
disabled: true,
});
```
### Enabling Chrome Features
Some APIs are disabled in Chrome during development because of the default flags `web-ext` uses to launch Chrome, like the [Prompt API](https://developer.chrome.com/docs/ai/prompt-api).
If your extension depends on new features or services, you can enable them via `chromiumArgs`:
```ts
import { defineWebExtConfig } from 'wxt';
export default defineWebExtConfig({
chromiumArgs: [
// For example, this flag enables the Prompt API
'--disable-features=DisableLoadExtensionCommandLineSwitch',
],
});
```
There is no comprehensive list of what feature flags enable what APIs and services.
Alternatively, if you can't find a flag that enables a feature you're looking for, [disable the opening the browser during development](#disable-opening-browser) and use your regular chrome profile for development.
@@ -10,70 +10,10 @@ WXT does several pre-processing steps to try and prevent errors during this proc
2. Use `@webext-core/fake-browser` to create a fake version of the `chrome` and `browser` globals expected by extensions.
3. Pre-process the JS/TS code, stripping out the `main` function then tree-shaking unused code from the file
However, this process is not perfect. It doesn't setup all the globals found in the browser and the APIs may behave differently. As such, **_you should avoid using browser or extension APIs outside the `main` function of your entrypoints!_**
However, this process is not perfect. It doesn't setup all the globals found in the browser and the APIs may behave differently. As such, **_you should avoid using browser or extension APIs outside the `main` function of your entrypoints!_** See [Entrypoint Limitations](/guide/essentials/extension-apis#entrypoint-limitations) for more details.
:::tip
If you're running into errors while importing entrypoints, run `wxt prepare --debug` to see more details about this process. When debugging, WXT will print out the pre-processed code to help you identify issues.
:::
Once the environment has been polyfilled and your code pre-processed, it's up the entrypoint loader to import your code, extracting the options from the default export.
There are two options for loading your entrypoints:
1. `vite-node` - default as of `v0.19.0`
2. `jiti` (**DEPRECATED, will be removed in `v0.20.0`**) - Default before `v0.19.0`
## vite-node
Since 0.19.0, WXT uses `vite-node`, the same tool that powers Vitest and Nuxt, to import your entrypoint files. It re-uses the same vite config used when building your extension, making it the most stable entrypoint loader.
## jiti
To enable `jiti`:
```ts
export default defineConfig({
entrypointLoader: 'jiti',
});
```
This is the original method WXT used to import TS files. However, because it doesn't support vite plugins like `vite-node`, it does one additional pre-processing step: It removes **_ALL_** imports from your code.
That means you cannot use imported variables outside the `main` function in JS entrypoints, like for content script `matches` or other options:
```ts
// entrypoints/content.ts
import { GOOGLE_MATCHES } from '~/utils/match-patterns';
export default defineContentScript({
matches: GOOGLE_MATCHES,
main() {
// ...
},
});
```
```
$ wxt build
wxt build
WXT 0.14.1
Building chrome-mv3 for production with Vite 5.0.5
✖ Command failed after 360 ms
[8:55:54 AM] ERROR entrypoints/content.ts: Cannot use imported variable "GOOGLE_MATCHES" before main function.
```
Usually, this error occurs when you try to extract options into a shared file or when running code outside the `main` function. To fix the example from above, use literal values when defining an entrypoint instead of importing them:
```ts
import { GOOGLE_MATCHES } from '~/utils/match-patterns'; // [!code --]
export default defineContentScript({
matches: GOOGLE_MATCHES, // [!code --]
matches: ['*//*.google.com/*'], // [!code ++]
main() {
// ...
},
});
```
@@ -4,11 +4,15 @@
WXT supports [dotenv files the same way as Vite](https://vite.dev/guide/env-and-mode.html#env-files). Create any of the following files:
```
```plaintext
.env
.env.local
.env.[mode]
.env.[mode].local
.env.[browser]
.env.[browser].local
.env.[mode].[browser]
.env.[mode].[browser].local
```
And any environment variables listed inside them will be available at runtime:
@@ -38,6 +42,8 @@ WXT provides some custom environment variables based on the current command:
| `import.meta.env.EDGE` | `boolean` | Equivalent to `import.meta.env.BROWSER === "edge"` |
| `import.meta.env.OPERA` | `boolean` | Equivalent to `import.meta.env.BROWSER === "opera"` |
You can set the [`targetBrowsers`](/api/reference/wxt/interfaces/InlineConfig#targetbrowsers) option to make the `BROWSER` variable a more specific type, like `"chrome" | "firefox"`.
You can also access all of [Vite's environment variables](https://vite.dev/guide/env-and-mode.html#env-variables):
| Usage | Type | Description |
@@ -52,3 +58,38 @@ Vite provides two other environment variables, but they aren't useful in WXT pro
- `import.meta.env.BASE_URL`: Use `browser.runtime.getURL` instead.
- `import.meta.env.SSR`: Always `false`.
:::
## Manifest
To use environment variables in the manifest, you need to use the function syntax:
```ts
export default defineConfig({
modules: ['@wxt-dev/module-vue'],
manifest: { // [!code --]
oauth2: { // [!code --]
client_id: import.meta.env.WXT_APP_CLIENT_ID // [!code --]
} // [!code --]
} // [!code --]
manifest: () => ({ // [!code ++]
oauth2: { // [!code ++]
client_id: import.meta.env.WXT_APP_CLIENT_ID // [!code ++]
} // [!code ++]
}), // [!code ++]
});
```
WXT can't load your `.env` files until after the config file has been loaded. So by using the function syntax for `manifest`, it defers creating the object until after the `.env` files are loaded into the process.
Note that Vite's runtime environment variables, like `import.meta.env.DEV`, will not be defined. Instead, access the `mode` like this:
```ts
export default defineConfig({
manifest: ({ mode }) => {
const isDev = mode === 'development';
console.log('Is development mode:', isDev);
// ...
},
});
```
+7 -4
View File
@@ -6,13 +6,12 @@ WXT includes a system that lets you hook into the build process and make changes
The easiest way to add a hook is via the `wxt.config.ts`. Here's an example hook that modifies the `manifest.json` file before it is written to the output directory:
```ts
// wxt.config.ts
```ts [wxt.config.ts]
export default defineConfig({
hooks: {
'build:manifestGenerated': (wxt, manifest) => {
if (wxt.config.mode === 'development') {
manifest.title += ' (DEV)';
manifest.name += ' (DEV)';
}
},
},
@@ -21,6 +20,8 @@ export default defineConfig({
Most hooks provide the `wxt` object as the first argument. It contains the resolved config and other info about the current build. The other arguments can be modified by reference to change different parts of the build system.
You can find the [list of all available hooks](/api/reference/wxt/interfaces/WxtHooks) in the API reference.
Putting one-off hooks like this in your config file is simple, but if you find yourself writing lots of hooks, you should extract them into [WXT Modules](/guide/essentials/wxt-modules) instead.
## Execution Order
@@ -33,7 +34,7 @@ Because hooks can be defined in multiple places, including [WXT Modules](/guide/
To see the order for your project, run `wxt prepare --debug` flag and search for the "Hook execution order":
```
```plaintext
⚙ Hook execution order:
⚙ 1. wxt:built-in:unimport
⚙ 2. src/modules/auto-icons.ts
@@ -51,7 +52,9 @@ Changing execution order is simple:
📄 0.my-module.ts
📄 1.another-module.ts
```
- If you need to run an NPM module after user modules, just make it a user module and prefix the filename with a number!
```ts
// modules/2.i18n.ts
export { default } from '@wxt-dev/i18n/module';
+44 -22
View File
@@ -1,10 +1,17 @@
# Manifest
In WXT, there is no `manifest.json` file in your source code. Instead, WXT generates it during the build process based off files in your project.
In WXT, there is no `manifest.json` file in your source code. Instead, WXT generates the manifest from multiple sources:
## Manifest Config
- Global options [defined in your `wxt.config.ts` file](#global-options)
- Entrypoint-specific options [defined in your entrypoints](/guide/essentials/entrypoints#defining-manifest-options)
- [WXT Modules](/guide/essentials/wxt-modules) added to your project can modify your manifest
- [Hooks](/guide/essentials/config/hooks) defined in your project can modify your manifest
To manually add a property to the `manifest.json` output during builds, use the `manifest` config inside `wxt.config.ts`:
Your extension's `manifest.json` will be output to `.output/{target}/manifest.json` when running `wxt build`.
## Global Options
To add a property to your manifest, use the `manifest` config inside your `wxt.config.ts`:
```ts
export default defineConfig({
@@ -121,7 +128,7 @@ If a version is not present in your `package.json`, it defaults to `"0.0.0"`.
WXT automatically discovers your extension's icon by looking at files in the `public/` directory:
```
```plaintext
public/
├─ icon-16.png
├─ icon-24.png
@@ -130,7 +137,7 @@ public/
└─ icon-128.png
```
Specifically, if an icon must match one of these regex to be discovered:
Specifically, an icon must match one of these regex to be discovered:
<<< @/../packages/wxt/src/core/utils/manifest.ts#snippet
@@ -152,10 +159,39 @@ export default defineConfig({
Alternatively, you can use [`@wxt-dev/auto-icons`](https://www.npmjs.com/package/@wxt-dev/auto-icons) to let WXT generate your icon at the required sizes.
### Firefox `theme_icons`
Firefox supports a [`theme_icons`](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/action#theme_icons) field on the toolbar action that swaps between a light and dark variant based on the current browser theme.
When [targeting Firefox](/guide/essentials/target-different-browsers.md), WXT auto-discovers paired light/dark icons in the `public/` directory and attaches them to `action` (MV3) or `browser_action` (MV2). You only need to drop both variants next to your regular icons:
```plaintext
public/
├─ icon-16.png # regular (default_icon)
├─ icon-light-16.png # Firefox light theme
├─ icon-dark-16.png # Firefox dark theme
├─ icon-32.png
├─ icon-light-32.png
└─ icon-dark-32.png
```
A size is only included in `theme_icons` if **both** a light and a dark file are present. The following filename patterns are discovered:
<<< @/../packages/wxt/src/core/utils/theme-icons.ts#snippet
Only `.png` files are discovered today, even though Firefox supports `.svg` - follow [#1120](https://github.com/wxt-dev/wxt/issues/1120) for updates.
If you set `manifest.action.theme_icons` (or `manifest.browser_action.theme_icons`) explicitly in `wxt.config.ts`, WXT will not overwrite it.
## Permissions
> [Chrome docs](https://developer.chrome.com/docs/extensions/reference/permissions/)
Most of the time, you need to manually add permissions to your manifest. Only in a few specific situations are permissions added automatically:
- During development: the `tabs` and `scripting` permissions will be added to enable hot reloading.
- When a `sidepanel` entrypoint is present: The `sidepanel` permission is added.
```ts
export default defineConfig({
manifest: {
@@ -171,7 +207,7 @@ export default defineConfig({
```ts
export default defineConfig({
manifest: {
permissions: ['storage', 'tabs'],
host_permissions: ['https://www.google.com/*'],
},
});
```
@@ -211,22 +247,7 @@ By default, whenever an `action` is generated, WXT falls back to `browser_action
### Action With Popup
To generate a manifest where a UI appears after clicking the icon, just create a [Popup entrypoint](/guide/essentials/entrypoints#popup).
```ts
export default defineConfig({
hooks: {
build: {
manifestGenerated(manifest) {
// Update the manifest variable by reference
manifest.name = 'Overriden name';
},
},
},
});
```
If you want to use a `page_action` for MV2, add the following meta tag to the HTML document's head:
To generate a manifest where a UI appears after clicking the icon, just create a [Popup entrypoint](/guide/essentials/entrypoints#popup). If you want to use a `page_action` for MV2, add the following meta tag to the HTML document's head:
```html
<meta name="manifest.type" content="page_action" />
@@ -238,6 +259,7 @@ If you want to use the `activeTab` permission or the `browser.action.onClicked`
1. Delete the [Popup entrypoint](/guide/essentials/entrypoints#popup) if it exists
2. Add the `action` key to your manifest:
```ts
export default defineConfig({
manifest: {
+7 -7
View File
@@ -5,10 +5,10 @@
Define runtime configuration in a single place, `<srcDir>/app.config.ts`:
```ts
import { defineAppConfig } from 'wxt/sandbox';
import { defineAppConfig } from '#imports';
// Define types for your config
declare module 'wxt/sandbox' {
declare module 'wxt/utils/define-app-config' {
export interface WxtAppConfig {
theme?: 'light' | 'dark';
}
@@ -20,15 +20,15 @@ export default defineAppConfig({
```
:::warning
This file is committed to the repo, so don't put any secrets here. Instead, use [Environment Variables](#environment-variables)
This file is committed to the repo, so don't put any secrets here. Instead, use [Environment Variables](/guide/essentials/config/environment-variables)
:::
To access runtime config, WXT provides the `useAppConfig` function:
To access runtime config, WXT provides the `getAppConfig` function:
```ts
import { useAppConfig } from 'wxt/sandbox';
import { getAppConfig } from '#imports';
console.log(useAppConfig()); // { theme: "dark" }
console.log(getAppConfig()); // { theme: "dark" }
```
## Environment Variables in App Config
@@ -36,7 +36,7 @@ console.log(useAppConfig()); // { theme: "dark" }
You can use environment variables in the `app.config.ts` file.
```ts
declare module 'wxt/sandbox' {
declare module 'wxt/utils/define-app-config' {
export interface WxtAppConfig {
apiKey?: string;
skipWelcome: boolean;
+1 -1
View File
@@ -14,7 +14,7 @@ At a minimum, you need to create a TSConfig in your root directory that looks li
Or if you're in a monorepo, you may not want to extend the config. If you don't extend it, you need to add `.wxt/wxt.d.ts` to the TypeScript project:
```ts
/// <reference types="./.wxt/wxt.d.ts" />
/// <reference path="./.wxt/wxt.d.ts" />
```
## Compiler Options
+3 -6
View File
@@ -12,8 +12,7 @@ In most cases, you shouldn't change Vite's build settings. WXT provides sensible
You can change Vite's config via the `wxt.config.ts` file:
```ts
// wxt.config.ts
```ts [wxt.config.ts]
import { defineConfig } from 'wxt';
export default defineConfig({
@@ -28,8 +27,7 @@ export default defineConfig({
To add a plugin, install the NPM package and add it to the Vite config:
```ts
// wxt.config.ts
```ts [wxt.config.ts]
import { defineConfig } from 'wxt';
import VueRouter from 'unplugin-vue-router/vite';
@@ -47,8 +45,7 @@ export default defineConfig({
:::warning
Due to the way WXT orchestrates Vite builds, some plugins may not work as expected. For example, `vite-plugin-remove-console` normally only runs when you build for production (`vite build`). However, WXT uses a combination of dev server and builds during development, so you need to manually tell it when to run:
```ts
// wxt.config.ts
```ts [wxt.config.ts]
import { defineConfig } from 'wxt';
import removeConsole from 'vite-plugin-remove-console';
+160 -36
View File
@@ -4,12 +4,14 @@ outline: deep
# Content Scripts
> To create a content script, see [Entrypoint Types](/guide/essentials/entrypoints#content-scripts).
## Context
The first argument to a content script's `main` function is it's "context".
The first argument to a content script's `main` function is its "context".
```ts
// entrypoints/content.ts
// entrypoints/example.content.ts
export default defineContentScript({
main(ctx) {},
});
@@ -17,7 +19,7 @@ export default defineContentScript({
This object is responsible for tracking whether or not the content script's context is "invalidated". Most browsers, by default, do not stop content scripts if the extension is uninstalled, updated, or disabled. When this happens, content scripts start reporting this error:
```
```plaintext
Error: Extension context invalidated.
```
@@ -62,7 +64,7 @@ In regular web extensions, CSS for content scripts is usually a separate CSS fil
In WXT, to add CSS to a content script, simply import the CSS file into your JS entrypoint, and WXT will automatically add the bundled CSS output to the `css` array.
```ts
// entrypoints/content/index.ts
// entrypoints/example.content/index.ts
import './style.css';
export default defineContentScript({
@@ -74,20 +76,20 @@ To create a standalone content script that only includes a CSS file:
1. Create the CSS file: `entrypoints/example.content.css`
2. Use the `build:manifestGenerated` hook to add the content script to the manifest:
```ts
// wxt.config.ts
```ts [wxt.config.ts]
export default defineConfig({
hooks: {
"build:manifestGenerated": (wxt, manifest) => {
'build:manifestGenerated': (wxt, manifest) => {
manifest.content_scripts ??= [];
manifest.content_scripts.push({
// Build extension once to see where your CSS get's written to
css: ["content-scripts/example.css"],
matches: ["*://*/*"]
)
}
}
})
css: ['content-scripts/example.css'],
matches: ['*://*/*'],
});
},
},
});
```
## UI
@@ -198,6 +200,7 @@ export default defineContentScript({
```ts [Svelte]
// entrypoints/example-ui.content/index.ts
import App from './App.svelte';
import { mount, unmount } from 'svelte';
export default defineContentScript({
matches: ['<all_urls>'],
@@ -208,14 +211,11 @@ export default defineContentScript({
anchor: 'body',
onMount: (container) => {
// Create the Svelte app inside the UI container
const app = new App({
target: container,
});
return app;
return mount(App, { target: container });
},
onRemove: (app) => {
// Destroy the app when the UI is removed
app.$destroy();
unmount(app);
},
});
@@ -239,6 +239,7 @@ export default defineContentScript({
onMount: (container) => {
// Render your app to the UI container
const unmount = render(() => <div>...</div>, container);
return unmount;
},
onRemove: (unmount) => {
// Unmount the app when the UI is removed
@@ -254,13 +255,13 @@ export default defineContentScript({
:::
See the [API Reference](/api/reference/wxt/client/functions/createIntegratedUi) for the complete list of options.
See the [API Reference](/api/reference/wxt/utils/content-script-ui/integrated/functions/createIntegratedUi) for the complete list of options.
### Shadow Root
Often in web extensions, you don't want your content script's CSS affecting the page, or vise-versa. The [`ShadowRoot`](https://developer.mozilla.org/en-US/docs/Web/API/ShadowRoot) API is ideal for this.
WXT's [`createShadowRootUi`](/api/reference/wxt/client/functions/createShadowRootUi) abstracts all the `ShadowRoot` setup away, making it easy to create UIs whose styles are isolated from the page. It also supports an optional `isolateEvents` parameter to further isolate user interactions.
WXT's [`createShadowRootUi`](/api/reference/wxt/utils/content-script-ui/shadow-root/functions/createShadowRootUi) abstracts all the `ShadowRoot` setup away, making it easy to create UIs whose styles are isolated from the page. It also supports an optional `isolateEvents` parameter to further isolate user interactions.
To use `createShadowRootUi`, follow these steps:
@@ -378,6 +379,7 @@ export default defineContentScript({
// 1. Import the style
import './style.css';
import App from './App.svelte';
import { mount, unmount } from 'svelte';
export default defineContentScript({
matches: ['<all_urls>'],
@@ -392,14 +394,11 @@ export default defineContentScript({
anchor: 'body',
onMount: (container) => {
// Create the Svelte app inside the UI container
const app = new App({
target: container,
});
return app;
return mount(App, { target: container });
},
onRemove: (app) => {
// Destroy the app when the UI is removed
app?.$destroy();
unmount(app);
},
});
@@ -443,7 +442,7 @@ export default defineContentScript({
:::
See the [API Reference](/api/reference/wxt/client/functions/createShadowRootUi) for the complete list of options.
See the [API Reference](/api/reference/wxt/utils/content-script-ui/shadow-root/functions/createShadowRootUi) for the complete list of options.
Full examples:
@@ -454,9 +453,10 @@ Full examples:
If you don't need to run your UI in the same frame as the content script, you can use an IFrame to host your UI instead. Since an IFrame just hosts an HTML page, **_HMR is supported_**.
WXT provides a helper function, [`createIframeUi`](/api/reference/wxt/client/functions/createIframeUi), which simplifies setting up the IFrame.
WXT provides a helper function, [`createIframeUi`](/api/reference/wxt/utils/content-script-ui/iframe/functions/createIframeUi), which simplifies setting up the IFrame.
1. Create an HTML page that will be loaded into your IFrame:
```html
<!-- entrypoints/example-iframe.html -->
<!doctype html>
@@ -471,9 +471,10 @@ WXT provides a helper function, [`createIframeUi`](/api/reference/wxt/client/fun
</body>
</html>
```
1. Add the page to the manifest's `web_accessible_resources`:
```ts
// wxt.config.ts
```ts [wxt.config.ts]
export default defineConfig({
manifest: {
web_accessible_resources: [
@@ -485,6 +486,7 @@ WXT provides a helper function, [`createIframeUi`](/api/reference/wxt/client/fun
},
});
```
1. Create and mount the IFrame:
```ts
@@ -509,7 +511,7 @@ WXT provides a helper function, [`createIframeUi`](/api/reference/wxt/client/fun
});
```
See the [API Reference](/api/reference/wxt/client/functions/createIframeUi) for the complete list of options.
See the [API Reference](/api/reference/wxt/utils/content-script-ui/iframe/functions/createIframeUi) for the complete list of options.
## Isolated World vs Main World
@@ -547,16 +549,35 @@ To use `injectScript`, we need two entrypoints, one content script and one unlis
```ts
// entrypoints/example-main-world.ts
export default defineUnlistedScript(() => {
console.log('Hello from the main world!');
console.log('Hello from the main world');
});
```
```ts
// entrypoints/example.content.ts
export default defineContentScript(async () => {
await injectScript('/example-main-world.js', {
keepInDom: true,
});
export default defineContentScript({
matches: ['*://*/*'],
async main() {
console.log('Injecting script...');
await injectScript('/example-main-world.js', {
keepInDom: true,
});
console.log('Done!');
},
});
```
```json
export default defineConfig({
manifest: {
// ...
web_accessible_resources: [
{
resources: ["example-main-world.js"],
matches: ["*://*/*"],
}
]
}
});
```
@@ -570,6 +591,109 @@ For MV3, `injectScript` is synchronous and the injected script will be evaluated
However for MV2, `injectScript` has to `fetch` the script's text content and create an inline `<script>` block. This means for MV2, your script is injected asynchronously and it will not be evaluated at the same time as your content script's `run_at`.
:::
The `script` element can be modified just before it is added to the DOM by using the `modifyScript` option. This can be used to e.g. modify `script.async`/`script.defer`, add event listeners to the element, or pass data to the script via `script.dataset`. An example:
```ts
// entrypoints/example.content.ts
export default defineContentScript({
matches: ['*://*/*'],
async main() {
await injectScript('/example-main-world.js', {
modifyScript(script) {
script.dataset['greeting'] = 'Hello there';
},
});
},
});
```
```ts
// entrypoints/example-main-world.ts
export default defineUnlistedScript(() => {
console.log(document.currentScript?.dataset['greeting']);
});
```
`injectScript` returns the created script element. It can be used to e.g. send messages to the script in the form of custom events. The script can add an event listener for them via `document.currentScript`. An example of bidirectional communication:
```ts
// entrypoints/example.content.ts
export default defineContentScript({
matches: ['*://*/*'],
async main() {
const { script } = await injectScript('/example-main-world.js', {
modifyScript(script) {
// Add a listener before the injected script is loaded.
script.addEventListener('from-injected-script', (event) => {
if (event instanceof CustomEvent) {
console.log(`${event.type}:`, event.detail);
}
});
},
});
// Send an event after the injected script is loaded.
script.dispatchEvent(
new CustomEvent('from-content-script', {
detail: 'General Kenobi',
}),
);
},
});
```
```ts
// entrypoints/example-main-world.ts
export default defineUnlistedScript(() => {
const script = document.currentScript;
script?.addEventListener('from-content-script', (event) => {
if (event instanceof CustomEvent) {
console.log(`${event.type}:`, event.detail);
}
});
script?.dispatchEvent(
new CustomEvent('from-injected-script', {
detail: 'Hello there',
}),
);
});
```
## Mounting UI to dynamic element
In many cases, you may need to mount a UI to a DOM element that does not exist at the time the web page is initially loaded. To handle this, use the `autoMount` API to automatically mount the UI when the target element appears dynamically and unmount it when the element disappears. In WXT, the `anchor` option is used to target the element, enabling automatic mounting and unmounting based on its appearance and removal.
```ts
export default defineContentScript({
matches: ['<all_urls>'],
main(ctx) {
const ui = createIntegratedUi(ctx, {
position: 'inline',
// It observes the anchor
anchor: '#your-target-dynamic-element',
onMount: (container) => {
// Append children to the container
const app = document.createElement('p');
app.textContent = '...';
container.append(app);
},
});
// Call autoMount to observe anchor element for add/remove.
ui.autoMount();
},
});
```
:::tip
When the `ui.remove` is called, `autoMount` also stops.
:::
See the [API Reference](/api/reference/wxt/utils/content-script-ui/types/interfaces/ContentScriptUi#automount) for the complete list of options.
## Dealing with SPAs
It is difficult to write content scripts for SPAs (single page applications) and websites using HTML5 history mode for navigation because content scripts are only ran on full page reloads. SPAs and websites that take advantage of HTML5 history mode **_do not perform a full reload when changing paths_**, and thus your content script isn't going to be ran when you expect it to be.
@@ -602,7 +726,7 @@ export default defineContentScript({
matches: ['*://*.youtube.com/*'],
main(ctx) {
ctx.addEventListener(window, 'wxt:locationchange', ({ newUrl }) => {
if (watchPattern.matches(newUrl)) mainWatch(ctx);
if (watchPattern.includes(newUrl)) mainWatch(ctx);
});
},
});
+234 -77
View File
@@ -4,50 +4,30 @@ outline: deep
# Entrypoints
WXT uses the files inside the `entrypoints/` directory as inputs when bundling your extension. They can be HTML, JS, CSS, or any variant of those file types supported by Vite (Pug, TS, JSX, SCSS, etc).
WXT uses the files inside the `entrypoints/` directory as inputs when bundling your extension. They can be HTML, JS, CSS, or any variant of those file types supported by Vite (TS, JSX, SCSS, etc).
Here's an example set of entrypoints:
## Folder Structure
Inside the `entrypoints/` directory, an entrypoint is defined as a single file or directory (with an `index` file) inside it.
:::code-group
<!-- prettier-ignore -->
```html
```html [Single File]
📂 entrypoints/
📂 popup/
📄 index.html
📄 main.ts
📄 style.css
📄 background.ts
📄 content.ts
📄 {name}.{ext}
```
[[toc]]
<!-- prettier-ignore -->
```html [Directory]
📂 entrypoints/
📂 {name}/
📄 index.{ext}
```
## Listed vs Unlisted
For web extensions, there are two types of entrypoints:
- **Listed**: Referenced in the `manifest.json`
- **Unlisted**: Not referenced in the `manifest.json`
Throughout the rest of WXT's documentation, listed files are referred to by name. For example:
- Popup
- Options
- Background
- Content Scripts
- Etc.
Some examples of "unlisted" entrypoints:
- A welcome page shown when the extension is installed
- JS files injected by content scripts into the page's main world
:::tip
Regardless of whether a entrypoint is listed or unlisted, it will still be bundled into your extension and be available at runtime.
:::
## Adding Entrypoints
An entrypoint can be defined as a single file or directory with an `index` file inside it.
The entrypoint's `name` dictates the type of entrypoint. For example, to add a ["Background" entrypoint](#background), either of these files would work:
:::code-group
@@ -66,18 +46,103 @@ An entrypoint can be defined as a single file or directory with an `index` file
:::
The entrypoint's name dictates the type of entrypoint, listed vs unlisted. In this example, "background" is the name of the ["Background" entrypoint](#background).
Refer to the [Entrypoint Types](#entrypoint-types) section for the full list of listed entrypoints and their filename patterns.
### Including Other Files
When using an entrypoint directory, `entrypoints/{name}/index.{ext}`, you can add related files next to the `index` file.
<!-- prettier-ignore -->
```html
📂 entrypoints/
📂 popup/
📄 index.html ← This file is the entrypoint
📄 main.ts
📄 style.css
📂 background/
📄 index.ts ← This file is the entrypoint
📄 alarms.ts
📄 messaging.ts
📂 youtube.content/
📄 index.ts ← This file is the entrypoint
📄 style.css
```
:::danger
**DO NOT** put files related to an entrypoint directly inside the `entrypoints/` directory. WXT will treat them as entrypoints and try to build them, usually resulting in an error.
Instead, use a directory for that entrypoint:
<!-- prettier-ignore -->
```html
📂 entrypoints/
📄 popup.html <!-- [!code --] -->
📄 popup.ts <!-- [!code --] -->
📄 popup.css <!-- [!code --] -->
📂 popup/ <!-- [!code ++] -->
📄 index.html <!-- [!code ++] -->
📄 main.ts <!-- [!code ++] -->
📄 style.css <!-- [!code ++] -->
```
:::
### Deeply Nested Entrypoints
While the `entrypoints/` directory might resemble the `pages/` directory of other web frameworks, like Nuxt or Next.js, **it does not support deeply nesting entrypoints** in the same way.
Entrypoints must be zero or one levels deep for WXT to discover and build them:
<!-- prettier-ignore -->
```html
📂 entrypoints/
📂 youtube/ <!-- [!code --] -->
📂 content/ <!-- [!code --] -->
📄 index.ts <!-- [!code --] -->
📄 ... <!-- [!code --] -->
📂 injected/ <!-- [!code --] -->
📄 index.ts <!-- [!code --] -->
📄 ... <!-- [!code --] -->
📂 youtube.content/ <!-- [!code ++] -->
📄 index.ts <!-- [!code ++] -->
📄 ... <!-- [!code ++] -->
📂 youtube-injected/ <!-- [!code ++] -->
📄 index.ts <!-- [!code ++] -->
📄 ... <!-- [!code ++] -->
```
## Unlisted Entrypoints
In web extensions, there are two types of entrypoints:
1. **Listed**: Referenced in the `manifest.json`
2. **Unlisted**: Not referenced in the `manifest.json`
Throughout the rest of WXT's documentation, listed entrypoints are referred to by name. For example:
- Popup
- Options
- Background
- Content Script
However, not all entrypoints in web extensions are listed in the manifest. Some are not listed in the manifest, but are still used by extensions. For example:
- A welcome page shown in a new tab when the extension is installed
- JS files injected by content scripts into the main world
For more details on how to add unlisted entrypoints, see:
- [Unlisted Pages](#unlisted-pages)
- [Unlisted Scripts](#unlisted-scripts)
- [Unlisted CSS](#unlisted-css)
## Defining Manifest Options
Most listed entrypoints have options that need to be added to the `manifest.json`. With WXT however, instead of defining the options in a separate file, _you define these options inside the entrypoint file itself_.
Most listed entrypoints have options that need to be added to the `manifest.json`. However with WXT, instead of defining the options in a separate file, _you define these options inside the entrypoint file itself_.
For example, here's how to define `matches` for content scripts:
```ts
// entrypoints/content.ts
```ts [entrypoints/content.ts]
export default defineContentScript({
matches: ['*://*.wxt.dev/*'],
main() {
@@ -86,6 +151,17 @@ export default defineContentScript({
});
```
For HTML entrypoints, options are configured as `<meta>` tags. For example, to use a `page_action` for your MV2 popup:
```html
<!doctype html>
<html lang="en">
<head>
<meta name="manifest.type" content="page_action" />
</head>
</html>
```
> Refer to the [Entrypoint Types](#entrypoint-types) sections for a list of options configurable inside each entrypoint, and how to define them.
When building your extension, WXT will look at the options defined in your entrypoints, and generate the manifest accordingly.
@@ -96,8 +172,6 @@ When building your extension, WXT will look at the options defined in your entry
[Chrome Docs](https://developer.chrome.com/docs/extensions/mv3/manifest/background/) &bull; [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/background)
For MV2, the background is added as a script to the background page. For MV3, the background becomes a service worker.
<EntrypointPatterns
:patterns="[
['background.[jt]s', 'background.js'],
@@ -131,6 +205,25 @@ export default defineBackground({
:::
For MV2, the background is added as a script to the background page. For MV3, the background becomes a service worker.
When defining your background entrypoint, keep in mind that WXT will import this file in a NodeJS environment during the build process. That means you cannot place any runtime code outside the `main` function.
<!-- prettier-ignore -->
```ts
browser.action.onClicked.addListener(() => { // [!code --]
// ... // [!code --]
}); // [!code --]
export default defineBackground(() => {
browser.action.onClicked.addListener(() => { // [!code ++]
// ... // [!code ++]
}); // [!code ++]
});
```
Refer to the [Entrypoint Loaders](/guide/essentials/config/entrypoint-loaders) documentation for more details.
### Bookmarks
[Chrome Docs](https://developer.chrome.com/docs/extensions/mv3/override/) &bull; [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/chrome_url_overrides)
@@ -159,18 +252,18 @@ export default defineBackground({
</html>
```
When you define a Bookmarks entrypoint, WXT will automatically update the manifest to override the browser's bookmarks page with your own HTML page.
### Content Scripts
[Chrome Docs](https://developer.chrome.com/docs/extensions/mv3/content_scripts/) &bull; [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Content_scripts)
See [Content Script UI](/guide/essentials/content-scripts) for more info on creating UIs and including CSS in content scripts.
<EntrypointPatterns
:patterns="[
['content.[jt]sx?', 'content-scripts/content.js'],
['content/index.[jt]sx?', 'content-scripts/content.js'],
['<name>.content.[jt]sx?', 'content-scripts/<name>.js'],
['<name>.content/index.[jt]sx?', 'content-scripts/<name>.js'],
['{name}.content.[jt]sx?', 'content-scripts/{name}.js'],
['{name}.content/index.[jt]sx?', 'content-scripts/{name}.js'],
]"
/>
@@ -203,12 +296,29 @@ export default defineContentScript({
});
```
When defining content script entrypoints, keep in mind that WXT will import this file in a NodeJS environment during the build process. That means you cannot place any runtime code outside the `main` function.
<!-- prettier-ignore -->
```ts
const container = document.createElement('div'); // [!code --]
document.body.append(container); // [!code --]
export default defineContentScript({
main: function () {
const container = document.createElement('div'); // [!code ++]
document.body.append(container); // [!code ++]
},
});
```
Refer to the [Entrypoint Loaders](/guide/essentials/config/entrypoint-loaders) documentation for more details.
See [Content Script UI](/guide/essentials/content-scripts) for more info on creating UIs and including CSS in content scripts.
### Devtools
[Chrome Docs](https://developer.chrome.com/docs/extensions/mv3/devtools/) &bull; [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/devtools_page)
Follow the [Devtools Example](https://github.com/wxt-dev/examples/tree/main/examples/devtools-extension#readme) to add different panels and panes.
<EntrypointPatterns
:patterns="[
['devtools.html', 'devtools.html'],
@@ -232,6 +342,8 @@ Follow the [Devtools Example](https://github.com/wxt-dev/examples/tree/main/exam
</html>
```
Follow the [Devtools Example](https://github.com/wxt-dev/examples/tree/main/examples/devtools-extension#readme) to add different panels and panes.
### History
[Chrome Docs](https://developer.chrome.com/docs/extensions/mv3/override/) &bull; [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/chrome_url_overrides)
@@ -260,6 +372,8 @@ Follow the [Devtools Example](https://github.com/wxt-dev/examples/tree/main/exam
</html>
```
When you define a History entrypoint, WXT will automatically update the manifest to override the browser's history page with your own HTML page.
### Newtab
[Chrome Docs](https://developer.chrome.com/docs/extensions/mv3/override/) &bull; [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/chrome_url_overrides)
@@ -288,6 +402,8 @@ Follow the [Devtools Example](https://github.com/wxt-dev/examples/tree/main/exam
</html>
```
When you define a Newtab entrypoint, WXT will automatically update the manifest to override the browser's new tab page with your own HTML page.
### Options
[Chrome Docs](https://developer.chrome.com/docs/extensions/mv3/options/) &bull; [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/options_ui)
@@ -304,14 +420,14 @@ Follow the [Devtools Example](https://github.com/wxt-dev/examples/tree/main/exam
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewportYou are responsible for loading/running these scripts where needed. If necessary, don't forget to add the script and/or any related stylesheets to web_accessible_resources."
content="width=device-width, initial-scale=1.0"
/>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Options Title</title>
<!-- Customize the manifest options -->
<meta name="manifest.open_in_tab" content="true|false" />
<meta name="manifest.chrome_style" content="true|false" />
<meta name="manifest.browser_style" content="true|false" />
<!-- Set include/exclude if the page should be removed from some builds -->
<meta name="manifest.include" content="['chrome', ...]" />
<meta name="manifest.exclude" content="['chrome', ...]" />
@@ -339,7 +455,11 @@ Follow the [Devtools Example](https://github.com/wxt-dev/examples/tree/main/exam
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- Set the `action.default_title` in the manifest -->
<title>Default Popup Title</title>
<!-- Customize the manifest options -->
<meta
name="manifest.default_icon"
content="{
@@ -350,6 +470,20 @@ Follow the [Devtools Example](https://github.com/wxt-dev/examples/tree/main/exam
/>
<meta name="manifest.type" content="page_action|browser_action" />
<meta name="manifest.browser_style" content="true|false" />
<!-- Firefox only: where to place the action button -->
<meta
name="manifest.default_area"
content="navbar|menupanel|tabstrip|personaltoolbar"
/>
<!-- Firefox only: icons for light/dark themes -->
<meta
name="manifest.theme_icons"
content="[
{ light: '/icon-light-16.png', dark: '/icon-dark-16.png', size: 16 },
{ light: '/icon-light-32.png', dark: '/icon-dark-32.png', size: 32 }
]"
/>
<!-- Set include/exclude if the page should be removed from some builds -->
<meta name="manifest.include" content="['chrome', ...]" />
<meta name="manifest.exclude" content="['chrome', ...]" />
@@ -372,8 +506,8 @@ Firefox does not support sandboxed pages.
:patterns="[
['sandbox.html', 'sandbox.html'],
['sandbox/index.html', 'sandbox.html'],
['<name>.sandbox.html', '<name>.html'],
['<name>.sandbox/index.html', '<name>.html'],
['{name}.sandbox.html', '{name}.html'],
['{name}.sandbox/index.html', '{name}.html'],
]"
/>
@@ -384,6 +518,7 @@ Firefox does not support sandboxed pages.
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Title</title>
<!-- Set include/exclude if the page should be removed from some builds -->
<meta name="manifest.include" content="['chrome', ...]" />
<meta name="manifest.exclude" content="['chrome', ...]" />
@@ -398,14 +533,12 @@ Firefox does not support sandboxed pages.
[Chrome Docs](https://developer.chrome.com/docs/extensions/reference/sidePanel/) &bull; [Firefox Docs](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/user_interface/Sidebars)
In Chrome, side panels use the `side_panel` API, while Firefox uses the `sidebar_action` API.
<EntrypointPatterns
:patterns="[
['sidepanel.html', 'sidepanel.html'],
['sidepanel/index.html', 'sidepanel.html'],
['<name>.sidepanel.html', '<name>.html` '],
['<name>.sidepanel/index.html', '<name>.html` '],
['{name}.sidepanel.html', '{name}.html` '],
['{name}.sidepanel/index.html', '{name}.html` '],
]"
/>
@@ -416,6 +549,8 @@ In Chrome, side panels use the `side_panel` API, while Firefox uses the `sidebar
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Default Side Panel Title</title>
<!-- Customize the manifest options -->
<meta
name="manifest.default_icon"
content="{
@@ -426,6 +561,7 @@ In Chrome, side panels use the `side_panel` API, while Firefox uses the `sidebar
/>
<meta name="manifest.open_at_install" content="true|false" />
<meta name="manifest.browser_style" content="true|false" />
<!-- Set include/exclude if the page should be removed from some builds -->
<meta name="manifest.include" content="['chrome', ...]" />
<meta name="manifest.exclude" content="['chrome', ...]" />
@@ -436,20 +572,18 @@ In Chrome, side panels use the `side_panel` API, while Firefox uses the `sidebar
</html>
```
In Chrome, side panels use the `side_panel` API, while Firefox uses the `sidebar_action` API.
### Unlisted CSS
Follow Vite's guide to setup your preprocessor of choice: https://vitejs.dev/guide/features.html#css-pre-processors
CSS entrypoints are always unlisted. To add CSS to a content script, see the [Content Script](/guide/essentials/content-scripts#css) docs.
<EntrypointPatterns
:patterns="[
['<name>.(css|scss|sass|less|styl|stylus)', '<name>.css'],
['<name>/index.(css|scss|sass|less|styl|stylus)', '<name>.css'],
['{name}.(css|scss|sass|less|styl|stylus)', '{name}.css'],
['{name}/index.(css|scss|sass|less|styl|stylus)', '{name}.css'],
['content.(css|scss|sass|less|styl|stylus)', 'content-scripts/content.css'],
['content/index.(css|scss|sass|less|styl|stylus)', 'content-scripts/content.css'],
['<name>.content.(css|scss|sass|less|styl|stylus)', 'content-scripts/<name>.css'],
['<name>.content/index.(css|scss|sass|less|styl|stylus)', 'content-scripts/<name>.css'],
['{name}.content.(css|scss|sass|less|styl|stylus)', 'content-scripts/{name}.css'],
['{name}.content/index.(css|scss|sass|less|styl|stylus)', 'content-scripts/{name}.css'],
]"
/>
@@ -459,12 +593,16 @@ body {
}
```
Follow Vite's guide to setup your preprocessor of choice: <https://vitejs.dev/guide/features.html#css-pre-processors>
CSS entrypoints are always unlisted. To add CSS to a content script, see the [Content Script](/guide/essentials/content-scripts#css) docs.
### Unlisted Pages
<EntrypointPatterns
:patterns="[
['<name>.html', '<name>.html'],
['<name>/index.html', '<name>.html'],
['{name}.html', '{name}.html'],
['{name}/index.html', '{name}.html'],
]"
/>
@@ -475,6 +613,7 @@ body {
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Title</title>
<!-- Set include/exclude if the page should be removed from some builds -->
<meta name="manifest.include" content="['chrome', ...]" />
<meta name="manifest.exclude" content="['chrome', ...]" />
@@ -485,20 +624,21 @@ body {
</html>
```
Pages are accessible at `/<name>.html`:
At runtime, unlisted pages are accessible at `/{name}.html`:
```ts
const url = browser.runtime.getURL('/<name>.html');
const url = browser.runtime.getURL('/{name}.html');
console.log(url); // "chrome-extension://<id>/<name>.html"
console.log(url); // "chrome-extension://{id}/{name}.html"
window.open(url); // Open the page in a new tab
```
### Unlisted Scripts
<EntrypointPatterns
:patterns="[
['<name>.[jt]sx?', '<name>.js'],
['<name>/index.[jt]sx?', '<name>.js'],
['{name}.[jt]sx?', '{name}.js'],
['{name}/index.[jt]sx?', '{name}.js'],
]"
/>
@@ -524,12 +664,29 @@ export default defineUnlistedScript({
:::
Scripts are accessible from `/<name>.js`:
At runtime, unlisted scripts are accessible from `/{name}.js`:
```ts
const url = browser.runtime.getURL('/<name>.js');
const url = browser.runtime.getURL('/{name}.js');
console.log(url); // "chrome-extension://<id>/<name>.js"
console.log(url); // "chrome-extension://{id}/{name}.js"
```
You are responsible for loading/running these scripts where needed. If necessary, don't forget to add the script and/or any related stylesheets to [`web_accessible_resources`](https://developer.chrome.com/docs/extensions/reference/manifest/web-accessible-resources).
You are responsible for loading/running these scripts where needed. If necessary, don't forget to add the script and/or any related assets to [`web_accessible_resources`](https://developer.chrome.com/docs/extensions/reference/manifest/web-accessible-resources).
When defining an unlisted script, keep in mind that WXT will import this file in a NodeJS environment during the build process. That means you cannot place any runtime code outside the `main` function.
<!-- prettier-ignore -->
```ts
document.querySelectorAll('a').forEach((anchor) => { // [!code --]
// ... // [!code --]
}); // [!code --]
export default defineUnlistedScript(() => {
document.querySelectorAll('a').forEach((anchor) => { // [!code ++]
// ... // [!code ++]
}); // [!code ++]
});
```
Refer to the [Entrypoint Loaders](/guide/essentials/config/entrypoint-loaders) documentation for more details.
+8 -8
View File
@@ -1,12 +1,10 @@
# ES Modules
Currently, ESM entrypoints are opt-in, so you must configure each entrypoint with that in mind.
Your source code should always be written as ESM. However, you have some control whether an entrypoint is bundled as ESM.
## HTML Pages <Badge type="warning" text="≥0.0.1" />
In general, you should always make HTML pages import ESM scripts, unless you need to support old browsers.
To make a script ESM, add `type="module"`:
Vite only supports bundling JS from HTML pages as ESM. Ensure you have added `type="module"` to your `<script>` tags:
<!-- prettier-ignore -->
```html
@@ -16,23 +14,25 @@ To make a script ESM, add `type="module"`:
## Background <Badge type="warning" text="≥0.16.0" />
In your background script, set `type: "module"`:
By default, your background will be bundled into a single file as IIFE. You can change this by setting `type: "module"` in your background entrypoint:
```ts
export default defineBackground({
type: 'module', // !code ++
type: 'module', // [!code ++]
main() {
// ...
},
});
```
This will change the output format to ESM, enable code-splitting between your background script and HTML pages, and set `"type": "module"` in your manifest.
:::warning
Only MV3 supports ESM background scripts/service workers. When targeting MV2, the `type` option is ignored and the background is always bundled into a single file as IIFE.
:::
## Content Scripts
WXT does not yet include built-in support for ESM content scripts. The plan is to add support for chunking to reduce bundle size, but not support HMR for now. There are several technical issues that make implementing a generic solution for HMR impossible. See [Content Script ESM Support #357](https://github.com/wxt-dev/wxt/issues/357) for details.
WXT does not yet include built-in support for bundling content scripts as ESM. The plan is to add support for chunking to reduce bundle size, but not support HMR for now. There are several technical issues that make implementing a generic solution for HMR impossible. See [Content Script ESM Support #357](https://github.com/wxt-dev/wxt/issues/357) for details.
If you can't wait, and need ESM support right now, you can implement ESM support manually. See the [ESM Content Script UI](https://github.com/wxt-dev/examples/tree/main/examples/esm-content-script-ui) example to get started.
If you can't wait, and need ESM support right now, you can implement ESM support manually. See the [ESM Content Script UI](https://github.com/wxt-dev/examples/tree/main/examples/esm-content-script-ui) example to learn how.
+100 -33
View File
@@ -4,62 +4,47 @@
Different browsers provide different global variables for accessing the extension APIs (chrome provides `chrome`, firefox provides `browser`, etc).
WXT simplifies this - always use `browser`:
WXT merges these two into a unified API accessed through the `browser` variable.
```ts
import { browser } from 'wxt/browser';
browser.action.onClicked.addListener(() => {
// ...
});
```
Other than that, refer to Chrome and Mozilla's documentation for how to use specific APIs. Everything a normal extension can do, WXT can do as well, just via `browser` instead of `chrome`.
:::tip
With auto-imports enabled, you don't even need to import this variable from `wxt/browser`!
:::
## Webextension Polyfill
The `browser` variable WXT provides is a simple export of the `browser` or `chrome` globals provided by the browser at runtime:
> Since `v0.1.0`
<<< @/../packages/browser/src/index.mjs#snippet
By default, WXT uses the [`webextension-polyfill` by Mozilla](https://www.npmjs.com/package/webextension-polyfill) to make the extension API consistent between browsers.
This means you can use the promise-style API for both MV2 and MV3, and it will work across all browsers (Chromium, Firefox, Safari, etc).
To access types, you should import the relevant namespace from `wxt/browser`:
## Accessing Types
All types can be accessed via WXT's `Browser` namespace:
```ts
import { Runtime } from 'wxt/browser';
import { type Browser } from 'wxt/browser';
function handleMessage(message: any, sender: Runtime.Sender) {
function handleMessage(message: any, sender: Browser.runtime.MessageSender) {
// ...
}
```
### Disabling the polyfill
## Using `webextension-polyfill`
> Since `v0.19.0`
If you want to use the `webextension-polyfill` when importing `browser`, you can do so by installing the `@wxt-dev/webextension-polyfill` package.
After the release of MV3 and Chrome's official deprecation of MV2 in June 2024, the polyfill isn't really doing anything useful anymore.
You can disable it with a single line:
```ts
// wxt.config.ts
export default defineConfig({
extensionApi: 'chrome',
});
```
This will change `wxt/browser` to simply export the `browser` or `chrome` globals based on browser at runtime:
<<< @/../packages/wxt/src/browser/chrome.ts#snippet
Accessing types is a little different with the polyfill disabled. They do not need to be imported; they're available on the `browser` object itself:
```ts
function handleMessage(message: any, sender: browser.runtime.Sender) {
// ...
}
```
See it's [Installation Guide](https://github.com/wxt-dev/wxt/blob/main/packages/webextension-polyfill/README.md) to get started.
## Feature Detection
Depending on the manifest version and browser, some APIs are not available at runtime. If an API is not available, it will be `undefined`.
Depending on the manifest version, browser, and permissions, some APIs are not available at runtime. If an API is not available, it will be `undefined`.
:::warning
Types will not help you here. The types WXT provides for `browser` assume all APIs exist. You are responsible for knowing whether an API is available or not.
@@ -90,3 +75,85 @@ Alternatively, if you're trying to use similar APIs under different names (to su
//
});
```
### Augmenting the Browser Type
WXT's `browser` types are based on the `@types/chrome` package. That means some Firefox-specific APIs may not be typed, like `browser.sidebarAction`. If you want to add types for these APIs, you can augment the browser type to add them yourself:
```ts
// <srcDir>/browser-types.d.ts
import '@wxt-dev/browser';
import type { SidebarAction } from 'webextension-polyfill';
declare module '@wxt-dev/browser' {
namespace Browser {
export const sidebarAction: SidebarAction.Static;
}
}
```
> For this to work, you may need to install `@wxt-dev/browser` as a direct dependency.
>
> ```sh
> pnpm add @wxt-dev/browser
> ```
## Entrypoint Limitations
Because WXT imports your entrypoint files into a NodeJS, non-extension environment, the `chrome`/`browser` variables provided to extensions by the browser **will not be available**.
To prevent some basic errors, WXT polyfills these globals with the same in-memory, fake implementation it uses for testing: [`@webext-core/fake-browser`](https://webext-core.aklinker1.io/fake-browser/installation/). However, not all the APIs have been implemented.
So it is extremely important to NEVER use `browser.*` extension APIs outside the main function of any JS/TS entrypoints (background, content scripts, and unlisted scripts). If you do, you'll see an error like this:
```plaintext
✖ Command failed after 440 ms
ERROR Browser.action.onClicked.addListener not implemented.
```
The fix is simple, just move your API usage into the entrypoint's main function:
:::code-group
```ts [background.ts]
browser.action.onClicked.addListener(() => {
/* ... */
}); // [!code --]
export default defineBackground(() => {
browser.action.onClicked.addListener(() => {
/* ... */
}); // [!code ++]
});
```
```ts [content.ts]
browser.runtime.onMessage.addListener(() => {
/* ... */
}); // [!code --]
export default defineContentScript({
main() {
browser.runtime.onMessage.addListener(() => {
/* ... */
}); // [!code ++]
},
});
```
```ts [unlisted.ts]
browser.runtime.onMessage.addListener(() => {
/* ... */
}); // [!code --]
export default defineUnlistedScript(() => {
browser.runtime.onMessage.addListener(() => {
/* ... */
}); // [!code ++]
});
```
:::
Read [Entrypoint Loaders](/guide/essentials/config/entrypoint-loaders) for more technical details about this limitation.
+51
View File
@@ -0,0 +1,51 @@
# Favicons
[Chrome Docs](https://developer.chrome.com/docs/extensions/how-to/ui/favicons)
Chromium-based browsers expose cached favicons through the `_favicon/` URL served from your extension. To use it, declare the `favicon` permission in your manifest and call `browser.runtime.getURL` with a `_favicon/` path:
```ts
// wxt.config.ts
import { defineConfig } from 'wxt';
export default defineConfig({
manifest: {
permissions: ['favicon'],
},
});
```
```ts
// Any entrypoint
function getFaviconUrl(pageUrl: string, size = 16) {
const url = new URL(browser.runtime.getURL('/_favicon/'));
url.searchParams.set('pageUrl', pageUrl);
url.searchParams.set('size', String(size));
return url.toString();
}
```
::: warning Chromium only
The favicon API is only available on Chromium-based browsers. Firefox has no equivalent, so `/_favicon/` URLs will not resolve at runtime there. If your extension supports both browsers, gate favicon usage behind `import.meta.env.CHROME` (or similar) and declare the permission per-browser.
:::
## Usage from a content script
WXT does **not** add a `web_accessible_resources` entry for `_favicon/*` — not every extension needs one, and adding it unconditionally would expose internals to sites that don't need them. If you want to load a favicon inside a content script (for example, as an `<img src>`), add your own entry in `wxt.config.ts`:
```ts
// wxt.config.ts
import { defineConfig } from 'wxt';
export default defineConfig({
manifest: {
permissions: ['favicon'],
web_accessible_resources: [
{
resources: ['_favicon/*'],
matches: ['<all_urls>'],
},
],
},
});
```
+9 -1
View File
@@ -9,6 +9,7 @@ This page discusses how to setup internationalization using the vanilla `browser
## Usage
1. Add `default_locale` to your manifest:
```ts
export default defineConfig({
manifest: {
@@ -16,11 +17,12 @@ This page discusses how to setup internationalization using the vanilla `browser
},
});
```
2. Create `messages.json` files in the `public/` directory:
<!-- prettier-ignore -->
```html
📂 {srcDir}/
📂 {rootDir}/
📂 public/
📂 _locales/
📂 en/
@@ -41,9 +43,11 @@ This page discusses how to setup internationalization using the vanilla `browser
```
3. Get the translation:
```ts
browser.i18n.getMessage('helloWorld');
```
4. _Optional_: Add translations for extension name and description:
```json
@@ -81,6 +85,10 @@ However, it is recommended you stick with the vanilla API (or a package based on
- Translations are not bundled multiple times, keeping your extension small
- Zero configuration
However, there is one major downside to the vanilla API and any packages built on top of it:
- Language cannot be changed without changing your browser/system language
Here are some examples of how to setup a third party i18n library:
- [vue-i18n](https://github.com/wxt-dev/wxt-examples/tree/main/examples/vue-i18n)
+1
View File
@@ -14,3 +14,4 @@ Here are some popular messaging libraries that support all browsers and work wit
- [`webext-bridge`](https://www.npmjs.com/package/webext-bridge) - Messaging in WebExtensions made super easy. Out of the box.
- [`@webext-core/messaging`](https://www.npmjs.com/package/@webext-core/messaging) - Light weight, type-safe wrapper around the web extension messaging APIs
- [`@webext-core/proxy-service`](https://www.npmjs.com/package/@webext-core/proxy-service) - A type-safe wrapper around the web extension messaging APIs that lets you call a function from anywhere, but execute it in the background.
- [`Comctx`](https://github.com/molvqingtai/comctx) - Cross-context RPC solution with type safety and flexible adapters.
+24 -25
View File
@@ -30,12 +30,13 @@ Here's a brief summary of each of these files and directories:
- `.wxt/`: Generated by WXT, it contains TS config
- `assets/`: Contains all CSS, images, and other assets that should be processed by WXT
- `components/`: Auto-imported by default, contains UI components
- `composables/`: Auto-imported by default, contains composable functions for Vue
- `composables/`: Auto-imported by default, contains source code for your project's composable functions for Vue
- `entrypoints/`: Contains all the entrypoints that get bundled into your extension
- `hooks/`: Auto-imported by default, contains hooks for React and Solid
- `hooks/`: Auto-imported by default, contains source code for your project's hooks for React and Solid
- `modules/`: Contains [local WXT Modules](/guide/essentials/wxt-modules) for your project
- `public/`: Contains any files you want to copy into the output folder as-is, without being processed by WXT
- `utils/`: Auto-imported by default, contains generic utilities used throughout your project
- `.env`: Contains [Environment Variables](/guide/essentials/config/runtime#environment-variables)
- `.env`: Contains [Environment Variables](/guide/essentials/config/environment-variables)
- `.env.publish`: Contains Environment Variables for [publishing](/guide/essentials/publishing)
- `app.config.ts`: Contains [Runtime Config](/guide/essentials/config/runtime)
- `package.json`: The standard file used by your package manager
@@ -47,8 +48,7 @@ Here's a brief summary of each of these files and directories:
Many developers like having a `src/` directory to separate source code from configuration files. You can enable it inside the `wxt.config.ts` file:
```ts
// wxt.config.ts
```ts [wxt.config.ts]
export default defineConfig({
srcDir: 'src',
});
@@ -59,24 +59,24 @@ After enabling it, your project structure should look like this:
<!-- prettier-ignore -->
```html
📂 {rootDir}/
📁 .output/
📁 .wxt/
📂 src/
📁 assets/
📁 components/
📁 composables/
📁 entrypoints/
📁 hooks/
📁 .output/
📁 .wxt/
📁 modules/
📁 public/
📁 utils/
📄 app.config.ts
📄 .env
📄 .env.publish
📄 package.json
📄 tsconfig.json
📄 web-ext.config.ts
📄 wxt.config.ts
📂 src/
📁 assets/
📁 components/
📁 composables/
📁 entrypoints/
📁 hooks/
📁 utils/
📄 app.config.ts
📄 .env
📄 .env.publish
📄 package.json
📄 tsconfig.json
📄 web-ext.config.ts
📄 wxt.config.ts
```
## Customizing Other Directories
@@ -84,17 +84,16 @@ After enabling it, your project structure should look like this:
You can configure the following directories:
<!-- prettier-ignore -->
```ts
// wxt.config.ts
```ts [wxt.config.ts]
export default defineConfig({
// Relative to project root
srcDir: "src", // default: "."
modulesDir: "wxt-modules", // default: "modules"
outDir: "dist", // default: ".output"
publicDir: "static", // default: "public"
// Relative to srcDir
entrypointsDir: "entries", // default: "entrypoints"
modulesDir: "wxt-modules", // default: "modules"
publicDir: "static", // default: "public"
})
```
+8 -10
View File
@@ -23,7 +23,7 @@ WXT provides two commands to help automate submitting a new version for review a
- `wxt submit init`: Setup all the required secrets and options for the `wxt submit` command
- `wxt submit`: Submit new versions of your extension for review (and publish them automatically once approved)
To get started, run `wxt submit init` and follow the prompts. Once finished, you should have a `.env.submit` file! WXT will use this file to submit your updates.
To get started, run `wxt submit init` and follow the prompts, or run `wxt submit --help` to view all available options. Once finished, you should have a `.env.submit` file! WXT will use this file to submit your updates.
> In CI, make sure you add all the environment variables to the submit step.
@@ -72,13 +72,13 @@ jobs:
submit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v5
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
node-version: 20
node-version: 22
cache: 'pnpm'
- name: Install dependencies
@@ -129,12 +129,11 @@ wxt zip
Firefox requires you to upload a ZIP of your source code. This allows them to rebuild your extension and review the code in a readable way. More details can be found in [Firefox's docs](https://extensionworkshop.com/documentation/publish/source-code-submission/).
When running `wxt zip -b firefox`, WXT will zip both your extension and sources. Certain files (such as config files, hidden files, and tests) are automatically excluded from your sources. However, it's important to manually check the ZIP to ensure it only contains the files necessary to rebuild your extension.
When running `wxt zip -b firefox`, WXT will zip both your extension and sources. Certain files (such as config files, hidden files, tests, and excluded entrypoints) are automatically excluded from your sources. However, it's important to manually check the ZIP to ensure it only contains the files necessary to rebuild your extension.
To customize which files are zipped, add the `zip` option to your config file.
```ts
// wxt.config.ts
```ts [wxt.config.ts]
import { defineConfig } from 'wxt';
export default defineConfig({
@@ -164,8 +163,8 @@ yarn zip:firefox
```
```sh [bun]
bun i
bun zip:firefox
bun install
bun run zip:firefox
```
:::
@@ -184,8 +183,7 @@ See Issue [#377](https://github.com/wxt-dev/wxt/issues/377) for more details.
If you use private packages and you don't want to provide your auth token to the Firefox team during the review process, you can use `zip.downloadPackages` to download any private packages and include them in the zip.
```ts
// wxt.config.ts
```ts [wxt.config.ts]
export default defineConfig({
zip: {
downloadPackages: [
+8 -5
View File
@@ -12,15 +12,18 @@ When using `browser.scripting.executeScript`, you can execute content scripts or
// entrypoints/background.ts
const res = await browser.scripting.executeScript({
target: { tabId },
files: ['injected.js'],
files: ['content-scripts/example.js'],
});
console.log(res); // "Hello John!"
```
```ts
// entrypoints/injected.js
export default defineUnlistedScript(() => {
console.log('Script was injected!');
return 'Hello John!';
// entrypoints/example.content.ts
export default defineContentScript({
registration: 'runtime',
main(ctx) {
console.log('Script was executed!');
return 'Hello John!';
},
});
```
+1 -1
View File
@@ -6,7 +6,7 @@ You can use the vanilla APIs (see docs above), use [WXT's built-in storage API](
## Alternatives
1. [`wxt/storage`](/storage) (recommended): WXT ships with its own wrapper around the vanilla storage APIs that simplifies common use cases
1. [`wxt/utils/storage`](/storage) (recommended): WXT ships with its own wrapper around the vanilla storage APIs that simplifies common use cases
2. DIY: If you're migrating to WXT and already have a storage wrapper, keep using it. In the future, if you want to delete that code, you can use one of these alternatives, but there's no reason to replace working code during a migration.
@@ -62,6 +62,7 @@ Here are some examples:
```
- HTML file only built for all targets other than `chrome`:
```html
<!doctype html>
<html lang="en">
@@ -75,3 +76,5 @@ Here are some examples:
</body>
</html>
```
Alternatively, you can use the [`filterEntrypoints` config](/api/reference/wxt/interfaces/InlineConfig#filterentrypoints) to list all the entrypoints you want to build.
+32 -4
View File
@@ -9,7 +9,7 @@ WXT provides first class support for Vitest for unit testing:
```ts
// vitest.config.ts
import { defineConfig } from 'vitest/config';
import { WxtVitest } from 'wxt/testing';
import { WxtVitest } from 'wxt/testing/vitest-plugin';
export default defineConfig({
plugins: [WxtVitest()],
@@ -32,11 +32,11 @@ Here are real projects with unit testing setup. Look at the code and tests to se
### Example Tests
This example demonstrates that you don't have to mock `browser.storage` (used by `wxt/storage`) in tests - [`@webext-core/fake-browser`](https://webext-core.aklinker1.io/fake-browser/installation) implements storage in-memory so it behaves like it would in a real extension!
This example demonstrates that you don't have to mock `browser.storage` (used by `wxt/utils/storage`) in tests - [`@webext-core/fake-browser`](https://webext-core.aklinker1.io/fake-browser/installation) implements storage in-memory so it behaves like it would in a real extension!
```ts
import { describe, it, expect } from 'vitest';
import { fakeBrowser } from 'wxt/testing';
import { fakeBrowser } from 'wxt/testing/fake-browser';
const accountStorage = storage.defineItem<Account>('local:account');
@@ -71,10 +71,38 @@ describe('isLoggedIn', () => {
});
```
### Mocking WXT APIs
First, you need to understand how the `#imports` module works. When WXT (and vitest) sees this import during a preprocessing step, the import is replaced with multiple imports pointing to their "real" import path.
For example, this is what your write in your source code:
```ts
// What you write
import { injectScript, createShadowRootUi } from '#imports';
```
But Vitest sees this:
```ts
import { injectScript } from 'wxt/utils/inject-script';
import { createShadowRootUi } from 'wxt/utils/content-script-ui/shadow-root';
```
So in this case, if you wanted to mock `injectScript`, you need to pass in `"wxt/utils/inject-script"`, not `"#imports"`.
```ts
vi.mock("wxt/utils/inject-script", () => ({
injectScript: ...
}))
```
Refer to your project's `.wxt/types/imports-module.d.ts` file to lookup real import paths for `#imports`. If the file doesn't exist, run [`wxt prepare`](/guide/essentials/config/typescript).
## Other Testing Frameworks
To use a different framework, you will likely have to disable auto-imports, setup import aliases, manually mock the extension APIs, and setup the test environment to support all of WXT's features that you use.
It is possible to do, but will require a bit more setup. Refer to Vitest's setup for an example of how to setup a test environment:
https://github.com/wxt-dev/wxt/blob/main/packages/wxt/src/testing/wxt-vitest-plugin.ts
<https://github.com/wxt-dev/wxt/blob/main/packages/wxt/src/testing/wxt-vitest-plugin.ts>
+106 -25
View File
@@ -1,28 +1,24 @@
---
outline: deep
---
# WXT Modules
WXT provides a "module system" that let's you run code at different steps in the build process to modify it.
WXT provides a "module system" that lets you run code at different steps in the build process to modify it.
[[toc]]
## Adding a Module
## Installing a Module
There are two ways to add a module to your project:
To use a published module from NPM, install the package and add it to your config:
1. **NPM**: install an NPM package, like [`@wxt-dev/auto-icons`](https://www.npmjs.com/package/@wxt-dev/auto-icons) and add it to your config:
```ts
// wxt.config.ts
export default defineConfig({
modules: ['@wxt-dev/auto-icons'],
});
```
> Searching for ["wxt module"](https://www.npmjs.com/search?q=wxt%20module) on NPM is a good way to find published WXT modules.
2. **Local**: add a file to your project's `modules/` directory:
```
<srcDir>/
modules/
my-module.ts
```
> To learn more about writing your own modules, read the [Writing Modules](/guide/essentials/wxt-modules) docs.
```ts [wxt.config.ts]
export default defineConfig({
modules: ['@wxt-dev/auto-icons'],
});
```
> Searching for ["wxt module"](https://www.npmjs.com/search?q=wxt%20module) on NPM is a good way to find published WXT modules.
## Module Options
@@ -41,7 +37,7 @@ Modules are loaded in the same order as hooks are executed. Refer to the [Hooks
## Writing Modules
Here's what a basic WXT module looks like:
If you need custom build logic for your project, you can write your own local module. Here's what a basic WXT module looks like:
```ts
import { defineWxtModule } from 'wxt/modules';
@@ -53,6 +49,14 @@ export default defineWxtModule({
});
```
To add it to your project, place the file in the `modules/` directory at the root of your project. Any module file in this directory is **automatically discovered and loaded** — no additional configuration is needed:
```plaintext
<rootDir>/
modules/
my-module.ts ← loaded automatically
```
Each module's setup function is executed after the `wxt.config.ts` file is loaded. The `wxt` object provides everything you need to write a module:
- Use `wxt.hook(...)` to hook into the build's lifecycle and make changes
@@ -62,7 +66,7 @@ Each module's setup function is executed after the `wxt.config.ts` file is loade
Refer to the [API reference](/api/reference/wxt/interfaces/Wxt) for a complete list of properties and functions available.
Also to make sure and read about all the [hooks that are available](https://wxt.dev/api/reference/wxt/interfaces/WxtHooks) - they are essential to writing modules.
Also make sure to read about [all the hooks that are available](/api/reference/wxt/interfaces/WxtHooks) - they are essential to writing modules.
### Recipes
@@ -75,7 +79,7 @@ import { defineWxtModule } from 'wxt/modules';
export default defineWxtModule({
setup(wxt) {
wxt.hook('ready', () => {
wxt.hook('config:resolved', () => {
wxt.config.outDir = 'dist';
});
},
@@ -112,12 +116,12 @@ export default defineWxtModule<AnalyticModuleOptions>({
```ts
import { defineWxtModule } from 'wxt/modules';
import 'wxt/sandbox';
import 'wxt/utils/define-app-config';
export interface MyModuleRuntimeOptions {
// Add your runtime options here...
}
declare module 'wxt/sandbox' {
declare module 'wxt/utils/define-app-config' {
export interface WxtAppConfig {
myModule: MyModuleOptions;
}
@@ -127,12 +131,64 @@ declare module 'wxt/sandbox' {
Runtime options are returned when calling
```ts
const config = useAppConfig();
const config = getAppConfig();
console.log(config.myModule);
```
This is very useful when [generating runtime code](#generate-runtime-module).
#### Add custom entrypoint options
Modules can add custom options to entrypoints by augmenting the entrypoint options types. This allows you to add custom configuration that can be accessed during the build process.
```ts
import { defineWxtModule } from 'wxt/modules';
import 'wxt';
declare module 'wxt' {
export interface BackgroundEntrypointOptions {
// Add custom options to the background entrypoint
myCustomOption?: string;
}
}
export default defineWxtModule({
setup(wxt) {
wxt.hook('entrypoints:resolved', (_, entrypoints) => {
const background = entrypoints.find((e) => e.type === 'background');
if (background) {
console.log('Custom option:', background.options.myCustomOption);
}
});
},
});
```
Now users can set the custom option in their entrypoint:
```ts [entrypoints/background.ts]
export default defineBackground({
myCustomOption: 'custom value',
main() {
// ...
},
});
```
This works for all other JS and HTML entrypoints, here's an example of how to pass a custom option from an HTML file.
```html [entrypoints/popup.html]
<html>
<head>
<meta name="wxt.myHtmlOption" content="custom value" />
<title>Popup</title>
</head>
<body>
<!-- ... -->
</body>
</html>
```
#### Generate output file
```ts
@@ -167,6 +223,31 @@ This file could then be loaded at runtime:
const res = await fetch(browser.runtime.getURL('/some-text.txt'));
```
#### Add custom entrypoints
Once the existing files under the `entrypoints/` directory have been discovered, the `entrypoints:found` hook can be used to add custom entrypoints.
:::info
The `entrypoints:found` hook is triggered before validation is carried out on the list of entrypoints. Thus, any custom entrypoints will still be checked for duplicate names and logged during debugging.
:::
```ts
import { defineWxtModule } from 'wxt/modules';
export default defineWxtModule({
setup(wxt) {
wxt.hook('entrypoints:found', (_, entrypointInfos) => {
// Add your new entrypoint
entrypointInfos.push({
name: 'my-custom-script',
inputPath: 'path/to/custom-script.js',
type: 'content-script',
});
});
},
});
```
#### Generate runtime module
Create a file in `.wxt`, add an alias to import it, and add auto-imports for exported variables.
@@ -191,7 +272,7 @@ export default defineWxtModule({
const analyticsModuleCode = `
import { createAnalytics } from 'some-module';
export const analytics = createAnalytics(useAppConfig().analytics);
export const analytics = createAnalytics(getAppConfig().analytics);
export const { reportEvent, reportPageView } = analytics;
`;
+25 -2
View File
@@ -45,48 +45,64 @@ Once you've run the `dev` command, continue to [Next Steps](#next-steps)!
1. Create a new project
:::code-group
```sh [PNPM]
cd my-project
pnpm init
```
```sh [Bun]
cd my-project
bun init
```
```sh [NPM]
cd my-project
npm init
```
```sh [Yarn]
cd my-project
yarn init
```
:::
2. Install WXT:
:::code-group
```sh [PNPM]
pnpm i -D wxt
```
```sh [Bun]
bun i -D wxt
bun add -D wxt
```
```sh [NPM]
npm i -D wxt
```
```sh [Yarn]
yarn add --dev wxt
```
:::
3. Add an entrypoint, `my-project/entrypoints/background.ts`:
:::code-group
```ts
export default defineBackground(() => {
console.log('Hello world!');
});
```
:::
4. Add scripts to your `package.json`:
```json
```json [package.json]
{
"scripts": {
"dev": "wxt", // [!code ++]
@@ -99,20 +115,26 @@ Once you've run the `dev` command, continue to [Next Steps](#next-steps)!
}
}
```
5. Run your extension in dev mode
:::code-group
```sh [PNPM]
pnpm dev
```
```sh [Bun]
bun run dev
```
```sh [NPM]
npm run dev
```
```sh [Yarn]
yarn dev
```
:::
WXT will automatically open a browser window with your extension installed.
@@ -121,3 +143,4 @@ Once you've run the `dev` command, continue to [Next Steps](#next-steps)!
- Keep reading on about WXT's [Project Structure](/guide/essentials/project-structure) and other essential concepts to learn
- Configure [automatic browser startup](/guide/essentials/config/browser-startup) during dev mode
- Explore [WXT's example library](/examples) to see how to use specific APIs or perform common tasks
- Checkout the [community page](/guide/resources/community) for a list of resources made by the community!
+3 -3
View File
@@ -1,15 +1,15 @@
# Welcome to WXT!
# Welcome to WXT
WXT is a modern, open-source framework for building web extensions. Inspired by Nuxt, its goals are to:
- Provide an awesome [DX](https://about.gitlab.com/topics/devops/what-is-developer-experience/)
- Provide first-class support for all major browsers
Check out the [comparison](/guide/resources/compare) to see how WXT compares to other tools for building web extnesions.
Check out the [comparison](/guide/resources/compare) to see how WXT compares to other tools for building web extensions.
## Prerequisites
These docs assume you have a basic knowledge of how Chrome extensions are structured and how you access the extension APIs.
These docs assume you have a basic knowledge of how web extensions are structured and how you access the extension APIs.
:::warning New to extension development?
If you have never written an extension before, follow Chrome's [Hello World tutorial](https://developer.chrome.com/docs/extensions/get-started/tutorial/hello-world) to first **_create an extension without WXT_**, then come back here.
+16
View File
@@ -0,0 +1,16 @@
# Community
This page is dedicated to all the awesome people how have made something for WXT or that works with WXT. Blog posts, YouTube videos, NPM packages, etc. If a section doesn't exist for the thing you made, add one!
[[toc]]
## Blog Posts
- [Building Modern Cross Browser Web Extensions](https://aabidk.dev/tags/wxt/) by Aabid ([@aabidk20](https://github.com/aabidk20))
- [Building Browser Extensions with WXT](https://rxliuli.com/blog/browser-extension-dev-01-introduction-to-basic-concepts/) by rxliuli ([@rxliuli](https://github.com/rxliuli))
## NPM Packages
- [`@webext-core/*`](https://webext-core.aklinker1.io/): Easy-to-use utilities for writing and testing web extensions that work on all browsers.
- [`Comctx`](https://github.com/molvqingtai/comctx): Cross-context RPC solution with type safety and flexible adapters.
- [`wxt-local-analytics`](https://github.com/HaNdTriX/wxt-local-analytics): Local analytics provider for [`@wxt-dev/analytics`](https://wxt.dev/analytics)
+60 -46
View File
@@ -8,50 +8,64 @@ Lets compare the features of WXT vs [Plasmo](https://docs.plasmo.com/framework)
- 🟡 - Partial support
- ❌ - No support
| Features | WXT | Plasmo | CRXJS |
| ------------------------------------------------------- | :--------------: | :-------------: | :--------------: |
| Supports all browsers | | | 🟡 <sup>10</sup> |
| MV2 Support | | ✅ | 🟡 <sup>1</sup> |
| MV3 Support | ✅ | ✅ | 🟡 <sup>1</sup> |
| Create Extension ZIPs | ✅ | ✅ | ❌ |
| Create Firefox Sources ZIP | | ❌ | ❌ |
| First-class TypeScript support | | ✅ | |
| Entrypoint discovery | ✅ <sup>2</sup> | ✅ <sup>2</sup> | |
| Inline entrypoint config | ✅ | ✅ |<sup>9</sup> |
| Auto-imports | ✅ | ❌ | |
| Reusable module system | ✅ | ❌ | |
| Supports all frontend frameworks | ✅ | 🟡 <sup>3</sup> | |
| Framework specific entrypoints (like `Popup.tsx`) | 🟡 <sup>4</sup> | ✅ <sup>5</sup> | |
| Automated publishing | ✅ | ✅ | ❌ |
| Remote Code Bundling (Google Analytics) | ✅ | ✅ | |
| Unlisted HTML Pages | | ✅ | ✅ |
| Unlisted Scripts | | ❌ | ❌ |
| ESM Content Scripts | ❌ <sup>12</sup> | ❌ | |
| <strong style="opacity: 50%">Dev Mode</strong> | | |
| `.env` Files | | ✅ | ✅ |
| Opens browser with extension installed | | | |
| HMR for UIs | ✅ | 🟡 <sup>6</sup> | |
| Reload HTML Files on Change | | 🟡 <sup>7</sup> | ✅ |
| Reload Content Scripts on Change | | 🟡 <sup>7</sup> | ✅ |
| Reload Background on Change | 🟡 <sup>7</sup> | 🟡 <sup>7</sup> | 🟡 <sup>7</sup> |
| Respects Content Script `run_at` | | ✅ | ❌ <sup>8</sup> |
| <strong style="opacity: 50%">Built-in Wrappers</strong> | | | |
| Storage | | ✅ | ❌ <sup>11</sup> |
| Messaging | ❌ <sup>11</sup> | | ❌ <sup>11</sup> |
| Content Script UI | ✅ | ✅ | ❌ <sup>11</sup> |
| I18n | | ❌ | ❌ |
| Features | WXT | Plasmo | CRXJS |
| ------------------------------------------------------- | :-----: | :-----: | :-----: |
| Maintained || 🟡 [^n] | 🟡 [^m] |
| Supports all browsers | ✅ | ✅ | 🟡 [^j] |
| MV2 Support | ✅ | ✅ | 🟡 [^a] |
| MV3 Support | ✅ | ✅ | 🟡 [^a] |
| Create Extension ZIPs | | ✅ | ❌ |
| Create Firefox Sources ZIP | ✅ | | |
| First-class TypeScript support | ✅ | | |
| Entrypoint discovery | ✅ [^b] | ✅ [^b] | |
| Inline entrypoint config | ✅ | ✅ | ❌ [^i] |
| Auto-imports | ✅ | | |
| Reusable module system | ✅ | | ❌ |
| Supports all frontend frameworks | | 🟡 [^c] | |
| Framework specific entrypoints (like `Popup.tsx`) | 🟡 [^d] | ✅ [^e] | ❌ |
| Automated publishing | ✅ | | |
| Remote Code Bundling (Google Analytics) | | ✅ | ❌ |
| Unlisted HTML Pages | | ✅ | ✅ |
| Unlisted Scripts | ✅ | | |
| ESM Content Scripts | ❌ [^l] | | |
| <strong style="opacity: 50%">Dev Mode</strong> | | | |
| `.env` Files | | | |
| Opens browser with extension installed | ✅ | | |
| HMR for UIs | ✅ | 🟡 [^f] | |
| Reload HTML Files on Change | ✅ | 🟡 [^g] | ✅ |
| Reload Content Scripts on Change | ✅ | 🟡 [^g] | ✅ |
| Reload Background on Change | 🟡 [^g] | 🟡 [^g] | 🟡 [^g] |
| Respects Content Script `run_at` | | | ❌ [^h] |
| <strong style="opacity: 50%">Built-in Wrappers</strong> | | | |
| Storage | | | ❌ [^k] |
| Messaging | ❌ [^k] | ✅ | ❌ [^k] |
| Content Script UI | | ✅ | ❌ [^k] |
| I18n | ✅ | ❌ | ❌ |
<small>
<sup>1</sup>: Either MV2 or MV3, not both.
<br/><sup>2</sup>: File based.
<br/><sup>3</sup>: Only React, Vue, and Svelte.
<br/><sup>4</sup>: <code>.html</code> <code>.ts</code> <code>.tsx</code>.
<br/><sup>5</sup>: <code>.html</code> <code>.ts</code> <code>.tsx</code>. <code>.vue</code> <code>.svelte</code>.
<br/><sup>6</sup>: React only.
<br/><sup>7</sup>: Reloads entire extension.
<br/><sup>8</sup>: ESM-style loaders run asynchronously.
<br/><sup>9</sup>: Entrypoint options all configured in <code>manifest.json</code>.
<br/><sup>10</sup>: As of <code>v2.0.0-beta.23</code>, but v2 stable hasn't been released yet.
<br/><sup>11</sup>: There is no built-in wrapper around this API. However, you can still access the standard APIs via <code>chrome</code>/<code>browser</code> globals or use any 3rd party NPM package.
<br/><sup>12</sup>: WIP, moving very slowly. Follow <a href="https://github.com/wxt-dev/wxt/issues/357" target="_blank"><code>wxt-dev/wxt#357</code></a> for updates.
</small>
[^a]: Either MV2 or MV3, not both.
[^b]: File based.
[^c]: Only React, Vue, and Svelte.
[^d]: `.html`, `.ts`, `.tsx`.
[^e]: `.html`, `.ts`, `.tsx`, `.vue`, `.svelte`.
[^f]: React only.
[^g]: Reloads entire extension.
[^h]: ESM-style loaders run asynchronously.
[^i]: Entrypoint options all configured in `manifest.json`.
[^j]: As of `v2.0.0-beta.23`, but v2 stable hasn't been released yet.
[^k]: There is no built-in wrapper around this API. However, you can still access the standard APIs via `chrome`/`browser` globals or use any 3rd party NPM package.
[^l]: WIP, moving very slowly. Follow [wxt-dev/wxt#357](https://github.com/wxt-dev/wxt/issues/357) for updates.
[^m]: See [crxjs/chrome-extension-tools#974](https://github.com/crxjs/chrome-extension-tools/discussions/974)
[^n]: Appears to be in maintenance mode with little to no maintainers nor feature development happening and _(see [wxt-dev/wxt#1404 (comment)](https://github.com/wxt-dev/wxt/pull/1404#issuecomment-2643089518))_
+204 -3
View File
@@ -8,9 +8,7 @@ Commonly asked questions about how to use WXT or why it behaves the way it does.
[[toc]]
---
### Why are content scripts not showing up in the manifest?
## Why aren't content scripts added to the manifest?
During development, WXT registers content scripts dynamically so they can be reloaded individually when a file is saved without reloading your entire extension.
@@ -19,3 +17,206 @@ To list the content scripts registered during development, open the service work
```js
await chrome.scripting.getRegisteredContentScripts();
```
## How do I disable opening the browser automatically during development?
See <https://wxt.dev/guide/essentials/config/browser-startup.html#disable-opening-browser>
## How do I stay logged into a website during development?
See <https://wxt.dev/guide/essentials/config/browser-startup.html#persist-data>
## My component library doesn't work in content scripts
This is usually caused by one of two things (or both) when using `createShadowRootUi`:
1. Styles are added outside the `ShadowRoot`
:::details
Some component libraries manually add CSS to the page by adding a `<style>` or `<link>` element. They place this element in the document's `<head>` by default. This causes your styles to be placed outside the `ShadowRoot` and it's isolation blocks the styles from being applied to your UI.
When a library does this, **you need to tell the library where to put its styles**. Here's the documentation for a few popular component libraries:
- Ant Design: [`StyleProvider`](https://ant.design/docs/react/compatible-style#shadow-dom-usage)
- Mantine: [`MantineProvider#getRootElement` and `MantineProvider#cssVariablesSelector`](https://mantine.dev/theming/mantine-provider/)
> If your library isn't listed above, try searching it's docs/issues for "shadow root", "shadow dom", or "css container". Not all libraries support shadow DOMs, you may have to open an issue to request this feature.
Here's an example of configuring Antd's styles:
```tsx
import { StyleProvider } from '@ant-design/cssinjs';
import ReactDOM from 'react-dom/client';
import App from './App.tsx';
const ui = await create`ShadowRoot`Ui(ctx, {
// ...
onMount: (container, shadow) => {
const cssContainer = shadow.querySelector('head')!;
const root = ReactDOM.createRoot(container);
root.render(
<StyleProvider container={cssContainer}>
<App />
</StyleProvider>,
);
return root;
},
});
```
:::
2. UI elements are added outside the `ShadowRoot`
::::::details
This is mostly caused by `Teleport` or `Portal` components that render an element somewhere else in the DOM, usually in the document's `<body>`. This is usually done for dialogs or popover components. This renders the element is outside the `ShadowRoot`, so styles are not applied to it.
To fix this, **you need to both provide a target to your app AND pass the target to the `Teleport`/`Portal`**.
First, store the reference to the `ShadowRoot`'s `<body>` element (not the document's `<body>`):
:::code-group
```ts [Vue]
import { createApp } from 'vue';
import App from './App.vue';
const ui = await create`ShadowRoot`Ui(ctx, {
// ...
onMount: (container, shadow) => {
const teleportTarget = shadow.querySelector('body')!;
const app = createApp(App)
.provide('TeleportTarget', teleportTarget)
.mount(container);
return app;
},
});
ui.mount();
```
```tsx [React]
// hooks/PortalTargetContext.ts
import { createContext } from 'react';
export const PortalTargetContext = createContext<HTMLElement>();
// entrypoints/example.content.ts
import ReactDOM from 'react-dom/client';
import App from './App.tsx';
import PortalTargetContext from '~/hooks/PortalTargetContext';
const ui = await create`ShadowRoot`Ui(ctx, {
// ...
onMount: (container, shadow) => {
const portalTarget = shadow.querySelector('body')!;
const root = ReactDOM.createRoot(container);
root.render(
<PortalTargetContext.Provider value={portalTarget}>
<App />
</PortalTargetContext.Provider>,
);
return root;
},
});
ui.mount();
```
:::
Then use the reference when teleporting/portaling part of your UI to a different place in the DOM:
:::code-group
```vue [Vue]
<script lang="ts" setup>
import { Teleport } from 'vue';
const teleportTarget = inject('TeleportTarget');
</script>
<template>
<div>
<Teleport :to="teleportTarget">
<dialog>My dialog</dialog>
</Teleport>
</div>
</template>
```
```tsx [React]
import { useContext } from 'react';
import { createPortal } from 'react-dom';
import PortalTargetContext from '~/hooks/PortalTargetContext';
const MyComponent = () => {
const portalTarget = useContext(PortalTargetContext);
return <div>{createPortal(<dialog>My dialog</dialog>, portalTarget)}</div>;
};
```
:::
If you use ShadCN, [see this blog post](https://aabidk.dev/blog/building-modern-cross-browser-web-extensions-content-scripts-and-ui/#using-radixui-portals-to-move-the-dialog-to-shadow-dom).
::::::
Both issues have the same cause: the library puts something outside the `ShadowRoot`, and the `ShadowRoot`'s isolation prevents CSS from being applied to your UI.
Both issues have the same fix: tell the library to put elements inside the `ShadowRoot`, not outside it. See the details above for more information and example fixes for each problem.
## Does WXT provide docs for LLMs?
Yes, WXT's documentation provides markdown files based on the [the /llms.txt proposal](https://llmstxt.org/).
## Is there an LLM trained on WXT's docs that I chat with?
Yes! There's a "Ask AI" button in the bottom right of the page, try it out! Or visit <https://knowledge.wxt.dev/> for a fullscreen experience.
Additionally, if you want to train your own model or provide context to your editor, you can use the LLM knowledge files hosted by the site:
<https://wxt.dev/knowledge/index.json>
You don't need to crawl the entire website, these files already contain all the relevant docs for training a LLM on WXT. But feel free to crawl it and generate your own files if you want!
## How do I run my WXT project with docker / [devcontainers](https://containers.dev)?
To run the WXT dev server in a devcontainer, but load the dev build of your extension in your browser:
1. **Bind-mount your project directory to your host**
If you're using VS Code, you can open your project folder with the `Dev Containers: Open Folder in Container...` command. This keeps the folder synchronized between your host and the devcontainer, ensuring that the extension `dist` directory remains accessible from the host.
2. **Disable auto-opening the browser**
WXT automatically opens your browser during development, but since you're running inside a container, it won't be able to access it. Follow [the guide here](https://wxt.dev/guide/essentials/config/browser-startup.html#disable-opening-browser) to disable browser auto-opening in your `wxt.config.ts`.
3. **Tell WXT to listen on all network interfaces**
To enable hot-reloading, your extension has to connect to the WXT dev server running inside your container. WXT will only listen on `localhost` by default, which prevents connections from outside the devcontainer. To fix this you can instruct WXT to listen on all interfaces with `wxt --host 0.0.0.0`.
## How do I use the new Prompt API in Chrome?
The service responsible for the [Prompt API](https://developer.chrome.com/docs/ai/prompt-api) is not enabled by default if you let WXT open the browser during dev mode. When checking `LanguageModel.availability`, you will always receive "unavailable".
You have two options:
1. Pass the `--disable-features=DisableLoadExtensionCommandLineSwitch` feature flag to enable the service in the browser WXT opens:
```ts
// wxt.config.ts
export default defineConfig({
webExt: {
chromiumArgs: [
'--disable-features=DisableLoadExtensionCommandLineSwitch',
],
},
});
```
2. Disable the runner and install your extension in your regular chrome profile manually:
```ts
// wxt.config.ts
export default defineConfig({
webExt: {
disabled: true,
},
});
```
+27 -4
View File
@@ -15,10 +15,15 @@ cd path/to/your/project
pnpm dlx wxt@latest init example-wxt --template vanilla
```
:::tip
We recommend reviewing [project structure](/guide/essentials/project-structure.md) before you get started.
You can customize directory names in `wxt.config.ts` to match your project's needs.
:::
In general, you'll need to:
&ensp;<input type="checkbox" /> Install `wxt`<br />
&ensp;<input type="checkbox" /> [Extend `.wxt/tsconfig.json`](/guide/essentials/config/typescript.html#typescript-configuration) in your project's `tsconfig.json`<br />
&ensp;<input type="checkbox" /> [Extend `.wxt/tsconfig.json`](/guide/essentials/config/typescript#typescript-configuration) in your project's `tsconfig.json`<br />
&ensp;<input type="checkbox" /> Update/create `package.json` scripts to use `wxt` (don't forget about `postinstall`)<br />
&ensp;<input type="checkbox" /> Move entrypoints into `entrypoints/` directory<br />
&ensp;<input type="checkbox" /> Move assets into either the `assets/` or `public/` directories<br />
@@ -26,7 +31,7 @@ In general, you'll need to:
&ensp;<input type="checkbox" /> Convert custom import syntax to be compatible with Vite<br />
&ensp;<input type="checkbox" /> Add a default export to JS entrypoints (`defineBackground`, `defineContentScript`, or `defineUnlistedScript`)<br />
&ensp;<input type="checkbox" /> Use the `browser` global instead of `chrome`<br />
&ensp;<input type="checkbox" /> Compare final `manifest.json` files, making sure permissions and host permissions are unchanged<br/>
&ensp;<input type="checkbox" /> ⚠️ Compare final `manifest.json` files, making sure permissions and host permissions are unchanged<br/>
:::warning
If your extension is already live on the Chrome Web Store, use [Google's update testing tool](https://github.com/GoogleChromeLabs/extension-update-testing-tool) to make sure no new permissions are being requested.
:::
@@ -48,7 +53,25 @@ Here's specific steps for other popular frameworks/build tools.
5. Convert Plasmo's custom import resolutions to Vite's
6. If importing remote code via a URL, add a `url:` prefix so it works with WXT
7. Replace your [Plasmo tags](https://docs.plasmo.com/framework/workflows/build#with-a-custom-tag) (`--tag`) with [WXT build modes](/guide/essentials/config/build-mode) (`--mode`)
8. Compare your output `manifest.json` files from before the migration to after the migration. They should have the same content. If not, tweak your entrypoints and config to get as close as possible.
8. ⚠️ Compare the old production manifest to `.output/*/manifest.json`. They should have the same content as before. If not, tweak your entrypoints and config until they are the same.
### CRXJS
If you used CRXJS's vite plugin, it's a simple refactor! The main difference between CRXJS and WXT is how the tools decide which entrypoints to build. CRXJS looks at your `manifest` (and vite config for "unlisted" entries), while WXT looks at files in the `entrypoints` directory.
To migrate:
1. Move all entrypoints into the `entrypoints` directory, refactoring to WXT's style (TS files have a default export).
2. Move [entrypoint specific options out of the manifest](/guide/essentials/entrypoints#defining-manifest-options) and into the entrypoint files themselves (like content script `matches` or `run_at`).
3. Move any other `manifest.json` options [into the `wxt.config.ts` file](/guide/essentials/config/manifest), like permissions.
4. For simplicity, you'll probably want to [disable auto-imports](/guide/essentials/config/auto-imports#disabling-auto-imports) at first (unless you were already using them via `unimport` or `unplugin-auto-imports`). If you like the feature, you can enable it later once you've finished the migration.
5. Update your `package.json` to include all of [WXT's suggested scripts (see step 4)](/guide/installation#from-scratch)
6. Specifically, make sure you add the `"postinstall": "wxt prepare"` script to your `package.json`.
7. Delete your `vite.config.ts` file. Move any plugins into the `wxt.config.ts` file. If you use a frontend framework, [install the relevant WXT module](/guide/essentials/frontend-frameworks).
8. Update your typescript project. [Extend WXT's generated config](/guide/essentials/config/typescript), and [add any path aliases to your `wxt.config.ts` file](/guide/essentials/config/typescript#tsconfig-paths).
9. ⚠️ Compare the old production manifest to `.output/*/manifest.json`. They should have the same content as before. If not, tweak your entrypoints and config until they are the same.
Here's an example migration: [GitHub Better Line Counts - CRXJS &rarr; WXT](https://github.com/aklinker1/github-better-line-counts/commit/39d766d2ba86866efefc2e9004af554ee434e2a8)
### `vite-plugin-web-extension`
@@ -60,4 +83,4 @@ Since you're already using Vite, it's a simple refactor.
4. Add `"postinstall": "wxt prepare"` script
5. Move the `manifest.json` into `wxt.config.ts`
6. Move any custom settings from `vite.config.ts` into `wxt.config.ts`'s
7. Compare `dist/manifest.json` to `.output/*/manifest.json`, they should have the same content as before. If not, tweak your entrypoints and config to get as close as possible.
7. ⚠️ Compare the old production manifest to `.output/*/manifest.json`. They should have the same content as before. If not, tweak your entrypoints and config until they are the same.
+302 -35
View File
@@ -1,17 +1,304 @@
---
outline: deep
---
# Upgrading WXT
## Overview
To upgrade WXT to the latest version... just install it!
To upgrade WXT to the latest major version:
1. Install it, skipping scripts so `wxt prepare` doesn't run - it will probably throw an error after a major version change (we'll run it later).
```sh
pnpm i wxt@latest --ignore-scripts
```
2. Follow the upgrade steps below to fix any breaking changes.
3. Run `wxt prepare`. It should succeed and type errors will go away afterwords.
```sh
pnpm wxt prepare
```
4. Manually test to make sure both dev mode and production builds work.
For minor or patch version updates, there are no special steps. Just update it with your package manager:
```sh
pnpm i wxt@latest
```
---
Listed below are all the breaking changes you should address when upgrading to a new version of WXT.
Currently, WXT is in pre-release. This means changes to the second digit, `v0.X`, are considered major and have breaking changes. Once v1 is released, only major version bumps will have breaking changes.
## v0.19.0 &rarr; v0.20.0
v0.20 is a big release! There are lots of breaking changes because this version is intended to be a release candidate for v1.0. If all goes well, v1.0 will be released with no additional breaking changes.
:::tip
Read through all the changes once before updating your code.
:::
### `webextension-polyfill` Removed
WXT's `browser` no longer uses the `webextension-polyfill`!
:::details Why?
See <https://github.com/wxt-dev/wxt/issues/784>
:::
To upgrade, you have two options:
1. **Stop using the polyfill**
- If you're already using `extensionApi: "chrome"`, then you're not using the polyfill and there is nothing to change!
- Otherwise there is only one change: `browser.runtime.onMessage` no longer supports using promises to return a response:
```ts
browser.runtime.onMessage.addListener(async () => { // [!code --]
const res = await someAsyncWork(); // [!code --]
return res; // [!code --]
browser.runtime.onMessage.addListener(async (_message, _sender, sendResponse) => { // [!code ++]
someAsyncWork().then((res) => { // [!code ++]
sendResponse(res); // [!code ++]
}); // [!code ++]
return true; // [!code ++]
});
```
2. **Continue using the polyfill** - If you want to keep using the polyfill, you can! One less thing to worry about during this upgrade.
- Install `webextension-polyfill` and WXT's [new polyfill module](https://www.npmjs.com/package/@wxt-dev/webextension-polyfill):
```sh
pnpm i webextension-polyfill @wxt-dev/webextension-polyfill
```
- Add the WXT module to your config:
```ts [wxt.config.ts]
export default defineConfig({
modules: ['@wxt-dev/webextension-polyfill'],
});
```
The new `browser` object (and types) is backed by WXT's new package: [`@wxt-dev/browser`](https://www.npmjs.com/package/@wxt-dev/browser). This package continues WXT's mission of providing useful packages for the whole community. Just like [`@wxt-dev/storage`](https://www.npmjs.com/package/@wxt-dev/storage), [`@wxt-dev/i18n`](https://www.npmjs.com/package/@wxt-dev/i18n), [`@wxt-dev/analytics`](https://www.npmjs.com/package/@wxt-dev/analytics), it is designed to be easy to use in any web extension project, not just those using WXT, and provides a consistent API across all browsers and manifest versions.
### `extensionApi` Config Removed
The `extensionApi` config has been removed. Before, this config provided a way to opt into using the new `browser` object prior to v0.20.0.
Remove it from your `wxt.config.ts` file if present:
```ts [wxt.config.ts]
export default defineConfig({
extensionApi: 'chrome', // [!code --]
});
```
### Extension API Type Changes
With the new `browser` introduced in v0.20, how you access types has changed. WXT now provides types based on `@types/chrome` instead of `@types/webextension-polyfill`.
These types are more up-to-date with MV3 APIs, contain less bugs, are better organized, and don't have any auto-generated names.
To access types, use the new `Browser` namespace from `wxt/browser`:
<!-- prettier-ignore -->
```ts
import type { Runtime } from 'wxt/browser'; // [!code --]
import type { Browser } from 'wxt/browser'; // [!code ++]
function getMessageSenderUrl(sender: Runtime.MessageSender): string { // [!code --]
function getMessageSenderUrl(sender: Browser.runtime.MessageSender): string { // [!code ++]
// ...
}
```
> If you use auto-imports, `Browser` will be available without manually importing it.
Not all type names will be the same as what `@types/webextension-polyfill` provides. You'll have to find the new type names by looking at the types of the `browser.*` API's you use.
### `public/` and `modules/` Directories Moved
The default location for the `public/` and `modules/` directories have changed to better align with standards set by other frameworks (Nuxt, Next, Astro, etc). Now, each path is relative to the project's **root directory**, not the src directory.
- If you follow the default folder structure, you don't need to make any changes.
- If you set a custom `srcDir`, you have two options:
1. Move the your `public/` and `modules/` directories to the project root:
<!-- prettier-ignore -->
```html
📂 {rootDir}/
📁 modules/ <!-- [!code ++] -->
📁 public/ <!-- [!code ++] -->
📂 src/
📁 components/
📁 entrypoints/
📁 modules/ <!-- [!code --] -->
📁 public/ <!-- [!code --] -->
📁 utils/
📄 app.config.ts
📄 wxt.config.ts
```
2. Keep the folders in the same place and update your project config:
```ts [wxt.config.ts]
export default defineConfig({
srcDir: 'src',
publicDir: 'src/public', // [!code ++]
modulesDir: 'src/modules', // [!code ++]
});
```
### Import Path Changes and `#imports`
The APIs exported by `wxt/sandbox`, `wxt/client`, or `wxt/storage` have moved to individual exports under the `wxt/utils/*` path.
:::details Why?
As WXT grows and more utilities are added, any helper with side-effects will not be tree-shaken out of your final bundle.
This can cause problems because not every API used by these side-effects is available in every type of entrypoint. Some APIs can only be used in the background, sandboxed pages can't use any extension API, etc. This was leading to JS throwing errors in the top-level scope, preventing your code from running.
Splitting each util into it's own module solves this problem, making sure you're only importing APIs and side-effects into entrypoints they can run in.
:::
Refer to the updated [API Reference](/api/reference/) to see the list of new import paths.
However, you don't need to memorize or learn the new import paths! v0.20 introduces a new virtual module, `#imports`, that abstracts all this away from developers. See the [blog post](/blog/2024-12-06-using-imports-module) for more details about how this module works.
So to upgrade, just replace any imports from `wxt/storage`, `wxt/client`, and `wxt/sandbox` with an import to the new `#imports` module:
```ts
import { storage } from 'wxt/storage'; // [!code --]
import { defineContentScript } from 'wxt/sandbox'; // [!code --]
import { ContentScriptContext, useAppConfig } from 'wxt/client'; // [!code --]
import { storage } from '#imports'; // [!code ++]
import { defineContentScript } from '#imports'; // [!code ++]
import { ContentScriptContext, getAppConfig } from '#imports'; // [!code ++]
```
You can combine the imports into a single import statement, but it's easier to just find/replace each statement.
```ts
import { storage } from 'wxt/storage'; // [!code --]
import { defineContentScript } from 'wxt/sandbox'; // [!code --]
import { ContentScriptContext, useAppConfig } from 'wxt/client'; // [!code --]
import {
// [!code ++]
storage, // [!code ++]
defineContentScript, // [!code ++]
ContentScriptContext, // [!code ++]
getAppConfig, // [!code ++]
} from '#imports'; // [!code ++]
```
:::tip
Before types will work, you'll need to run `wxt prepare` after installing v0.20 to generate the new TypeScript declarations.
:::
### `createShadowRootUi` CSS Changes
WXT now resets styles inherited from the webpage (`visibility`, `color`, `font-size`, etc.) by setting `all: initial` inside the shadow root.
:::warning
This doesn't effect `rem` units. You should continue using `postcss-rem-to-px` or an equivalent library if the webpage sets the HTML element's `font-size`.
:::
If you use `createShadowRootUi`:
1. Remove any manual CSS overrides that reset the style of specific websites. For example:
<!-- prettier-ignore -->
```css [entrypoints/reddit.content/style.css]
body { /* [!code --] */
/* Override Reddit's default "hidden" visibility on elements */ /* [!code --] */
visibility: visible !important; /* [!code --] */
} /* [!code --] */
```
2. Double check that your UI looks the same as before.
If you run into problems with the new behavior, you can disable it and continue using your current CSS:
```ts
const ui = await createShadowRootUi({
inheritStyles: true, // [!code ++]
// ...
});
```
### Default Output Directories Changed
The default value for the [`outDirTemplate`](/api/reference/wxt/interfaces/InlineConfig#outdirtemplate) config has changed. Now, different build modes are output to different directories:
- `--mode production` &rarr; `.output/chrome-mv3`: Production builds are unchanged
- `--mode development` &rarr; `.output/chrome-mv3-dev`: Dev mode now has a `-dev` suffix so it doesn't overwrite production builds
- `--mode custom` &rarr; `.output/chrome-mv3-custom`: Other custom modes end with a `-[mode]` suffix
To use the old behavior, writing all output to the same directory, set the `outDirTemplate` option:
```ts [wxt.config.ts]
export default defineConfig({
outDirTemplate: '{{browser}}-mv{{manifestVersion}}', // [!code ++]
});
```
:::warning
If you've previously loaded the extension into your browser manually for development, you'll need to uninstall and re-install it from the new dev output directory.
:::
### Deprecated APIs Removed
- `entrypointLoader` option: WXT now uses `vite-node` for importing entrypoints during the build process.
<!-- markdownlint-disable-next-line MD051 -->
> This was deprecated in v0.19.0, see the [v0.19 section](#v0-18-5-rarr-v0-19-0) for migration steps.
- `transformManifest` option: Use the `build:manifestGenerated` hook to transform the manifest instead:
<!-- prettier-ignore -->
```ts [wxt.config.ts]
export default defineConfig({
transformManifest(manifest) { // [!code --]
hooks: { // [!code ++]
'build:manifestGenerated': (_, manifest) => { // [!code ++]
// ...
}, // [!code ++]
},
});
```
### New Deprecations
#### `runner` APIs Renamed
To improve consistency with the `web-ext.config.ts` filename, the "runner" API and config options have been renamed. You can continue using the old names, but they have been deprecated and will be removed in a future version:
1. The `runner` option has been renamed to `webExt`:
```ts [wxt.config.ts]
export default defineConfig({
runner: { // [!code --]
webExt: { // [!code ++]
startUrls: ["https://wxt.dev"],
},
});
```
2. `defineRunnerConfig` has been renamed to `defineWebExtConfig`:
```ts [web-ext.config.ts]
import { defineRunnerConfig } from 'wxt'; // [!code --]
import { defineWebExtConfig } from 'wxt'; // [!code ++]
```
3. The `ExtensionRunnerConfig` type has been renamed to `WebExtConfig`
```ts
import type { ExtensionRunnerConfig } from 'wxt'; // [!code --]
import type { WebExtConfig } from 'wxt'; // [!code ++]
```
## v0.18.5 &rarr; v0.19.0
### `vite-node` Entrypoint Loader
@@ -19,7 +306,7 @@ Currently, WXT is in pre-release. This means changes to the second digit, `v0.X`
The default entrypoint loader has changed to `vite-node`. If you use any NPM packages that depend on the `webextension-polyfill`, you need to add them to Vite's `ssr.noExternal` option:
<!-- prettier-ignore -->
```ts
```ts [wxt.config.ts]
export default defineConfig({
vite: () => ({ // [!code ++]
ssr: { // [!code ++]
@@ -35,8 +322,7 @@ export default defineConfig({
Importing variables and using them in the entrypoint options:
```ts
// entrypoints/content.ts
```ts [entrypoints/content.ts]
import { GOOGLE_MATCHES } from '~/utils/constants'
export default defineContentScript({
@@ -47,8 +333,7 @@ export default defineContentScript({
Using Vite-specific APIs like `import.meta.glob` to define entrypoint options:
```ts
// entrypoints/content.ts
```ts [entrypoints/content.ts]
const providers: Record<string, any> = import.meta.glob('../providers/*', {
eager: true,
});
@@ -69,7 +354,7 @@ Basically, you can now import and do things outside the `main` function of the e
To continue using the old approach, add the following to your `wxt.config.ts` file:
```ts
```ts [wxt.config.ts]
export default defineConfig({
entrypointLoader: 'jiti', // [!code ++]
});
@@ -86,7 +371,7 @@ WXT no longer ships with Common JS support. If you're using CJS, here's your mig
1. Add [`"type": "module"`](https://nodejs.org/api/packages.html#type) to your `package.json`.
2. Change the file extension of any `.js` files that use CJS syntax to `.cjs`, or update them to use EMS syntax.
Vite also provides steps for migrating to ESM. Check them out for more details: https://vitejs.dev/guide/migration#deprecate-cjs-node-api
Vite also provides steps for migrating to ESM. Check them out for more details: <https://vitejs.dev/guide/migration#deprecate-cjs-node-api>
## v0.18.0 &rarr; v0.18.5
@@ -101,33 +386,13 @@ If you already have `<srcDir>/modules` or `<srcDir>/Modules` directory, `wxt pre
You have two options:
1. [Recommended] Keep your files where they are and tell WXT to look in a different folder:
```ts
// wxt.config.ts
```ts [wxt.config.ts]
export default defineConfig({
modulesDir: 'wxt-modules', // defaults to "modules"
});
```
2. Rename your `modules` directory to something else.
## v0.18.0 &rarr; v0.18.5
> When this version was released, it was not considered a breaking change... but it should have been.
### New `modules/` Directory
WXT now recognizes the `modules/` directory as a folder containing [WXT modules](/guide/essentials/wxt-modules).
If you already have `<srcDir>/modules` or `<srcDir>/Modules` directory, `wxt prepare` and other commands will fail.
You have two options:
1. [Recommended] Keep your files where they are and tell WXT to look in a different folder:
```ts
// wxt.config.ts
export default defineConfig({
modulesDir: 'wxt-modules', // defaults to "modules"
});
```
2. Rename your `modules` directory to something else.
## v0.17.0 &rarr; v0.18.0
@@ -181,7 +446,7 @@ item.watch((newValue: number, oldValue: number) => { // [!code ++]
JS entrypoints in the output directory have been moved. Unless you're doing some kind of post-build work referencing files, you don't have to make any changes.
```
```plaintext
.output/
<target>/
chunks/
@@ -196,8 +461,7 @@ JS entrypoints in the output directory have been moved. Unless you're doing some
### Renamed `zip.ignoredSources` to `zip.excludeSources`
```ts
// wxt.config.ts
```ts [wxt.config.ts]
export default defineConfig({
zip: {
ignoredSources: [
@@ -212,7 +476,7 @@ export default defineConfig({
### Renamed Undocumented Constants
Renamed undocumented constants for detecting the build config at runtime in [#380](https://github.com/wxt-dev/wxt/pull/380). Now documented here: https://wxt.dev/guide/multiple-browsers.html#runtime
Renamed undocumented constants for detecting the build config at runtime in [#380](https://github.com/wxt-dev/wxt/pull/380). Now documented here: <https://wxt.dev/guide/essentials/config/environment-variables.html#built-in-environment-variables>
- `__BROWSER__` → `import.meta.env.BROWSER`
- `__COMMAND__` → `import.meta.env.COMMAND`
@@ -239,7 +503,7 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
### New `wxt/storage` APIs
`wxt/storage` no longer relies on [`unstorage`](https://www.npmjs.com/package/unstorage). Some `unstorage` APIs, like `prefixStorage`, have been removed, while others, like `snapshot`, are methods on the new `storage` object. Most of the standard usage remains the same. See https://wxt.dev/guide/storage and https://wxt.dev/api/reference/wxt/storage/ for more details ([#300](https://github.com/wxt-dev/wxt/pull/300))
`wxt/storage` no longer relies on [`unstorage`](https://www.npmjs.com/package/unstorage). Some `unstorage` APIs, like `prefixStorage`, have been removed, while others, like `snapshot`, are methods on the new `storage` object. Most of the standard usage remains the same. See <https://wxt.dev/guide/storage> and <https://wxt.dev/api/reference/wxt/storage/> for more details ([#300](https://github.com/wxt-dev/wxt/pull/300))
## v0.11.0 &rarr; v0.12.0
@@ -249,6 +513,7 @@ Renamed undocumented constants for detecting the build config at runtime in [#38
- If you use auto-imports, no changes are required.
- If you have disabled auto-imports, you'll need to manually update your import statements:
```ts
import { defineBackground, defineContentScript } from 'wxt/client'; // [!code --]
import { defineBackground, defineContentScript } from 'wxt/sandbox'; // [!code ++]
@@ -292,6 +557,8 @@ Unlisted scripts must now `export default defineUnlistedScript(...)`.
### `BackgroundDefinition` Type
<!-- cspell:disable -->
Rename `BackgroundScriptDefintition` to `BackgroundDefinition`.
## v0.6.0 &rarr; v0.7.0
+9 -3
View File
@@ -6,7 +6,7 @@ title: Next-gen Web Extension Framework
hero:
name: WXT
text: Next-gen Web Extension Framework
tagline: An open source tool that makes Chrome Extension development faster than ever before.
tagline: An open source tool that makes web extension development faster than ever before.
image:
src: /hero-logo.svg
alt: WXT
@@ -73,9 +73,15 @@ features:
linkText: Read docs
---
## Sponsors
WXT is a [MIT-licensed](https://github.com/wxt-dev/wxt/blob/main/LICENSE) open source project with its ongoing development made possible entirely by the support of these awesome backers. If you'd like to join them, please consider [sponsoring WXT's development](https://github.com/sponsors/wxt-dev).
<a href="https://github.com/sponsors/wxt-dev"><img alt="WXT Sponsors" src="https://raw.githubusercontent.com/wxt-dev/static/refs/heads/main/sponsorkit/sponsors-wide.svg"></a>
## Put <span style="color: var(--vp-c-brand-1)">Developer Experience</span> First
WXT simplifies the chrome extension development process by providing tools for zipping and publishing, the best-in-class dev mode, an opinionated project structure, and more. Iterate faster, develop features not build scripts, and use everything the JS ecosystem has to offer.
WXT simplifies the web extension development process by providing tools for zipping and publishing, the best-in-class dev mode, an opinionated project structure, and more. Iterate faster, develop features not build scripts, and use everything the JS ecosystem has to offer.
<div style="margin: auto; width: 100%; max-width: 900px; text-align: center">
<video src="https://github.com/wxt-dev/wxt/assets/10101283/4d678939-1bdb-495c-9c36-3aa281d84c94" controls></video>
@@ -87,7 +93,7 @@ WXT simplifies the chrome extension development process by providing tools for z
## Who's Using WXT?
Battle tested and ready for production. Explore chrome extensions made with WXT.
Battle tested and ready for production. Explore web extensions made with WXT.
<ClientOnly>
<UsingWxtSection />
+1
View File
@@ -0,0 +1 @@
<!--@include: ../packages/is-background/README.md-->
+2
View File
@@ -32,6 +32,8 @@
/guide/build-targets.html /guide/multiple-browsers.html
/guide/installation.html /get-started/installation.html
/guide/introduction.html /get-started/introduction.html
/guide/upgrade-guide/wxt /guide/resources/upgrading.html
/guide/upgrade-guide/wxt.html /guide/resources/upgrading.html
# 0.19.0
/guide/go-further/entrypoint-side-effects.html /guide/go-further/entrypoint-loaders.html
+1
View File
@@ -0,0 +1 @@
<!--@include: ../packages/runner/README.md-->
+71 -27
View File
@@ -4,25 +4,48 @@ outline: deep
# WXT Storage
[Changelog](https://github.com/wxt-dev/wxt/blob/main/packages/wxt/CHANGELOG.md)
[Changelog](https://github.com/wxt-dev/wxt/blob/main/packages/wxt/CHANGELOG.md) &bull; [API Reference](/api/reference/wxt/utils/storage/interfaces/WxtStorage)
WXT provides a simplified API to replace the `browser.storage.*` APIs. Use the `storage` auto-import from `wxt/storage` or import it manually to get started:
A simplified wrapper around the extension storage APIs.
## Installation
### With WXT
This module is built-in to WXT, so you don't need to install anything.
```ts
import { storage } from 'wxt/storage';
import { storage } from '#imports';
```
> [!IMPORTANT]
> To use the `wxt/storage` API, the `"storage"` permission must be added to the manifest:
>
> ```ts
> // wxt.config.ts
> export default defineConfig({
> manifest: {
> permissions: ['storage'],
> },
> });
> ```
If you use auto-imports, `storage` is auto-imported for you, so you don't even need to import it!
### Without WXT
Install the NPM package:
```sh
npm i @wxt-dev/storage
pnpm add @wxt-dev/storage
yarn add @wxt-dev/storage
bun add @wxt-dev/storage
```
```ts
import { storage } from '@wxt-dev/storage';
```
## Storage Permission
To use the `@wxt-dev/storage` API, the `"storage"` permission must be added to the manifest:
```ts [wxt.config.ts]
export default defineConfig({
manifest: {
permissions: ['storage'],
},
});
```
## Basic Usage
@@ -51,11 +74,11 @@ await storage.watch<number>(
await storage.getMeta<{ v: number }>('local:installDate');
```
For a full list of methods available, see the [API reference](/api/reference/wxt/storage/interfaces/WxtStorage).
> This approach is fine for one-off storage fields or generic helpers, but [defining storage items](#defining-storage-items) is the recommended way to add type-safety.
## Watchers
To listen for storage changes, use the `storage.watch` function. It lets you setup a listener for a single key:
To listen for storage changes, use the `storage.watch` function. It lets you set up a listener for a single key:
```ts
const unwatch = storage.watch<number>('local:counter', (newCount, oldCount) => {
@@ -74,7 +97,7 @@ unwatch();
## Metadata
`wxt/storage` also supports setting metadata for keys, stored at `key + "$"`. Metadata is a collection of properties associated with a key. It might be a version number, last modified date, etc.
`@wxt-dev/storage` also supports setting metadata for keys, stored at `key + "$"`. Metadata is a collection of properties associated with a key. It might be a version number, last modified date, etc.
[Other than versioning](#versioning), you are responsible for managing a field's metadata:
@@ -100,7 +123,7 @@ You can remove all metadata associated with a key, or just specific properties:
// Remove all properties
await storage.removeMeta('local:preference');
// Remove one property
// Remove only the "lastModified" property
await storage.removeMeta('local:preference', 'lastModified');
// Remove multiple properties
@@ -123,7 +146,7 @@ const showChangelogOnUpdate = storage.defineItem<boolean>(
);
```
Now, instead of using the `storage` variable, you can use the helper functions on the storage item you created:
Now, instead of using the `storage` variable, you can use the storage item instead:
```ts
await showChangelogOnUpdate.getValue();
@@ -134,8 +157,6 @@ const unwatch = showChangelogOnUpdate.watch((newValue) => {
});
```
For a full list of properties and methods available, see the [API reference](/api/reference/wxt/storage/interfaces/WxtStorageItem).
### Versioning
You can add versioning to storage items if you expect them to grow or change over time. When defining the first version of an item, start with version 1.
@@ -225,13 +246,13 @@ export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV3[]>( // [!code
Internally, this uses a metadata property called `v` to track the value's current version.
:::
In this case, we thought that the ignored website list might change in the future, and were able to setup a versioned storage item from the start.
In this case, we thought that the ignored website list might change in the future, and were able to set up a versioned storage item from the start.
Realistically, you won't know a item needs versioned until you need to change it's schema. Thankfully, it's simple to add versioning to an unversioned storage item.
Realistically, you won't know an item needs versioning until you need to change its schema. Thankfully, it's simple to add versioning to an unversioned storage item.
When a previous version isn't found, WXT assumes the version was `1`. That means you just need to set `version: 2` and add a migration for `2`, and it will just work!
Lets look at the same ignored websites example from before, but start with an unversioned item this time:
Let's look at the same ignored websites example from before, but start with an unversioned item this time:
:::code-group
@@ -275,13 +296,13 @@ export const ignoredWebsites = storage.defineItem<IgnoredWebsiteV2[]>( // [!code
### Running Migrations
As soon as `storage.defineItem` is called, WXT checks if migrations need to be ran, and if so, runs them. Calls to get or update the storage item's value or metadata (`getValue`, `setValue`, `removeValue`, `getMeta`, etc) will automatically wait for the migration process to finish before actually reading or writing values.
As soon as `storage.defineItem` is called, WXT checks if migrations need to be run, and if so, runs them. Calls to get or update the storage item's value or metadata (`getValue`, `setValue`, `removeValue`, `getMeta`, etc.) will automatically wait for the migration process to finish before actually reading or writing values.
### Default Values
With `storage.defineItem`, there are multiple ways of defining default values:
1. `fallback` - Return this value from `getValue` instead of `null` if the value is missing.
1. **`fallback`** - Return this value from `getValue` instead of `null` if the value is missing.
This option is great for providing default values for settings:
@@ -294,7 +315,7 @@ With `storage.defineItem`, there are multiple ways of defining default values:
});
```
2. `init` - Initialize and save a value in storage if it is not already saved.
2. **`init`** - Initialize and save a value in storage if it is not already saved.
This is great for values that need to be initialized or set once:
@@ -308,3 +329,26 @@ With `storage.defineItem`, there are multiple ways of defining default values:
```
The value is initialized in storage immediately.
## Bulk Operations
When getting or setting multiple values in storage, you can perform bulk operations to improve performance by reducing the number of individual storage calls. The `storage` API provides several methods for performing bulk operations:
- **`getItems`** - Get multiple values at once.
- **`getMetas`** - Get metadata for multiple items at once.
- **`setItems`** - Set multiple values at once.
- **`setMetas`** - Set metadata for multiple items at once.
- **`removeItems`** - Remove multiple values (and optionally metadata) at once.
All these APIs support both string keys and defined storage items:
```ts
const userId = storage.defineItem('local:userId');
await storage.setItems([
{ key: 'local:installDate', value: Date.now() },
{ item: userId, value: generateUserId() },
]);
```
Refer to the [API Reference](/api/reference/wxt/utils/storage/interfaces/WxtStorage) for types and examples of how to use all the bulk APIs.
+2 -2
View File
@@ -20,13 +20,13 @@ Set Framerate 50
# Terminal theme with WXT brand colors (which was taken from the website)
# Based on the standard charmbracelet/vhs theme:
# https://github.com/charmbracelet/vhs/blob/88e634f4a10bbe305b6aea9a12b4d8dc3dd7f31c/style.go#L7-L28
Set Theme {"background": "#1a1b1a", "foreground": "#dddddd", "black": "#282a2e", "brightBlack": "#4d4d4d", "red": "#D74E6F", "brightRed": "#FE5F86", "green": "#67d45e", "brightGreen": "#67d45e", "yellow": "#D3E561", "brightYellow": "#EBFF71", "blue": "#8056FF", "brightBlue": "#9B79FF", "magenta": "#ED61D7", "brightMagenta": "#FF7AEA", "cyan": "#04D7D7", "brightCyan": "#00FEFE", "white": "#bfbfbf", "brightWhite": "#e6e6e6", "indigo": "#5B56E0"}
Set Theme {"background": "#161618", "foreground": "#dddddd", "black": "#282a2e", "brightBlack": "#4d4d4d", "red": "#D74E6F", "brightRed": "#FE5F86", "green": "#67d45e", "brightGreen": "#67d45e", "yellow": "#D3E561", "brightYellow": "#EBFF71", "blue": "#8056FF", "brightBlue": "#9B79FF", "magenta": "#ED61D7", "brightMagenta": "#FF7AEA", "cyan": "#04D7D7", "brightCyan": "#00FEFE", "white": "#bfbfbf", "brightWhite": "#e6e6e6", "indigo": "#5B56E0"}
Set FontSize 32
# Terminal settings
Set Shell "bash"
# Terminal prompt. It looks like "● mycommand ..."
# Terminal prompt. It looks like "● command ..."
Env PS1 "\e[0;32m●\e[0m "
+9 -2
View File
@@ -2,11 +2,18 @@
"$schema": "https://typedoc.org/schema.json",
"entryPointStrategy": "packages",
"entryPoints": ["../packages/wxt"],
"plugin": ["typedoc-plugin-markdown", "typedoc-vitepress-theme"],
"plugin": [
"typedoc-plugin-markdown",
"typedoc-vitepress-theme",
"typedoc-plugin-frontmatter"
],
"out": "./api/reference",
"githubPages": false,
"excludePrivate": true,
"excludeProtected": true,
"excludeInternal": true,
"readme": "none"
"readme": "none",
"frontmatterGlobals": {
"editLink": false
}
}
+6
View File
@@ -0,0 +1,6 @@
[build]
command = "bun run docs:build"
publish = "docs/.vitepress/dist"
[build.environment]
BUN_VERSION = "1.3.5"
+49 -36
View File
@@ -2,55 +2,68 @@
"private": true,
"type": "module",
"engines": {
"node": ">=18.20.3"
"bun": ">=1.3.5"
},
"packageManager": "pnpm@9.12.0",
"workspaces": [
"packages/*"
],
"scripts": {
"check": "check && pnpm -r --sequential run check",
"test": "pnpm -r --sequential run test run",
"test:coverage": "pnpm -r --sequential run test:coverage",
"check": "check && bun run --workspaces check",
"test": "bun run --workspaces test run",
"test:coverage": "bun run --workspaces test:coverage",
"prepare": "simple-git-hooks",
"prepublish": "pnpm -s build",
"docs:gen": "typedoc --options docs/typedoc.json",
"docs:dev": "pnpm -s docs:gen && vitepress dev docs",
"docs:build": "pnpm -s docs:gen && vitepress build docs",
"docs:preview": "pnpm -s docs:gen && vitepress preview docs"
"docs:dev": "bun run --silent docs:gen && bun run --bun vitepress dev docs",
"docs:build": "bun run --silent docs:gen && bun run --bun vitepress build docs",
"docs:preview": "bun run --silent docs:gen && bun run --bun vitepress preview docs"
},
"devDependencies": {
"@aklinker1/buildc": "^1.1.4",
"@aklinker1/check": "^1.4.5",
"@types/fs-extra": "^11.0.4",
"@vitest/coverage-v8": "^2.1.2",
"changelogen": "^0.5.7",
"consola": "^3.2.3",
"fast-glob": "^3.3.2",
"fs-extra": "^11.2.0",
"lint-staged": "^15.2.10",
"nano-spawn": "^0.1.0",
"prettier": "^3.3.3",
"simple-git-hooks": "^2.11.1",
"tsx": "4.15.7",
"@aklinker1/buildc": "^1.1.7",
"@aklinker1/check": "^2.4.0",
"@commitlint/config-conventional": "^20.4.3",
"@commitlint/types": "^20.4.3",
"@types/bun": "^1.3.5",
"@types/semver": "^7.7.1",
"@vitest/coverage-v8": "^4.0.18",
"changelogen": "^0.6.2",
"consola": "^3.4.2",
"cspell": "^9.7.0",
"feed": "^5.2.0",
"markdown-it-footnote": "^4.0.0",
"markdownlint-cli": "^0.48.0",
"nano-spawn": "^2.0.0",
"nano-staged": "^0.8.0",
"p-map": "^7.0.4",
"pkg-pr-new": "^0.0.66",
"prettier": "^3.8.1",
"prettier-plugin-jsdoc": "^1.8.0",
"semver": "^7.7.4",
"simple-git-hooks": "^2.13.1",
"tinyglobby": "^0.2.15",
"tsdown": "^0.21.0",
"tsx": "4.21.0",
"typedoc": "^0.25.4",
"typedoc-plugin-frontmatter": "^1.3.1",
"typedoc-plugin-markdown": "4.0.0-next.23",
"typedoc-vitepress-theme": "1.0.0-next.3",
"typescript": "^5.6.2",
"vitepress": "^1.3.4",
"vitest-mock-extended": "^2.0.2",
"vue": "^3.5.11",
"typescript": "^5.9.3",
"vitepress": "^1.6.4",
"vitepress-knowledge": "^0.4.1",
"vitepress-plugin-group-icons": "^1.7.3",
"vitepress-plugin-llms": "^1.12.0",
"vitest-mock-extended": "^3.1.0",
"vue": "^3.5.29",
"wxt": "workspace:*"
},
"patchedDependencies": {
"markdown-it-footnote@4.0.0": "patches/markdown-it-footnote.patch",
"simple-git-hooks@2.13.1": "patches/simple-git-hooks@2.13.1.patch",
"pkg-pr-new@0.0.66": "patches/pkg-pr-new@0.0.66.patch"
},
"simple-git-hooks": {
"pre-commit": "pnpm lint-staged"
"pre-commit": "./node_modules/.bin/nano-staged"
},
"lint-staged": {
"nano-staged": {
"*": "prettier --ignore-unknown --write"
},
"pnpm": {
"peerDependencyRules": {
"ignoreMissing": [
"@algolia/client-search",
"search-insights"
]
}
}
}
+100
View File
@@ -0,0 +1,100 @@
# Changelog
## v0.5.4
[compare changes](https://github.com/wxt-dev/wxt/compare/analytics-v0.5.3...analytics-v0.5.4)
### 🩹 Fixes
- Continue using `useAppConfig` to support older versions of WXT ([bfd94556](https://github.com/wxt-dev/wxt/commit/bfd94556))
### ❤️ Contributors
- Aaron ([@aklinker1](https://github.com/aklinker1))
## v0.5.3
[compare changes](https://github.com/wxt-dev/wxt/compare/analytics-v0.5.2...analytics-v0.5.3)
### 🩹 Fixes
- Add `getAppConfig` as an alias to `useAppConfig` ([#2144](https://github.com/wxt-dev/wxt/pull/2144))
- Allow `userId` option to return `undefined` ([636cf1f8](https://github.com/wxt-dev/wxt/commit/636cf1f8))
- Improve background script detection logic for analytics package ([#1808](https://github.com/wxt-dev/wxt/pull/1808))
### 🏡 Chore
- Created new types, instead of `any` for `analytics` ([#2119](https://github.com/wxt-dev/wxt/pull/2119))
### ❤️ Contributors
- Smit ([@sm17p](https://github.com/sm17p))
- Aaron ([@aklinker1](https://github.com/aklinker1))
- Patryk Kuniczak ([@PatrykKuniczak](https://github.com/PatrykKuniczak))
- Sheng Zhang ([@Arktomson](https://github.com/Arktomson))
## v0.5.2
[compare changes](https://github.com/wxt-dev/wxt/compare/analytics-v0.5.1...analytics-v0.5.2)
### 🩹 Fixes
- Normalize path for createAnalytics of analytics/index.ts ([#2013](https://github.com/wxt-dev/wxt/pull/2013))
- Allow custom API URL in Google Analytics 4 provider options ([#1653](https://github.com/wxt-dev/wxt/pull/1653))
### 💅 Refactors
- Code cleanup in analytics package ([#2084](https://github.com/wxt-dev/wxt/pull/2084))
### 🏡 Chore
- Fix other type error after `chrome` types update ([31ebf966](https://github.com/wxt-dev/wxt/commit/31ebf966))
- Upgrade dev and non-major prod dependencies ([#2000](https://github.com/wxt-dev/wxt/pull/2000))
- Use `tsdown` to build packages ([#2006](https://github.com/wxt-dev/wxt/pull/2006))
- Move script-only dev dependencies to top-level `package.json` ([#2007](https://github.com/wxt-dev/wxt/pull/2007))
- Update dependencies ([#2069](https://github.com/wxt-dev/wxt/pull/2069))
### ❤️ Contributors
- Honwhy Wang <honwhy.wang@gmail.com>
- Aaron ([@aklinker1](https://github.com/aklinker1))
- Patryk Kuniczak ([@PatrykKuniczak](https://github.com/PatrykKuniczak))
## v0.5.1
[compare changes](https://github.com/wxt-dev/wxt/compare/analytics-v0.5.0...analytics-v0.5.1)
### 🚀 Enhancements
- Integrate latest measurement protocol changes ([#1767](https://github.com/wxt-dev/wxt/pull/1767))
### 🩹 Fixes
- Use `@wxt-dev/browser` instead of `@types/chrome` ([#1645](https://github.com/wxt-dev/wxt/pull/1645))
### 🏡 Chore
- Stop using PNPM catalog ([#1644](https://github.com/wxt-dev/wxt/pull/1644))
- Upgrade `@aklinker1/check` to v2 ([#1647](https://github.com/wxt-dev/wxt/pull/1647))
- Change browser workspace dependency to `^` ([c7335add](https://github.com/wxt-dev/wxt/commit/c7335add))
- Fix auto-fixable `markdownlint` errors ([#1710](https://github.com/wxt-dev/wxt/pull/1710))
- **deps:** Upgrade typescript from 5.8.3 to 5.9.2 ([a6eef643](https://github.com/wxt-dev/wxt/commit/a6eef643))
- Create script for managing dependency upgrades ([#1875](https://github.com/wxt-dev/wxt/pull/1875))
- **deps:** Upgrade all dev dependencies ([#1876](https://github.com/wxt-dev/wxt/pull/1876))
### ❤️ Contributors
- Aaron ([@aklinker1](https://github.com/aklinker1))
- Tanishq-aggarwal ([@tanishq-aggarwal](https://github.com/tanishq-aggarwal))
## v0.5.0
[⚠️ breaking changes](https://wxt.dev/guide/resources/upgrading.html) &bull; [compare changes](https://github.com/wxt-dev/wxt/compare/analytics-v0.4.1...analytics-v0.5.0)
### 🩹 Fixes
- ⚠️ Update min WXT version to 0.20 ([2e8baf0](https://github.com/wxt-dev/wxt/commit/2e8baf0))
### ❤️ Contributors
- Aaron ([@aklinker1](https://github.com/aklinker1))
+277
View File
@@ -0,0 +1,277 @@
# WXT Analytics
Report analytics events from your web extension extension.
## Supported Analytics Providers
- [Google Analytics 4 (Measurement Protocol)](#google-analytics-4-measurement-protocol)
- [Umami](#umami)
## Install With WXT
1. Install the NPM package:
```bash
pnpm i @wxt-dev/analytics
```
2. In your `wxt.config.ts`, add the WXT module:
```ts
export default defineConfig({
modules: ['@wxt-dev/analytics/module'],
});
```
3. In your `<srcDir>/app.config.ts`, add a provider:
```ts
// <srcDir>/app.config.ts
import { umami } from '@wxt-dev/analytics/providers/umami';
export default defineAppConfig({
analytics: {
debug: true,
providers: [
// ...
],
},
});
```
4. Then use the `#analytics` module to report events:
```ts
import { analytics } from '#analytics';
await analytics.track('some-event');
await analytics.page();
await analytics.identify('some-user-id');
analytics.autoTrack(document.body);
```
## Install Without WXT
1. Install the NPM package:
```bash
pnpm i @wxt-dev/analytics
```
2. Create an `analytics` instance:
```ts
// utils/analytics.ts
import { createAnalytics } from '@wxt-dev/analytics';
export const analytics = createAnalytics({
providers: [
// ...
],
});
```
3. Import your analytics module in the background to initialize the message listener:
```ts
// background.ts
import './utils/analytics';
```
4. Then use your `analytics` instance to report events:
```ts
import { analytics } from './utils/analytics';
await analytics.track('some-event');
await analytics.page();
await analytics.identify('some-user-id');
analytics.autoTrack(document.body);
```
## Providers
### Google Analytics 4 (Measurement Protocol)
The [Measurement Protocol](https://developers.google.com/analytics/devguides/collection/protocol/ga4) is an alternative to GTag for reporting events to Google Analytics for MV3 extensions.
> [Why use the Measurement Protocol instead of GTag?](https://developer.chrome.com/docs/extensions/how-to/integrate/google-analytics-4#measurement-protocol)
Follow [Google's documentation](https://developer.chrome.com/docs/extensions/how-to/integrate/google-analytics-4#setup-credentials) to obtain your credentials and put them in your `.env` file:
```dotenv
WXT_GA_API_SECRET='...'
```
Then add the `googleAnalytics4` provider to your `<srcDir>/app.config.ts` file:
```ts
import { googleAnalytics4 } from '@wxt-dev/analytics/providers/google-analytics-4';
export default defineAppConfig({
analytics: {
providers: [
googleAnalytics4({
apiSecret: import.meta.env.WXT_GA_API_SECRET,
measurementId: '...',
}),
],
},
});
```
### Umami
[Umami](https://umami.is/) is a privacy-first, open source analytics platform.
In Umami's dashboard, create a new website. The website's name and domain can be anything. Obviously, an extension doesn't have a domain, so make one up if you don't have one.
After the website has been created, save the website ID and domain to your `.env` file:
```dotenv
WXT_UMAMI_WEBSITE_ID='...'
WXT_UMAMI_DOMAIN='...'
```
Then add the `umami` provider to your `<srcDir>/app.config.ts` file:
```ts
import { umami } from '@wxt-dev/analytics/providers/umami';
export default defineAppConfig({
analytics: {
providers: [
umami({
apiUrl: 'https://<your-umami-instance>/api',
websiteId: import.meta.env.WXT_UMAMI_WEBSITE_ID,
domain: import.meta.env.WXT_UMAMI_DOMAIN,
}),
],
},
});
```
### Custom Provider
If your analytics platform is not supported, you can provide an implementation of the `AnalyticsProvider` type in your `app.config.ts` instead:
```ts
import { defineAnalyticsProvider } from '@wxt-dev/analytics/client';
interface CustomAnalyticsOptions {
// ...
}
const customAnalytics = defineAnalyticsProvider<CustomAnalyticsOptions>(
(analytics, analyticsConfig, providerOptions) => {
// ...
},
);
export default defineAppConfig({
analytics: {
providers: [
customAnalytics({
// ...
}),
],
},
});
```
Example `AnalyticsProvider` implementations can be found at [`./modules/analytics/providers`](https://github.com/wxt-dev/wxt/tree/main/packages/analytics/modules/analytics/providers).
## User Properties
User ID and properties are stored in `browser.storage.local`. To change this or customize where these values are stored, use the `userId` and `userProperties` config:
```ts
// app.config.ts
import { storage } from 'wxt/storage';
export default defineAppConfig({
analytics: {
userId: storage.defineItem('local:custom-user-id-key'),
userProperties: storage.defineItem('local:custom-user-properties-key'),
},
});
```
To set the values at runtime, use the `identify` function:
```ts
await analytics.identify(userId, userProperties);
```
Alternatively, a common pattern is to use a random string as the user ID. This keeps the actual user information private, while still providing useful metrics in your analytics platform. This can be done very easily using WXT's storage API:
```ts
// app.config.ts
import { storage } from 'wxt/storage';
export default defineAppConfig({
analytics: {
userId: storage.defineItem('local:custom-user-id-key', {
init: () => crypto.randomUUID(),
}),
},
});
```
If you aren't using `wxt` or `@wxt-dev/storage`, you can define custom implementations for the `userId` and `userProperties` config:
```ts
const analytics = createAnalytics({
userId: {
getValue: () => ...,
setValue: (userId) => ...,
}
})
```
## Auto-track UI events
Call `analytics.autoTrack(container)` to automatically track UI events so you don't have to manually add them. Currently it:
- Tracks clicks to elements inside the `container`
In your extension's HTML pages, you'll want to call it with `document`:
```ts
analytics.autoTrack(document);
```
But in content scripts, you usually only care about interactions with your own UI:
```ts
const ui = createIntegratedUi({
// ...
onMount(container) {
analytics.autoTrack(container);
},
});
ui.mount();
```
## Enabling/Disabling
By default, **analytics is disabled**. You can configure how the value is stored (and change the default value) via the `enabled` config:
```ts
// app.config.ts
import { storage } from 'wxt/storage';
export default defineAppConfig({
analytics: {
enabled: storage.defineItem('local:analytics-enabled', {
fallback: true,
}),
},
});
```
At runtime, you can call `setEnabled` to change the value:
```ts
analytics.setEnabled(true);
```
+20
View File
@@ -0,0 +1,20 @@
import { defineAppConfig } from 'wxt/utils/define-app-config';
import { googleAnalytics4 } from './modules/analytics/providers/google-analytics-4';
import { umami } from './modules/analytics/providers/umami';
export default defineAppConfig({
analytics: {
debug: true,
providers: [
googleAnalytics4({
apiSecret: '...',
measurementId: '...',
}),
umami({
apiUrl: 'https://umami.aklinker1.io/api',
domain: 'analytics.wxt.dev',
websiteId: '8f1c2aa4-fad3-406e-a5b2-33e8d4501716',
}),
],
},
});
@@ -0,0 +1,17 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Popup</title>
</head>
<body>
<label>
<input id="enabledCheckbox" type="checkbox" />
&emsp;Analytics enabled
</label>
<button id="button1">Button 1</button>
<button class="cool-button">Button 2</button>
<script type="module" src="./main.ts"></script>
</body>
</html>
@@ -0,0 +1,9 @@
import { analytics } from '#analytics';
declare const enabledCheckbox: HTMLInputElement;
analytics.autoTrack(document);
enabledCheckbox.oninput = () => {
void analytics.setEnabled(enabledCheckbox.checked);
};
@@ -0,0 +1,3 @@
import '#analytics';
export default () => {};

Some files were not shown because too many files have changed in this diff Show More