Token导航 LogoToken导航TokenDH.com
前端设计敏感数据github未标认证来源可访问clear审计通过

hono-cloudflarehono Cloudflare 前端

Agent Skill

用于辅助前端页面、组件、样式和交互逻辑的开发与维护。它适合让 Agent 生成或审查 React、Next.js、Vue、Tailwind、CSS 等相关代码,整理组件结构,或定位布局和性能问题。使用时需要结合项目现有设计系统、路由和构建方式,避免只生成孤立片段;涉及页面改动时,应配合本地预览和构建检查确认视觉效果。

总安装

9,160

周安装

367

GitHub Stars

39

下载量

2,965
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:hono-cloudflare(hono Cloudflare 前端)
来源仓库:https://github.com/bobmatnyc/claude-mpm-skills
仓库路径:skills/hono-cloudflare
安装命令:
npx skills add https://github.com/bobmatnyc/claude-mpm-skills --skill hono-cloudflare
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/bobmatnyc/claude-mpm-skills --skill hono-cloudflare

简介

用于辅助前端页面和组件的开发与维护。hono-cloudflare 属于前端设计类 Skill,可作为该场景下的辅助能力补充。

  • 支持 React、Next.js、Vue 等框架的代码生成。
  • 需要结合项目设计系统和构建方式使用。
  • 涉及页面改动时应配合本地预览确认效果。
  • 避免生成孤立片段,需与现有结构保持一致。

SKILL.md

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

# Select: cloudflare-workers

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

// src/index.ts
import { Hono } from 'hono'

const app = new Hono()

app.get('/', (c) => c.text('Hello Cloudflare Workers!'))

export default app

Deploy

# Deploy to Cloudflare
npx wrangler deploy

# Local development
npx wrangler dev

Environment Bindings

Typed Bindings

import { Hono } from 'hono'

// Define your bindings
type Bindings = {
  // Environment variables
  API_KEY: string
  DATABASE_URL: string

  // KV Namespaces
  MY_KV: KVNamespace

  // D1 Databases
  DB: D1Database

  // R2 Buckets
  BUCKET: R2Bucket

  // Durable Objects
  COUNTER: DurableObjectNamespace

  // Queues
  MY_QUEUE: Queue
}

const app = new Hono<{ Bindings: Bindings }>()

app.get('/config', (c) => {
  // Fully typed access
  const apiKey = c.env.API_KEY
  return c.json({ configured: !!apiKey })
})

export default app

wrangler.toml Configuration

name = "my-app"
main = "src/index.ts"
compatibility_date = "2024-01-01"

[vars]
API_KEY = "your-api-key"  # pragma: allowlist secret

[[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 }>()

// Get value
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 })
})

// Get JSON 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 })
})

// Set 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  // 1 hour
  })

  return c.json({ success: true })
})

// Delete value
app.delete('/cache/:key', async (c) => {
  const key = c.req.param('key')
  await c.env.CACHE.delete(key)

  return c.json({ success: true })
})

// List keys
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 }>()

// Select all
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 })
})

// Select one
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 })
})

// Insert
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)
})

// Update
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 })
})

// Delete
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 }>()

// Upload file
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 })
})

// Download file
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 })
})

// Delete file
app.delete('/files/:key', async (c) => {
  const key = c.req.param('key')
  await c.env.BUCKET.delete(key)

  return c.json({ success: true })
})

// List files
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

// src/counter.ts
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)

    // Load value from storage
    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 })
})

// Batch send
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 {
        // Process message
        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"

# Serve static files from public directory
assets = { directory = "public" }

With Route Handler

import { Hono } from 'hono'
import { serveStatic } from 'hono/cloudflare-workers'

const app = new Hono()

// Serve static files
app.use('/static/*', serveStatic({ root: './' }))

// API routes
app.get('/api/hello', (c) => c.json({ hello: 'world' }))

export default app

Scheduled Events (Cron)

import { Hono } from 'hono'

const app = new Hono()

// Regular routes...

export default {
  fetch: app.fetch,

  async scheduled(
    event: ScheduledEvent,
    env: Bindings,
    ctx: ExecutionContext
  ): Promise<void> {
    switch (event.cron) {
      case '0 * * * *':  // Every hour
        await hourlyTask(env)
        break

      case '0 0 * * *':  // Daily at midnight
        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

// functions/[[path]].ts
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
}

// Access env in middleware
const authMiddleware = createMiddleware<{ Bindings: Bindings }>(
  async (c, next) => {
    // Don't access env at module level - access in handler!
    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 = {
  // Variables
  MY_VAR: string

  // KV
  MY_KV: KVNamespace

  // D1
  DB: D1Database

  // R2
  BUCKET: R2Bucket

  // Durable Objects
  MY_DO: DurableObjectNamespace

  // Queues
  MY_QUEUE: Queue

  // Service Bindings
  OTHER_WORKER: Fetcher
}

Common Commands

# Local development
npx wrangler dev

# Deploy
npx wrangler deploy

# Create D1 database
npx wrangler d1 create my-database

# Execute D1 SQL
npx wrangler d1 execute my-database --file=schema.sql

# Create KV namespace
npx wrangler kv:namespace create MY_KV

# Create R2 bucket
npx wrangler r2 bucket create my-bucket

# Tail logs
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

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Claude Code

26.99%
按下载量换算800

OpenCode

23.45%
按下载量换算695

Antigravity

16.71%
按下载量换算495

Gemini CLI

14.09%
按下载量换算418

Codex

7.95%
按下载量换算236

Cursor

3.64%
按下载量换算108

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

敏感数据

该 Skill 可能接触密钥、Token、环境变量或敏感配置,应进入高风险复核队列,默认不自动发布。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。

来源信息

继续浏览同类 Skills