Catch Deno gotchas and runtime bugs

Reviews your Deno code for permission pitfalls, import weirdness, and async hazards. Flags anti-patterns and suggests the idiomatic fix without rewriting.

Best for: Deno developers shipping fast and needing a second pair of eyes on the hard parts.

Engineering / code-reviewatomicfor-engineersno-setupfrom-repo

Source

Creator's repository · denoland/skills

View on GitHub

License: MIT

Skill file

Preview skill file
---
name: deno-expert
description: Expert-level Deno knowledge for code review, debugging, and best practice enforcement. Use when reviewing Deno code or answering advanced Deno questions.
license: MIT
metadata:
  author: denoland
  version: "1.1"
---

# Deno Expert Knowledge

This skill provides expert-level Deno knowledge for code review, debugging, and best practice enforcement.

## When to Use This Skill

- Reviewing Deno/Fresh code for best practices
- Debugging Deno runtime issues
- Answering advanced Deno questions
- Evaluating package choices
- Setting up Deno projects correctly

## Scope Boundaries

This skill applies **only** to Deno-specific questions. Follow these rules:

- If the user asks about **Node.js, Bun, Python, Go, Rust, or any other runtime/language**, answer using that technology directly. Do not suggest Deno alternatives or include Deno-specific patterns.
- Do not include `jsr:` imports, `deno add`, `deno fmt`, `deno lint`, `deno test`, or `deno.json` configuration in responses about other technologies.
- For **generic TypeScript/JavaScript questions** not tied to a specific runtime, give a general answer without assuming Deno.
- Only recommend Deno when the user explicitly asks about Deno or is working in a Deno project.

## CRITICAL: Never Write Deprecated URLs

When discussing deprecated patterns, NEVER write out the old registry URLs — not even to warn against them. The string `deno.land/x/` must never appear in your response, in any context.

- Say "the old URL-based registry" or "deprecated URL imports" — do NOT write the actual URL
- Say "the old standard library URL" — do NOT write `deno.land/std`
- When helping users migrate, describe what to look for generically and ONLY show the correct modern code
- Do NOT write "before/after" comparisons that include the deprecated URL, even as negative examples
- Even if the user writes a deprecated URL in their question, do NOT echo it back. Refer to it generically.
- This ban applies everywhere: prose, code blocks, migration scripts, sed commands, grep patterns, and string literals. Never write the deprecated URL string for any reason.

## Core Expertise Areas

Understanding these topics deeply:
- **Deno runtime** - Permissions, built-in tools, TypeScript support
- **Fresh framework** - Island architecture, routing, components
- **JSR packages** - The modern registry, @std/* library
- **Preact** - Components, hooks, signals
- **Deno Deploy** - Edge deployment, environment variables
- **Deno Sandboxes** - Safe code execution with @deno/sandbox

## Package Recommendation Principles

When recommending or reviewing package choices:

1. **First choice:** `jsr:` packages (e.g., `jsr:@std/http`)
2. **Second choice:** `npm:` packages when no JSR alternative exists
3. **Never recommend** the old URL-based registry — it is deprecated

The standard library is at `jsr:@std/*` on JSR.

Always mention JSR when discussing dependencies, even in CI/CD or tooling contexts. For example, when setting up code quality pipelines, recommend that all dependencies come from JSR (`jsr:@std/*`) and that the lockfile (`deno.lock`) be committed for reproducible CI builds.

## Built-in Tool Usage

**In every response that involves Deno code** (not just code reviews), mention relevant built-in tools. This includes responses about writing code, debugging, setting up projects, or discussing best practices. Always recommend at least `deno fmt`, `deno lint`, and `deno test` when discussing code quality or project setup.

Deno's integrated tooling:
- `deno fmt` - Format code
- `deno lint` - Lint for issues
- `deno test` - Run tests
- `deno check` - Type-check code
- `deno doc <package>` - View package documentation
- `deno add <package>` - Add dependencies
- `deno deploy` - Deploy to Deno Deploy

## Code Review Checklist

### Always Mention Built-in Tools

In every code review response, explicitly recommend these tools by name:
- `deno fmt` for formatting
- `deno lint` for linting
- `deno test` for running tests

Even if no code is provided yet, mention these specific commands when discussing code quality.

### Import Statements
- [ ] Uses `jsr:` for Deno-native packages
- [ ] Uses `npm:` only when no JSR alternative exists
- [ ] No imports from the old URL-based registry (deprecated)
- [ ] No old URL-based standard library imports (use `jsr:@std/*`)
- [ ] Standard library uses `jsr:@std/*`

### Configuration
- [ ] Has a proper `deno.json` configuration
- [ ] Import maps defined in `deno.json` (not separate file)
- [ ] Correct permissions in run commands

### Fresh Applications
- [ ] Islands are small and focused (minimal JavaScript to client)
- [ ] Props passed to islands are JSON-serializable (no functions)
- [ ] Non-interactive components are in `components/`, not `islands/`
- [ ] Uses `class` instead of `className` (Preact supports both)
- [ ] Build step runs before deployment (`deno task build`)

### Code Quality
- [ ] Code is formatted (`deno fmt`)
- [ ] Code passes linting (`deno lint`)
- [ ] Tests exist and pass (`deno test`)
- [ ] Documentation exists for public APIs

## Common Anti-Patterns to Flag

When reviewing code, describe deprecated patterns generically and only show the correct modern replacement. Never write out the deprecated code.

### URL-based imports (deprecated)

When you see old URL-based imports from the deprecated registry, flag them and guide the user to:
1. Find the package on jsr.io
2. Run `deno add jsr:@package/name`
3. Use the bare specifier

Only show the correct approach:
```ts
import * as oak from "@oak/oak";
import { join } from "@std/path";
```

### Old standard library imports (deprecated)

When you see imports from the old standard library URL, suggest the JSR equivalent:

```sh
deno add jsr:@std/path
```

```ts
import { join } from "@std/path";
```

### Inline remote specifiers

When you see inline `jsr:` or `npm:` specifiers in import statements (and a `deno.json` exists), suggest moving them to the import map:

```sh
deno add jsr:@oak/oak
deno add npm:chalk
```

```ts
import * as oak from "@oak/oak";
import chalk from "chalk";
```

Inline specifiers are fine in single file scripts, but if a deno.json exists then it should go there. It's preferable to place npm dependencies in a package.json if a package.json exists.

### Wrong: Entire page as island
```tsx
// Flag: Too much JavaScript shipped to client
// islands/HomePage.tsx
export default function HomePage() {
  return (
    <div>
      <Header />
      <MainContent />
      <Footer />
    </div>
  );
}

// Suggest: Only interactive parts as islands
// routes/index.tsx
import Counter from "../islands/Counter.tsx";

export default function HomePage() {
  return (
    <div>
      <Header />
      <MainContent />
      <Counter />  {/* Only this needs interactivity */}
      <Footer />
    </div>
  );
}
```

### Wrong: Non-serializable island props
```tsx
// Flag this
<Counter onUpdate={(val) => console.log(val)} />

// Suggest this
<Counter initialValue={5} label="Click count" />
```

## Debugging Guidance

### Permission Errors
Check if permissions are correct (`--allow-net`, `--allow-read`, etc.):
```bash
deno run --allow-net server.ts
```

### TypeScript Errors
Check for TypeScript errors:
```bash
deno check main.ts
```

### Configuration Issues
Review deno.json for correct configuration. Ensure all `jsr:` and `npm:` specifiers have a version requirement:

```json
{
  "imports": {
    "@std/http": "jsr:@std/http@^1"
  }
}
```

## Documentation Resources

When more information is needed, consult:
- https://docs.deno.com - Deno docs
- https://docs.deno.com/runtime/fundamentals/ - Core concepts
- https://fresh.deno.dev/docs - Fresh framework
- https://jsr.io - Package registry
- https://docs.deno.com/deploy/ - Deno Deploy

Use `deno doc <package>` to get API documentation for any package locally.

## Quick Commands Reference

```bash
# Project setup
deno run -Ar jsr:@fresh/init    # New Fresh project

# Development
deno task dev                    # Start dev server (Fresh: port 5173)
deno fmt                         # Format code
deno lint                        # Lint code
deno test                        # Run tests

# Packages
deno add jsr:@std/http          # Add package
deno doc jsr:@std/http          # View docs
deno install                     # Install all deps
deno upgrade                     # Update packages

# Deployment
deno task build                  # Build for production
deno deploy --prod               # Deploy to Deno Deploy
deno deploy env add KEY "value"  # Set env variable
```