# Mental model

## Deno in one diagram

```text
source (.ts/.js/.wasm)
  ├─ modules: local / JSR / npm / URL
  ├─ config: deno.json(c) + deno.lock
  ├─ tools: fmt / lint / check / test / doc / compile
  └─ runtime: Web APIs + Deno APIs + Node compatibility
                    ↓
       permission boundary (--allow-* / --deny-*)
                    ↓
       files, network, environment, subprocesses, FFI
```

## Three important differences from Node.js

1. **Secure defaults:** sensitive I/O is denied until granted, and grants can be scoped to paths, hosts, or variable names.
2. **Direct TypeScript execution:** execution transpiles TypeScript but does not imply a full type-check on every run; keep `deno check` in CI.
3. **One toolchain:** formatting, linting, testing, and docs ship with the same CLI version.

## Dependencies have multiple sources

- JSR packages use `jsr:` and work well for TypeScript-native packages and the Deno standard library.
- npm packages use `npm:`; Node built-ins use `node:`.
- `imports` in `deno.json` maps full specifiers to stable bare import names.
- `deno.lock` pins resolution and integrity data and should be committed.

<Callout type="info" title="Type-checking boundary">
“Runs `.ts`” does not mean “performs a full type-check before every execution.” Put `deno check` in CI to turn type errors into a release gate.
</Callout>

Continue with [Permissions](/en/docs/core/permissions) and [Dependencies](/en/docs/core/dependencies).
