Skip to main content Skills Marketplace コミュニティが作成したAIスキルを発見・探索
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
直接コマンドでは確認用 Prompt が省略されます。実行前にソースを確認してください。
npx skills add https://github.com/bobmatnyc/claude-mpm-skills --skill hono-cloudflareコマンドは1行のまま表示されます。コピー前に横へスクロールして全体を確認してください。
ローカルで確認しますか?SkillsMP が現在取得できるファイルをダウンロードできます。
Zipをダウンロード ダウンロード中... name hono-cloudflare description Hono on Cloudflare Workers - bindings, KV, D1, R2, Durable Objects, and edge deployment patterns user-invocable false disable-model-invocation true skill_version 1.0.0 updated_at "2025-01-03T00:00:00.000Z" tags ["hono","cloudflare-workers","edge","kv","d1","r2","durable-objects","serverless"] progressive_disclosure {"entry_point":{"summary":"Deploy Hono to Cloudflare Workers with KV, D1, R2, and Durable Objects bindings","when_to_use":"Building edge applications on Cloudflare with Workers, Pages, or serverless functions","quick_start":"1. npm create hono@latest (cloudflare-workers) 2. Configure wrangler.toml 3. npx wrangler deploy"},"references":[]} context_limit 800
Hono on Cloudflare Workers
Overview
Hono was originally built for Cloudflare Workers and provides first-class support for the entire Cloudflare ecosystem including KV, D1, R2, Durable Objects, Queues, and more.
Key Features :
Native Workers support
Type-safe bindings access
KV, D1, R2, Durable Objects integration
Static asset serving
Cloudflare Pages support
Queue and scheduled handlers
When to Use This Skill
Use Hono on Cloudflare when:
Building edge APIs with global distribution
Need serverless SQLite with D1
Building real-time apps with Durable Objects
Storing files with R2
Need fast key-value storage with KV
Deploying full-stack apps to Pages
Quick Start
Create New Project
npm create hono@latest my-app
cd my-app
npm install
npm run dev
Project Structure
my-app/
├── src/
│ └── index.ts # Main entry point
├── wrangler.toml # Cloudflare configuration
├── package.json
└── tsconfig.json
Basic Application
import { Hono } from 'hono'
const app = new Hono ()
app.get ('/' , (c ) => c.text ('Hello Cloudflare Workers!' ))
export default app
Deploy
npx wrangler deploy
npx wrangler dev
Environment Bindings
Typed Bindings
import { Hono }
= {
:
:
:
: D1Database
: R2Bucket
:
:
}
app = <{ : }>()
app. ( , {
apiKey = c. .
c. ({ : !!apiKey })
})
app
from
'hono'
type
Bindings
API_KEY
string
DATABASE_URL
string
MY_KV
KVNamespace
DB
BUCKET
COUNTER
DurableObjectNamespace
MY_QUEUE
Queue
const
new
Hono
Bindings
Bindings
get
'/config'
(c ) =>
const
env
API_KEY
return
json
configured
export
default
wrangler.toml Configuration name = "my-app"
main = "src/index.ts"
compatibility_date = "2024-01-01"
[vars]
API_KEY = "your-api-key"
[[kv_namespaces]]
binding = "MY_KV"
id = "your-kv-id"
[[d1_databases]]
binding = "DB"
database_name = "my-database"
database_id = "your-d1-id"
[[r2_buckets]]
binding = "BUCKET"
bucket_name = "my-bucket"
[[queues.producers]]
binding = "MY_QUEUE"
queue = "my-queue"
KV Storage
Basic Operations type Bindings = {
CACHE : KVNamespace
}
const app = new Hono <{ Bindings : Bindings }>()
app.get ('/cache/:key' , async (c) => {
const key = c.req .param ('key' )
const value = await c.env .CACHE .get (key)
if (!value) {
return c.json ({ error : 'Not found' }, 404 )
}
return c.json ({ key, value })
})
app.get ('/cache/:key/json' , async (c) => {
const key = c.req .param ('key' )
const value = await c.env .CACHE .get (key, 'json' )
return c.json ({ key, value })
})
app.put ('/cache/:key' , async (c) => {
const key = c.req .param ('key' )
const body = await c.req .json ()
await c.env .CACHE .put (key, JSON .stringify (body), {
expirationTtl : 3600
})
return c.json ({ success : true })
})
app.delete ('/cache/:key' , async (c) => {
const key = c.req .param ('key' )
await c.env .CACHE .delete (key)
return c.json ({ success : true })
})
app.get ('/cache' , async (c) => {
const prefix = c.req .query ('prefix' ) || ''
const list = await c.env .CACHE .list ({ prefix, limit : 100 })
return c.json ({ keys : list.keys })
})
KV with Metadata interface UserMeta {
createdAt : string
role : string
}
app.put ('/users/:id' , async (c) => {
const id = c.req .param ('id' )
const user = await c.req .json ()
await c.env .CACHE .put (`user:${id} ` , JSON .stringify (user), {
metadata : {
createdAt : new Date ().toISOString (),
role : user.role
} as UserMeta
})
return c.json ({ success : true })
})
app.get ('/users/:id' , async (c) => {
const id = c.req .param ('id' )
const { value, metadata } = await c.env .CACHE .getWithMetadata <UserMeta >(`user:${id} ` , 'json' )
if (!value) {
return c.json ({ error : 'Not found' }, 404 )
}
return c.json ({ user : value, metadata })
})
D1 Database
Basic Queries type Bindings = {
DB : D1Database
}
const app = new Hono <{ Bindings : Bindings }>()
app.get ('/users' , async (c) => {
const { results } = await c.env .DB
.prepare ('SELECT * FROM users ORDER BY created_at DESC' )
.all ()
return c.json ({ users : results })
})
app.get ('/users/:id' , async (c) => {
const id = c.req .param ('id' )
const user = await c.env .DB
.prepare ('SELECT * FROM users WHERE id = ?' )
.bind (id)
.first ()
if (!user) {
return c.json ({ error : 'Not found' }, 404 )
}
return c.json ({ user })
})
app.post ('/users' , async (c) => {
const { name, email } = await c.req .json ()
const result = await c.env .DB
.prepare ('INSERT INTO users (name, email) VALUES (?, ?)' )
.bind (name, email)
.run ()
return c.json ({
success : result.success ,
id : result.meta .last_row_id
}, 201 )
})
app.put ('/users/:id' , async (c) => {
const id = c.req .param ('id' )
const { name, email } = await c.req .json ()
const result = await c.env .DB
.prepare ('UPDATE users SET name = ?, email = ? WHERE id = ?' )
.bind (name, email, id)
.run ()
return c.json ({ success : result.success })
})
app.delete ('/users/:id' , async (c) => {
const id = c.req .param ('id' )
const result = await c.env .DB
.prepare ('DELETE FROM users WHERE id = ?' )
.bind (id)
.run ()
return c.json ({ success : result.success })
})
Batch Operations app.post ('/users/batch' , async (c) => {
const { users } = await c.req .json ()
const statements = users.map ((user : { name: string ; email: string } ) =>
c.env .DB
.prepare ('INSERT INTO users (name, email) VALUES (?, ?)' )
.bind (user.name , user.email )
)
const results = await c.env .DB .batch (statements)
return c.json ({
success : results.every (r => r.success ),
count : results.length
})
})
R2 Object Storage type Bindings = {
BUCKET : R2Bucket
}
const app = new Hono <{ Bindings : Bindings }>()
app.post ('/files/:key' , async (c) => {
const key = c.req .param ('key' )
const body = await c.req .arrayBuffer ()
const contentType = c.req .header ('Content-Type' ) || 'application/octet-stream'
await c.env .BUCKET .put (key, body, {
httpMetadata : { contentType }
})
return c.json ({ success : true , key })
})
app.get ('/files/:key' , async (c) => {
const key = c.req .param ('key' )
const object = await c.env .BUCKET .get (key)
if (!object ) {
return c.json ({ error : 'Not found' }, 404 )
}
const headers = new Headers ()
headers.set ('Content-Type' , object .httpMetadata ?.contentType || 'application/octet-stream' )
headers.set ('ETag' , object .httpEtag )
return new Response (object .body , { headers })
})
app.delete ('/files/:key' , async (c) => {
const key = c.req .param ('key' )
await c.env .BUCKET .delete (key)
return c.json ({ success : true })
})
app.get ('/files' , async (c) => {
const prefix = c.req .query ('prefix' ) || ''
const list = await c.env .BUCKET .list ({ prefix, limit : 100 })
return c.json ({
objects : list.objects .map (obj => ({
key : obj.key ,
size : obj.size ,
uploaded : obj.uploaded
}))
})
})
Durable Objects
Define Durable Object
export class Counter {
private state : DurableObjectState
private value : number = 0
constructor (state : DurableObjectState ) {
this .state = state
}
async fetch (request : Request ): Promise <Response > {
const url = new URL (request.url )
this .value = await this .state .storage .get ('value' ) || 0
switch (url.pathname ) {
case '/increment' :
this .value ++
await this .state .storage .put ('value' , this .value )
return new Response (String (this .value ))
case '/decrement' :
this .value --
await this .state .storage .put ('value' , this .value )
return new Response (String (this .value ))
case '/value' :
return new Response (String (this .value ))
default :
return new Response ('Not found' , { status : 404 })
}
}
}
Use in Hono import { Hono } from 'hono'
type Bindings = {
COUNTER : DurableObjectNamespace
}
const app = new Hono <{ Bindings : Bindings }>()
app.get ('/counter/:name/increment' , async (c) => {
const name = c.req .param ('name' )
const id = c.env .COUNTER .idFromName (name)
const stub = c.env .COUNTER .get (id)
const response = await stub.fetch ('http://counter/increment' )
const value = await response.text ()
return c.json ({ name, value : parseInt (value) })
})
app.get ('/counter/:name' , async (c) => {
const name = c.req .param ('name' )
const id = c.env .COUNTER .idFromName (name)
const stub = c.env .COUNTER .get (id)
const response = await stub.fetch ('http://counter/value' )
const value = await response.text ()
return c.json ({ name, value : parseInt (value) })
})
export default app
export { Counter }
wrangler.toml for Durable Objects [[durable_objects.bindings]]
name = "COUNTER"
class_name = "Counter"
[[migrations]]
tag = "v1"
new_classes = ["Counter" ]
Queues
Producer type Bindings = {
MY_QUEUE : Queue
}
const app = new Hono <{ Bindings : Bindings }>()
app.post ('/tasks' , async (c) => {
const task = await c.req .json ()
await c.env .MY_QUEUE .send ({
type : 'process' ,
data : task
})
return c.json ({ queued : true })
})
app.post ('/tasks/batch' , async (c) => {
const { tasks } = await c.req .json ()
await c.env .MY_QUEUE .sendBatch (
tasks.map ((task : any ) => ({
body : { type : 'process' , data : task }
}))
)
return c.json ({ queued : tasks.length })
})
Consumer export default {
fetch : app.fetch ,
async queue (batch : MessageBatch , env : Bindings ): Promise <void > {
for (const message of batch.messages ) {
const { type , data } = message.body as { type : string ; data : any }
try {
console .log (`Processing ${type } :` , data)
message.ack ()
} catch (error) {
message.retry ()
}
}
}
}
Static Assets
wrangler.toml name = "my-app"
main = "src/index.ts"
compatibility_date = "2024-01-01"
assets = { directory = "public" }
With Route Handler import { Hono } from 'hono'
import { serveStatic } from 'hono/cloudflare-workers'
const app = new Hono ()
app.use ('/static/*' , serveStatic ({ root : './' }))
app.get ('/api/hello' , (c ) => c.json ({ hello : 'world' }))
export default app
Scheduled Events (Cron) import { Hono } from 'hono'
const app = new Hono ()
export default {
fetch : app.fetch ,
async scheduled (
event : ScheduledEvent ,
env : Bindings ,
ctx : ExecutionContext
): Promise <void > {
switch (event.cron ) {
case '0 * * * *' :
await hourlyTask (env)
break
case '0 0 * * *' :
await dailyTask (env)
break
}
}
}
async function hourlyTask (env : Bindings ) {
console .log ('Running hourly task' )
}
async function dailyTask (env : Bindings ) {
console .log ('Running daily task' )
}
wrangler.toml for Cron [triggers]
crons = ["0 * * * *" , "0 0 * * *" ]
Cloudflare Pages
pages/functions Directory my-app/
├── public/ # Static assets
│ ├── index.html
│ └── styles.css
└── functions/
└── [[path]].ts # Catch-all function
Catch-All Handler
import { Hono } from 'hono'
import { handle } from 'hono/cloudflare-pages'
const app = new Hono ().basePath ('/api' )
app.get ('/hello' , (c ) => c.json ({ hello : 'world' }))
app.post ('/echo' , async (c) => c.json (await c.req .json ()))
export const onRequest = handle (app)
Middleware with Bindings import { createMiddleware } from 'hono/factory'
type Bindings = {
API_KEY : string
}
const authMiddleware = createMiddleware<{ Bindings : Bindings }>(
async (c, next) => {
const apiKey = c.req .header ('X-API-Key' )
if (apiKey !== c.env .API_KEY ) {
return c.json ({ error : 'Unauthorized' }, 401 )
}
await next ()
}
)
app.use ('/api/*' , authMiddleware)
Quick Reference
Bindings Types type Bindings = {
MY_VAR : string
MY_KV : KVNamespace
DB : D1Database
BUCKET : R2Bucket
MY_DO : DurableObjectNamespace
MY_QUEUE : Queue
OTHER_WORKER : Fetcher
}
Common Commands
npx wrangler dev
npx wrangler deploy
npx wrangler d1 create my-database
npx wrangler d1 execute my-database --file=schema.sql
npx wrangler kv:namespace create MY_KV
npx wrangler r2 bucket create my-bucket
npx wrangler tail
Related Skills
hono-core - Framework fundamentals
hono-middleware - Middleware patterns
hono-testing - Testing with mocked bindings
Version : Hono 4.x, Wrangler 3.x
Last Updated : January 2025
License : MIT