Skip to main content
Get your type-safe JSON API up and running in minutes. This guide will walk you through cloning the template, setting up your environment, and making your first API call.
1

Clone the Template

Clone the template without git history using degit:
npx degit w3cj/hono-open-api-starter my-api
cd my-api
This creates a fresh copy of the starter template without the original repository’s commit history.
2

Install Dependencies

Install the required packages using pnpm:
pnpm install
This template uses pnpm, but you can also use npm or yarn. The project includes all necessary dependencies including Hono, Drizzle ORM, Zod, and OpenAPI tooling.
3

Configure Environment

Create your environment configuration file:
cp .env.example .env
The default .env file contains:
.env
NODE_ENV=development
PORT=9999
LOG_LEVEL=debug
DATABASE_URL=file:dev.db
  • NODE_ENV - Runtime environment (development, production, test)
  • PORT - Server port number (default: 9999)
  • LOG_LEVEL - Logging verbosity (fatal, error, warn, info, debug, trace, silent)
  • DATABASE_URL - SQLite database file path or Turso URL
  • DATABASE_AUTH_TOKEN - Required for production when using Turso (optional in development)
The application validates environment variables on startup using Zod schemas. If any required variables are missing or invalid, the app will fail to start with a detailed error message.
4

Initialize the Database

Create the SQLite database and push the schema:
pnpm drizzle-kit push
This creates a dev.db file in your project root with the tasks table schema:
src/db/schema.ts
export const tasks = sqliteTable("tasks", {
  id: integer({ mode: "number" })
    .primaryKey({ autoIncrement: true }),
  name: text().notNull(),
  done: integer({ mode: "boolean" })
    .notNull()
    .default(false),
  createdAt: integer({ mode: "timestamp" })
    .$defaultFn(() => new Date()),
  updatedAt: integer({ mode: "timestamp" })
    .$defaultFn(() => new Date())
    .$onUpdate(() => new Date()),
});
5

Start the Development Server

Run the development server with hot reload:
pnpm dev
You should see output indicating the server is running:
Server is running on port http://localhost:9999
The dev server uses tsx watch for automatic reloading when you make changes to your code.
6

Explore the API Documentation

Open your browser and navigate to the interactive API documentation:
http://localhost:9999/reference
This displays a beautiful Scalar API reference powered by your OpenAPI specification. You can:
  • Browse all available endpoints
  • View request/response schemas
  • Test API calls directly from the browser
  • See example requests in multiple languages
The OpenAPI spec is also available in JSON format at http://localhost:9999/doc
7

Make Your First API Call

Test the API by creating a task. Choose your preferred method:
curl -X POST http://localhost:9999/tasks \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Build my first API",
    "done": false
  }'
Expected response:
{
  "id": 1,
  "name": "Build my first API",
  "done": false,
  "createdAt": "2026-03-04T12:00:00.000Z",
  "updatedAt": "2026-03-04T12:00:00.000Z"
}
8

Try Other Endpoints

Explore the complete Tasks API:
curl http://localhost:9999/tasks
All endpoints are fully documented with:
  • Request/response validation using Zod schemas
  • OpenAPI specification generation
  • Type-safe handlers
  • Proper HTTP status codes
  • Error handling

Available Endpoints

MethodPathDescription
GET/API index
GET/docOpenAPI specification (JSON)
GET/referenceInteractive API documentation
GET/tasksList all tasks
POST/tasksCreate a new task
GET/tasks/{id}Get a task by ID
PATCH/tasks/{id}Update a task
DELETE/tasks/{id}Delete a task

Next Steps

Project Architecture

Learn about the codebase organization and key files

Creating Routes

Build your own OpenAPI routes with full type safety

Database Schema

Work with Drizzle ORM and define your data models

Deployment

Deploy your API to production environments

Additional Commands

# Run tests
pnpm test

# Lint code
pnpm lint

# Type check
pnpm typecheck

# Build for production
pnpm build

# Start production server
pnpm start

Build docs developers (and LLMs) love