> ## Documentation Index
> Fetch the complete documentation index at: https://extension.js.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Deno projects with Extension.js

> Scaffold and build browser extensions in Deno-first projects. Extension.js reads deno.jsonc as the project manifest and resolves npm: imports.

Extension.js treats Deno as a first-class runtime, and a CI lane runs `extension build` and `extension dev` on Deno for every change. Scaffold with Deno and the project gets a `deno.jsonc` instead of a `package.json`. Work in a hybrid project and `deno.jsonc` sits beside `package.json` for Deno-native settings. Either way, `extension dev` and `extension build` behave the same.

## Which Deno versions work

Extension.js needs Deno 2.5 or newer. The CLI reads `process.versions.deno` at startup and judges Deno on its own version, never on the Node version that Deno emulates, so the number in the message is the one you can act on.

| Deno version | Status |
| - | - |
| 2.5 and newer | Supported, apart from 2.8.0 |
| 2.8.0 | Refused. That release cannot resolve `node:querystring` inside the bundler, and Deno fixed it in 2.8.1 |
| Older than 2.5 | Refused, because the floor is 2.5. As background, those releases also emulate a Node version below 22.12 |

## Create a project with Deno

```bash theme={null}
deno run -A npm:extension@latest create my-extension --template=react
```

Then run the dev task:

```bash theme={null}
cd my-extension
deno task dev
```

## Primary mode: deno.jsonc is the project manifest

When you scaffold under the Deno runtime, `deno.jsonc` becomes the project's only manifest and `package.json` is removed.

* Template dependencies move into `imports` as `npm:` specifiers, and `deno install` resolves them.
* The `extension` engine itself is declared there too, as `npm:extension@<version>`.
* `nodeModulesDir` is set to `"auto"`, so `npm:` dependencies materialize in a real `node_modules` directory. The bundler resolves project dependencies from it at dev and build time.
* `deno task <name>` also finds binaries in `node_modules/.bin`, so the generated tasks run the locally installed Extension.js CLI.

A trimmed example:

```jsonc theme={null}
{
  "imports": {
    "react": "npm:react@^19.0.0",
    "react-dom": "npm:react-dom@^19.0.0",
    "extension": "npm:extension@^4.0.0"
  },
  "nodeModulesDir": "auto",
  "tasks": {
    "dev": "extension dev",
    "build": "extension build"
  }
}
```

When a template ships its own Deno config, Extension.js merges into that file instead of creating a second one. Deno's own discovery prefers `deno.json` over `deno.jsonc`, so the merge targets the file that Deno will read.

## Companion mode: deno.jsonc beside package.json

Monorepo templates, and projects that already have a `package.json`, keep it. Dependencies stay declared in `package.json`, and `deno install` resolves them from there. The companion `deno.jsonc` carries only Deno-native settings and the `tasks` that run the CLI.

## How the toolchain detects Deno

Detection works on files, not on how you invoked the CLI:

* Extension.js reads `deno.jsonc` or `deno.json` when it scans project dependencies. Framework, CSS, and TypeScript detection all see packages that `imports` declares through `npm:` specifiers.
* When both manifests declare the same package, the `package.json` entry wins.
* A project counts as Deno-managed when it has a `deno.lock`, or a Deno config with no `package.json` beside it. An npm-family lockfile wins for hybrids, and Deno is claimed only when the `deno` binary is on your PATH.

## TypeScript in Deno projects

TypeScript detection follows the same rules as everywhere else. See [TypeScript](/docs/languages-and-frameworks/typescript): SWC compiles the sources, and the `typescript` package is only needed for `tsc --noEmit`.

## Managed browsers need Node.js

`extension install <browser>` downloads a managed browser through `npx`, or through the package manager that launched the CLI. `deno` has no such runner, so on Deno that one command needs Node.js on your `PATH`. Without it the command fails at the download step. `dev`, `build`, `preview`, and `start` run on Deno alone, and a browser that is already installed on your system needs no download. See [`install`](/docs/commands/install).

## Next steps

* Learn how Extension.js handles [Node APIs](/docs/languages-and-frameworks/node).
* Learn how to manage [Extension configuration](/docs/features/extension-configuration).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.