First Worker
Scaffold a Hono-based Worker, run it locally, and deploy to Cloudflare’s edge. This is the starting point for the Webhook Hub project.
Prerequisites: Platform Model, Workers
Scaffold the Project
npm create cloudflare@latest webhook-hub -- --template=hono
cd webhook-hub
The scaffolder creates a working project with Hono, TypeScript, and a wrangler.jsonc config. You can deploy immediately or customize first.
Project Structure
webhook-hub/
├── src/
│ └── index.ts # Hono app (your code)
├── worker-configuration.d.ts # Auto-generated binding types
├── wrangler.jsonc # Cloudflare config
├── package.json
└── tsconfig.json
Understanding wrangler.jsonc
The generated config is minimal:
{
"name": "webhook-hub",
"main": "src/index.ts",
"compatibility_date": "2025-01-01",
"compatibility_flags": ["nodejs_compat"]
}
Key fields:
name- Worker name (also the default*.workers.devsubdomain)main- entry pointcompatibility_date- locks runtime behavior to a point in time (update periodically)compatibility_flags- enables features like Node.js built-in support
As you add services (D1, R2, KV), you add binding declarations here. Each subsequent quickstart shows the new config section.
Typed Environment Bindings
Run npx wrangler types to generate worker-configuration.d.ts. This file contains TypeScript types for all your bindings declared in wrangler.jsonc:
npx wrangler types
For a fresh project with no bindings, it generates an empty Env interface. As you add D1, R2, KV bindings to wrangler.jsonc, re-run the command and the interface updates automatically.
// worker-configuration.d.ts (auto-generated)
interface Env {
// Bindings appear here after you add them to wrangler.jsonc
// and re-run `npx wrangler types`
}
Use this type with Hono’s generic parameter so c.env is fully typed:
import { Hono } from "hono";
// Use the auto-generated Env type from worker-configuration.d.ts
const app = new Hono<{ Bindings: Env }>();
Tip: Add
npx wrangler typesto your build script or run it after changingwrangler.jsonc. It keeps your types in sync with your config automatically.
Write a Hono App
Replace src/index.ts with a basic API:
import { Hono } from "hono";
const app = new Hono<{ Bindings: Env }>();
app.get("/", (c) => {
return c.json({ name: "Webhook Hub", status: "running" });
});
app.get("/health", (c) => {
return c.text("ok");
});
app.post("/webhook/:source", async (c) => {
const source = c.req.param("source");
const payload = await c.req.json();
// For now, echo the payload back. Later quickstarts add D1, R2, KV.
return c.json({ received: true, source, payload }, 202);
});
// 404 fallback
app.notFound((c) => {
return c.json({ error: "not found" }, 404);
});
export default app;
Three things to notice:
Hono<{ Bindings: Env }>- passes the auto-generatedEnvtype soc.envis typedc.req.param("source")- Hono’s typed route parametersexport default app- Hono implements the Workerfetchhandler interface, so this just works
Local Development
npx wrangler dev
This starts workerd locally on http://localhost:8787 with hot reload. Test your routes:
# Health check
curl http://localhost:8787/health
# Post a test webhook
curl -X POST http://localhost:8787/webhook/github \
-H "Content-Type: application/json" \
-d '{"event": "push", "repo": "my-project"}'
wrangler dev runs on the same workerd runtime as production. If it works locally, it works deployed.
Deploy
npx wrangler deploy
First deploy prompts you to log in (if you haven’t). After that, your Worker is live at:
https://webhook-hub.<your-subdomain>.workers.dev
Every subsequent npx wrangler deploy pushes updates in seconds. No build pipeline, no container images, no cold starts.
Error Handling
Add a global error handler so uncaught exceptions return JSON instead of a bare 500:
app.onError((err, c) => {
console.error(`${c.req.method} ${c.req.path}:`, err.message);
return c.json({ error: "internal server error" }, 500);
});
In production, errors logged with console.error appear in npx wrangler tail (live log stream) and in the Workers dashboard under Logs.
Viewing Logs
# Stream live logs from your deployed Worker
npx wrangler tail
This shows every request with status code, timing, and any console.log output. Essential for debugging in production.
What’s Next
This Worker becomes the Webhook Hub API in later quickstarts. Each one adds a Cloudflare service:
- D1 CRUD - store webhook payloads in a database
- R2 Files - offload large payloads to object storage
- KV Caching - add per-source rate limiting
- Turnstile - protect the dashboard with bot verification
For deeper coverage of wrangler, Vitest, and the Vite plugin, see Dev Tooling.