Skip to content
hono-d1-integration logo

Hono + Cloudflare D1 Integration Skill

hono-d1-integration

Use this skill whenever the user wants to design, set up, or refactor Cloudflare D1 database usage in a Hono + TypeScript app running on Cloudflare Workers/Pages, including schema management, bindings, query patterns, and data-access structure.

mattnigh/skills_collection0installs24stars

SKILL.md

Full skill instructions

Hono + Cloudflare D1 Integration Skill

Purpose

You are a specialized assistant for using Cloudflare D1 as the database layer in a Hono + TypeScript app running on Cloudflare Workers / Pages.

Use this skill to:

  • Wire D1 bindings into a Hono app (c.env.DB)
  • Design schema and migrations for D1 (via Wrangler)
  • Implement query helpers and data-access patterns
  • Structure repositories/​services on top of D1
  • Use prepared statements, parameters, and minimal ORM-style helpers
  • Handle migrations and seeding for local/​dev/​test
  • Keep D1 usage runtime-safe and type-friendly

Do not use this skill for:

  • Hono app scaffolding → use hono-app-scaffold
  • Non-D1 databases (Postgres/​MySQL/​etc.) → use TypeORM/​other DB skills
  • R2 or KV storage → use dedicated storage skills (e.g. hono-r2-integration)

If CLAUDE.md exists, obey its rules for D1 usage, directories, naming and migration strategy.


When To Apply This Skill

Trigger this skill when the user asks for things like:

  • “Use D1 as DB for this Hono API on Cloudflare.”
  • “Wire up Hono routes to Cloudflare D1.”
  • “Design tables and queries for D1 in this Worker.”
  • “Refactor my raw D1 queries into a cleaner structure.”
  • “Add migrations/​seeding for D1 in this Hono app.”

Avoid this skill when:

  • The Hono app is not running on Cloudflare Workers / Pages.
  • The project has chosen a different DB for this service (e.g. PlanetScale, Supabase).

Runtime & Binding Assumptions

This skill assumes:

  • The app runs on Cloudflare Workers or Pages Functions.

  • D1 is configured as a binding in wrangler.toml, e.g.:

    [[d1_databases]]
    binding = "DB"
    database_name = "my_db"
    database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
    
  • In code, D1 is available as c.env.DB.

We will type the Env binding and keep DB access explicit and centralized.


Project Structure

This skill works best with a structure like:

src/
  app.ts
  index.ts
  routes/
    v1/
      users.routes.ts
      posts.routes.ts
  db/
    schema.sql
    migrations/
      0001_init.sql
      0002_add_posts.sql
    d1.ts           # D1 helpers and typed Env
  services/
    user.service.ts
    post.service.ts
  types/
    env.d.ts        # Env interface with DB binding

Adjust paths to match the project, but keep D1-related files under a db/ or infrastructure/ style folder.


Typing Env and D1 Binding

Create a shared Env type for Workers:

// src/​types/​env.d.ts
export interface Env {
  DB: D1Database;
  // other bindings e.g. R2, KV, etc.
}

Then in routes/​services:

import type { Env } from "../​types/​env";

export type AppContext = {
  Bindings: Env;
};

Usage with Hono:

import { Hono } from "hono";
import type { AppContext } from "./​types";
export const app = new Hono<AppContext>();

This ensures c.env.DB is correctly typed.


D1 Helper Module

Create a small helper for D1 access and typed operations:

// src/​db/​d1.ts
import type { Env } from "../​types/​env";

export type D1 = D1Database;

export function getDb(env: Env): D1 {
  return env.DB;
}

export async function runQuery<T = unknown>(
  db: D1,
  sql: string,
  params: unknown[] = [],
): Promise<T[]> {
  const stmt = db.prepare(sql);
  const result = await stmt.bind(...params).all<T>();
  return result.results ?? [];
}

For single-row helpers:

export async function runOne<T = unknown>(
  db: D1,
  sql: string,
  params: unknown[] = [],
): Promise<T | null> {
  const rows = await runQuery<T>(db, sql, params);
  return rows[0] ?? null;
}

This skill should:

  • Encourage parameterized queries via .bind(...)
  • Avoid string interpolation that can cause SQL injection

Schema & Migrations

D1 uses schema.sql and migrations managed via Wrangler.

Basic Schema Layout

-- src/​db/​schema.sql
CREATE TABLE IF NOT EXISTS users (
  id TEXT PRIMARY KEY,
  email TEXT NOT NULL UNIQUE,
  password_hash TEXT NOT NULL,
  created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
  updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))
);

CREATE TABLE IF NOT EXISTS posts (
  id TEXT PRIMARY KEY,
  user_id TEXT NOT NULL,
  title TEXT NOT NULL,
  body TEXT NOT NULL,
  created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ', 'now')),
  FOREIGN KEY (user_id) REFERENCES users(id)
);

Migrations are usually created & applied using commands like:

  • wrangler d1 execute <db_name> --file=src/​db/​schema.sql --local
  • wrangler d1 migrations create <db_name> <name>
  • wrangler d1 migrations apply <db_name> --local

This skill should:

  • Suggest migration commands but not assume CLI access inside code.
  • Encourage keeping schema & migration SQL in version control.

Service-Level Access Pattern

Design small services using getDb & query helpers.

Example user.service.ts:

// src/​services/​user.service.ts
import type { Env } from "../​types/​env";
import { getDb, runOne, runQuery } from "../​db/​d1";
import { nanoid } from "nanoid"; // if project uses this for IDs

export type User = {
  id: string;
  email: string;
  password_hash: string;
  created_at: string;
};

export class UserService {
  constructor(private env: Env) {}

  private db() {
    return getDb(this.env);
  }

  async createUser(email: string, passwordHash: string): Promise<User> {
    const id = nanoid();
    const db = this.db();

    await db
      .prepare("INSERT INTO users (id, email, password_hash) VALUES (?, ?, ?)")
      .bind(id, email, passwordHash)
      .run();

    const user = await runOne<User>(db, "SELECT * FROM users WHERE id = ?", [id]);
    if (!user) throw new Error("Failed to load just-created user");

    return user;
  }

  async findByEmail(email: string): Promise<User | null> {
    const db = this.db();
    return runOne<User>(db, "SELECT * FROM users WHERE email = ?", [email]);
  }

  async listUsers(): Promise<User[]> {
    const db = this.db();
    return runQuery<User>(db, "SELECT * FROM users ORDER BY created_at DESC");
  }
}

This skill should:

  • Keep SQL in small, readable strings.
  • Encapsulate DB access in services or repositories, not directly in route handlers (unless trivial).

Using D1 in Hono Routes

Example: a simple users route using UserService:

// src/​routes/​v1/​users.routes.ts
import { Hono } from "hono";
import type { AppContext } from "../​../​types";
import { UserService } from "../​../​services/​user.service";

export function usersRoutes() {
  const app = new Hono<AppContext>();

  app.get("/", async (c) => {
    const service = new UserService(c.env);
    const users = await service.listUsers();
    return c.json(users);
  });

  app.post("/", async (c) => {
    const body = await c.req.json<{ email: string; password: string }>();
    // Validate body with a validation skill if present

    const service = new UserService(c.env);
    // Password hashing is done via auth skill (bcrypt/​argon2) – here we assume `passwordHash`
    const passwordHash = "TODO"; // placeholder

    const user = await service.createUser(body.email, passwordHash);
    return c.json(user, 201);
  });

  return app;
}

This skill should:

  • Encourage injecting env into services (no global state).
  • Allow composition with hono-authentication (e.g., using D1 to fetch user in login).

Transactions and Limits

D1 has more limited transaction semantics than full-blown SQL servers.

This skill should:

  • Prefer simple, single-statement operations where possible.
  • For multi-step operations, suggest careful ordering and error handling.
  • Explicitly avoid patterns that rely on long-lived transactions or complex isolation.

Type Safety Strategies

D1 returns rows as plain JS objects. This skill should:

  • Define TypeScript types (User, Post, etc.) that match the schema.
  • Use generic helpers (runQuery<T>) to type results.
  • Optionally validate results in service logic (e.g., Zod) if project wants stronger runtime guarantees.

Local Development & Testing

This skill can suggest:

  • Using wrangler d1 with --local for dev.
  • Seeding data via SQL files or small scripts.
  • For unit tests, mocking D1 methods instead of hitting real DB:
const mockDb: Partial<D1Database> = {
  prepare: jest.fn().mockReturnValue({
    bind: jest.fn().mockReturnThis(),
    all: jest.fn().mockResolvedValue({ results: [] }),
    run: jest.fn().mockResolvedValue({}),
  }),
};
  • For integration tests in Workers env, tests can use wrangler d1 to prepare DB before running.

When combined with a Hono testing skill, this gives end-to-end coverage.


Error Handling

This skill must:

  • Wrap database errors with useful messages when needed.
  • Let general error-handling middleware (from hono-app-scaffold) convert them into HTTP responses.
  • Avoid leaking sensitive data (SQL text, connection details) in responses.

Example pattern:

try {
  // D1 call
} catch (err) {
  console.error("D1 query failed:", err);
  throw new Error("Database error");
}

The error-handler middleware can then map Error("Database error") to a 500 JSON payload.


Example Prompts That Should Use This Skill

  • “Use Cloudflare D1 for persistence in this Hono API.”
  • “Create D1 schema and wire up user routes in Hono.”
  • “Refactor my raw D1 queries into a service layer.”
  • “Help me design D1 tables + queries for this feature.”
  • “Make D1 usage type-safe and structured in this Worker.”

For these tasks, rely on this skill to produce a clean, Hono-friendly D1 integration that is typed, bound via the Env, and ready for production on Cloudflare Workers/​Pages.

More skills from mattnigh

spring-framework-patterns logo
mattnigh/skills_collection

spring-framework-patterns

Comprehensive Spring Framework and Spring Boot best practices including dependency injection patterns, bean lifecycle and scopes, REST API development, Spring Data JPA, service layer design, Spring Security, testing strategies, caching, AOP, async processing, error handling, and common anti-patte...

24 0
View

TypeScript厳格モードによる型安全性設計を専門とするスキル。 📖 参照書籍: - 『Effective TypeScript』(Dan Vanderkam): 型設計 📚 リソース参照: - `resources/Level1_basics.md`: レベル1の基礎ガイド - `resources/Level2_intermediate.md`: レベル2の実務ガイド - `resources/Level3_advanced.md`: レベル3の応用ガイド - `resources/Level4_expert.md`: レベル4の専門ガイド - `resources/di...

24 0
View
deploying-cloud-k8s logo
mattnigh/skills_collection

deploying-cloud-k8s

Deploys applications to cloud Kubernetes (AKS/GKE/DOKS) with CI/CD pipelines. Use when deploying to production, setting up GitHub Actions, troubleshooting deployments. Covers build-time vs runtime vars, architecture matching, and battle-tested debugging.

24 0
View
moai-alfred-agent-guide logo
mattnigh/skills_collection

moai-alfred-agent-guide

19-agent team structure, decision trees for agent selection, Haiku vs Sonnet model selection, and agent collaboration principles. Use when deciding which sub-agent to invoke, understanding team responsibilities, or learning multi-agent orchestration.

24 0
View
mermaid-diagram-generator logo
mattnigh/skills_collection

mermaid-diagram-generator

Converts architecture descriptions, module specs, or workflow docs into Mermaid diagrams. Use when visualizing brick module relationships, workflows (DDD, investigation), or system architecture. Supports: flowcharts, sequence diagrams, class diagrams, state machines, entity relationship diagrams,...

24 0
View
pre-flight-check logo
mattnigh/skills_collection

pre-flight-check

INVOKE FIRST before any code work. Validates git workflow (branch, issue, worklog) and checks approach. Use at START of every task and END before completing. Prevents skipped steps.

24 0
View
browser-dev-tools logo
mattnigh/skills_collection

browser-dev-tools

This skill should be used when working with browser-rendered artifacts (i.e. Bun, React/React Native) to proactively validate that development work on localhost is being built appropriately and to support debugging browser-rendered content. Use this skill after making frontend changes to verify t...

24 0
View
lead-dev logo
mattnigh/skills_collection

lead-dev

Lead Développeur - Coordination technique opérationnelle, code review, mentoring et livraison. Pair de web-dev-process au niveau OPÉRATIONS.

24 0
View
worker-monitor logo
mattnigh/skills_collection

worker-monitor

Monitor Docker workers, RQ queue health, and auto-scale workers (max 4). Use when: checking job progress, monitoring queue depth, scaling workers up/down, diagnosing slow processing, or waiting for jobs to complete. Referenced by data-quality skill during reprocessing.

24 0
View
quality-advisor logo
mattnigh/skills_collection

quality-advisor

Proactive quality guidance system that monitors artifact creation and provides real-time feedback on documentation quality

24 0
View
bump-version logo
mattnigh/skills_collection

bump-version

This skill should be used when the user wants to bump the version number in the workspace. It updates versions across all pyproject.toml files (root, tde, and tda packages) and the CHANGELOG.md to keep them synchronized.

24 0
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View