Deno

Build secure, type-safe APIs with Igniter.js and Deno, the modern JavaScript runtime built for security and productivity.

Deno is a modern JavaScript runtime that prioritizes security, developer experience, and web standards. When combined with Igniter.js, you get a secure-by-default environment with native TypeScript support, built-in testing, and automatic code formatting—all without configuration.

This guide shows you how to build production-ready APIs with Deno and Igniter.js. You'll experience Deno's security model with granular permissions, standard library utilities, and native TypeScript execution, all while maintaining Igniter.js's type-safe controllers and automatic API documentation.

Secure by Default

Deno + Igniter.js provides security-first development. Deno requires explicit permissions for file system, network, and environment access—perfect for production deployments.


Quick Start

The fastest way to start is using the official CLI with Deno's native TypeScript support:

npx @igniter-js/cli@latest init
pnpm dlx @igniter-js/cli@latest init
yarn dlx @igniter-js/cli@latest init
bunx @igniter-js/cli@latest init

Your API runs at http://localhost:8000/api/v1, and interactive docs at http://localhost:8000/api/v1/docs 🚀


Manual Setup

Complete Deno Setup Guide

Prerequisites

Before you begin, ensure you have:

Initialize Deno Project

Create a new directory and initialize with deno.json:

deno.json
{
  "tasks": {
    "dev": "deno run --allow-net --allow-env --allow-read --watch src/index.ts",
    "start": "deno run --allow-net --allow-env --allow-read src/index.ts"
  },
  "compilerOptions": {
    "lib": ["deno.window"],
    "strict": true
  },
  "imports": {
    "@/": "./src/",
    "@igniter-js/core": "npm:@igniter-js/core@latest",
    "zod": "npm:zod@latest"
  }
}

Deno's import map allows you to use npm packages seamlessly with native Deno modules.

Define Application Context

The context defines dependencies available throughout your API. Create src/igniter.context.ts:

src/igniter.context.ts
/**
 * Application Context Type
 * Defines what dependencies are available to all API handlers
 */
export interface AppContext {
  // Add your dependencies here, e.g.:
  // db: Database
  // cache: KvStore
}

/**
 * Context Factory
 * Creates the context instance passed to handlers
 */
export function createIgniterAppContext(): AppContext {
  return {
    // Initialize dependencies here
  }
}

Initialize Igniter.js

Create the main Igniter instance. Create src/igniter.ts:

src/igniter.ts
import { Igniter } from '@igniter-js/core'
import { createIgniterAppContext } from './igniter.context.ts'

export const igniter = Igniter
  .context(createIgniterAppContext())
  .config({
    baseURL: Deno.env.get('IGNITER_API_URL') || 'http://localhost:8000',
    basePATH: Deno.env.get('IGNITER_API_BASE_PATH') || '/api/v1',
  })
  .docs({
    info: {
      title: 'My Deno API',
      version: '1.0.0',
      description: 'Secure API built with Deno and Igniter.js',
    }
  })
  .create()

Note: Deno uses Deno.env.get() for environment variables with explicit --allow-env permission.

Create Your First Controller

Controllers group related endpoints. Create src/features/example/controllers/example.controller.ts:

src/features/example/controllers/example.controller.ts
import { igniter } from '@/igniter.ts'

export const exampleController = igniter.controller({
  name: 'Example',
  path: '/example',
  actions: {
    hello: igniter.query({
      path: '/hello',
      handler: async ({ response }) => {
        return response.success({ 
          message: 'Hello from Igniter.js with Deno! 🦕',
          timestamp: new Date().toISOString(),
          runtime: 'Deno',
          version: Deno.version.deno
        })
      },
    }),
  },
})

Create barrel export at src/features/example/index.ts:

src/features/example/index.ts
export * from './controllers/example.controller.ts'

This creates GET /api/v1/example/hello with fully typed responses.

Create Application Router

The router assembles all controllers. Create src/igniter.router.ts:

src/igniter.router.ts
import { igniter } from './igniter.ts'
import { exampleController } from './features/example/index.ts'

export const AppRouter = igniter.router({
  controllers: {
    example: exampleController
  }
})

      export type AppRouterType = typeof AppRouter

Set Up Deno Server

Deno has a built-in HTTP server based on web standards. Create src/index.ts:

src/index.ts
import { serve } from 'https://deno.land/std@0.203.0/http/server.ts'
import { AppRouter } from './igniter.router.ts'

const handler = (req: Request) => {
  const url = new URL(req.url)
  const IGNITER_API_BASE_PATH = Deno.env.get('IGNITER_API_BASE_PATH') || '/api/v1'

  // Route to Igniter.js
  if (url.pathname.startsWith(IGNITER_API_BASE_PATH)) {
    return AppRouter.handler(req)
  }

  return new Response('Not Found', { status: 404 })
}

const port = 8000

serve(handler, { port })

console.log(`🚀 Server running at http://localhost:${port}/`)

Deno's serve function uses the standard Request and Response APIs—no framework needed!

Step 7: Run with Permissions

Deno requires explicit permissions. Run your server:

# Development with auto-reload
deno task dev

# Or run directly
deno run --allow-net --allow-env --allow-read --watch src/index.ts

Permissions explained:

  • --allow-net: Network access for HTTP server
  • --allow-env: Read environment variables
  • --allow-read: Read files (for static assets, configs)
  • --watch: Auto-reload on file changes

Deno-Specific Features

Native TypeScript

Deno runs TypeScript natively—no build step required. File extensions are mandatory:

// Always include .ts extension
import { igniter } from './igniter.ts'
import type { User } from './types.ts'

Environment Variables

Create .env file and load with --env flag:

.env
IGNITER_API_BASE_PATH=/api/v1
IGNITER_API_URL=http://localhost:8000
DATABASE_URL=postgresql://localhost/mydb

Access via Deno.env.get():

const dbUrl = Deno.env.get('DATABASE_URL')

Or use the --env flag:

deno run --env --allow-net --allow-env src/index.ts

Deno KV (Built-in Database)

Deno includes a built-in key-value database:

src/igniter.context.ts
export async function createIgniterAppContext() {
  const kv = await Deno.openKv()
  
  return {
    db: kv
  }
}

Use it in controllers:

const result = await context.db.get(['users', userId])
await context.db.set(['users', userId], userData)

Standard Library

Deno's standard library provides utilities without npm:

// File system
import { ensureDir } from 'https://deno.land/std@0.203.0/fs/mod.ts'

// HTTP server
import { serve } from 'https://deno.land/std@0.203.0/http/server.ts'

// Testing
import { assertEquals } from 'https://deno.land/std@0.203.0/assert/mod.ts'

Type-Safe Client

Create a type-safe client for consuming your API. Create src/igniter.client.ts:

src/igniter.client.ts
import { createIgniterClient } from '@igniter-js/core/client'
import type { AppRouterType } from './igniter.router.ts'

export const api = createIgniterClient<AppRouterType>({
  baseURL: Deno.env.get('IGNITER_API_URL') || 'http://localhost:8000',
  basePATH: Deno.env.get('IGNITER_API_BASE_PATH') || '/api/v1',
  router: () => {
    // Dynamic import for Deno
    return import('./igniter.router.ts').then(m => m.AppRouter)
  },
})

export type ApiClient = typeof api

Use it anywhere:

// Fully typed, secure by default
const { message, version } = await api.example.hello.query()

Testing with Deno

Deno has built-in testing—no additional packages needed:

src/features/example/example.test.ts
import { assertEquals } from 'https://deno.land/std@0.203.0/assert/mod.ts'
import { api } from '@/igniter.client.ts'

Deno.test('Example controller returns hello message', async () => {
  const result = await api.example.hello.query()
  
  assertEquals(result.runtime, 'Deno')
  assertEquals(typeof result.version, 'string')
})

Run tests:

deno test --allow-net --allow-env

Igniter Studio (API Playground)

Igniter.js includes an interactive API playground called Igniter Studio. It's automatically available at /api/v1/docs when you configure the .docs() method.

To access it:

  1. Start your dev server: deno task dev
  2. Navigate to http://localhost:8000/api/v1/docs
  3. You'll see an interactive interface where you can:
    • Browse all API endpoints
    • View request/response schemas
    • Test endpoints directly
    • See auto-generated examples

The playground updates automatically as you add endpoints.


Production Deployment

Deno Deploy

Deploy to Deno's edge network with zero configuration:

# Install Deno Deploy CLI
deno install --allow-all --no-check -r -f https://deno.land/x/deploy/deployctl.ts

# Deploy your project
deployctl deploy --project=my-api src/index.ts

Docker

Create a Dockerfile:

FROM denoland/deno:1.40.0

WORKDIR /app
COPY . .

RUN deno cache src/index.ts

EXPOSE 8000

CMD ["deno", "run", "--allow-net", "--allow-env", "--allow-read", "src/index.ts"]

Project Structure

Here's the recommended structure:

index.ts
igniter.ts
igniter.context.ts
igniter.router.ts
igniter.client.ts
igniter.schema.ts
deno.json
.env

Next Steps