What Even is the Best Stack? 🤔
As developers, we are constantly in pursuit of the best way to build applications that are frictionless, scalable, and a joy to work with. The ecosystem is filled with countless frameworks, libraries, and tools, each promising to make development easier. But what if there was a stack that combined performance, simplicity, and flexibility?
Enter theHONC Stack.
What is the HONC Stack?
HONC is a modern full-stack development approach optimized for speed, developer experience, and global scalability. It stands for:
- H –Hono: A lightweight, fast, and Edge-first web framework for building APIs and applications.
- O –Drizzle ORM: A type-safe ORM designed for SQL databases with a great developer experience.
- N –Name your Database: Whether it'sCloudflare D1(SQLite on the Edge),Neon (serverless Postgres), or any other preferred database, HONC allows for flexibility.
- C –Cloudflare: A powerful developer platform offering Workers, KV, R2, D1, and more, making it an ideal environment for deploying modern apps at the Edge.
Why the HONC Stack?
The HONC stack is designed to take advantage of modern cloud and Edge computing principles, enabling developers to:
- ⚡ Build fast, globally distributed applications with Cloudflare Workers and Hono.
- 🛡️ Ensure type safety and maintainability with Drizzle ORM.
- 🗃️ Use a flexible database solution depending on the use case.
- 🚀 Deploy effortlessly with Cloudflare’s robust global infrastructure.
Getting Started with HONC
Want to try the HONC stack for yourself? Setting up a new project is as easy as running:
npm create honc-app@latest
This command sets up a new application with Hono, Drizzle ORM, and Cloudflare Worker bindings pre-configured. During setup, you’ll be prompted to choose a template. Select theD1 base template to ensure your application is optimized for Cloudflare D1 as the database solution.
Build a Bookmark Manager with the HONC Stack
To showcase the HONC Stack in action, let's build a simpleBookmark Manager that allows users to:
- Add bookmarks (title, URL, description, tags)
- View saved bookmarks
- Delete bookmarks
Set Up Your HONC App
This part was already done in the step above, go ahead and run the application using:
npm run db:setupnpm run dev
Configure Cloudflare D1
Let's create a new D1 database:
npx wrangler d1 create bookmarks_db
Add it towrangler.toml
and update the database name inpackage.json
scripts accordingly:
[[d1_databases]]binding="DB"database_name="bookmarks_db"database_id="<your-database-id>"migrations_dir="drizzle/migrations"
Define the Database Schema (Drizzle ORM)
Update theschema.ts
to define the bookmarks table:
import{sql}from'drizzle-orm';import{integer,sqliteTable,text}from'drizzle-orm/sqlite-core';exporttypeNewBookmark=typeofbookmarks.$inferInsert;exportconstbookmarks=sqliteTable('bookmarks',{id:integer('id',{mode:'number'}).primaryKey(),title:text('title').notNull(),url:text('url').notNull(),description:text('description'),tags:text('tags'),createdAt:text('created_at').notNull().default(sql`(CURRENT_TIMESTAMP)`)});
Create API Routes with OpenAPI (Hono)
Next, update theindex.ts
to define API endpoints with OpenAPI support:
import{drizzle,typeDrizzleD1Database}from"drizzle-orm/d1";import{eq}from"drizzle-orm";import{createFiberplane}from"@fiberplane/hono";import{OpenAPIHono,createRoute,z}from"@hono/zod-openapi";import*asschemafrom"./db/schema";typeBindings={DB:D1Database;};typeVariables={db:DrizzleD1Database;};constapp=newOpenAPIHono<{Bindings:Bindings;Variables:Variables}>();app.use(async(c,next)=>{constdb=drizzle(c.env.DB);c.set("db",db);awaitnext();});constBookmarkSchema=z.object({id:z.number().openapi({example:1}),title:z.string().openapi({example:"My Bookmark"}),url:z.string().url().openapi({example:"https://example.com"}),description:z.string().optional().openapi({example:"A useful link"}),tags:z.string().optional().openapi({example:"tech, coding"}),}).openapi("Bookmark");constgetBookmarks=createRoute({method:'get',path:'/api/bookmarks',responses:{200:{content:{'application/json':{schema:z.array(BookmarkSchema)}},description:'Bookmarks fetched successfully',},},});constcreateBookmark=createRoute({method:"post",path:"/api/bookmark",request:{body:{required:true,content:{"application/json":{schema:BookmarkSchema,},},},},responses:{201:{content:{"application/json":{schema:BookmarkSchema,},},description:"Bookmark created successfully",},},});constdeleteBookmark=createRoute({method:'delete',path:'/api/bookmark/{id}',responses:{200:{content:{'application/json':{schema:z.object({message:z.string()})},},description:'Bookmark deleted successfully',},},});app.openapi(getBookmarks,async(c)=>{constdb=c.get("db");constbookmarks=awaitdb.select().from(schema.bookmarks);returnc.json(bookmarks);});app.openapi(createBookmark,async(c)=>{constdb=c.get("db");const{title,url,description,tags}=c.req.valid("json");const[newBookmark]=awaitdb.insert(schema.bookmarks).values({title,url,description,tags}).returning();returnc.json(newBookmark,201);});exportdefaultapp;
Seed the Database
To populate the database with actual sample bookmarks, update the existingscripts/seed.ts
file to include:
import{bookmarks}from'./src/db/schema';...constsampleBookmarks=[{title:"Hono Framework",url:"https://hono.dev",description:"A lightweight web framework for building APIs and applications.",tags:"hono, framework, edge",},{title:"Drizzle ORM",url:"https://orm.drizzle.team",description:"A type-safe ORM designed for SQL databases.",tags:"orm, database, typescript",},{title:"Cloudflare D1",url:"https://developers.cloudflare.com/d1/",description:"Cloudflare’s globally distributed, serverless database.",tags:"cloudflare, database, d1",},{title:"HTMX",url:"https://htmx.org",description:"A library that allows access to modern browser features directly from HTML.",tags:"htmx, frontend, html",},{title:"MDN Web Docs",url:"https://developer.mozilla.org",description:"Comprehensive documentation for web technologies.",tags:"documentation, web, mdn",},];seedDatabase();asyncfunctionseedDatabase(){...try{awaitdb.insert(bookmarks).values(sampleBookmarks);console.log('✅ Database seeded successfully!');if(!isProd){}}catch(error){console.error('❌ Error seeding database:',error);process.exit(1);}finally{process.exit(0);}}
Build a Frontend with Hono JSX Renderer
Use Hono's JSX renderer to serve the frontend dynamically:
import{jsxRenderer}from'hono/jsx-renderer';app.use('*',jsxRenderer());app.get('/',async(c)=>{constdb=c.get('db');constbookmarks:Bookmark[]=awaitdb.select().from(schema.bookmarks);returnc.render(<html><head><title>Bookmark Manager</title><scriptsrc="https://cdn.tailwindcss.com"></script><scriptsrc="https://unpkg.com/htmx.org@1.9.5"></script></head><bodyclass="bg-gray-100 min-h-screen"><h1class="text-4xl text-center font-bold mb-4 my-6">📌 Bookmark Manager</h1><divclass="max-w-xl w-full mx-auto bg-white p-6 my-6 rounded shadow-md"><formhx-post="/api/bookmark"hx-target="#bookmarkList"hx-swap="beforeend"class="flex flex-col gap-2 mb-4"><inputtype="text"name="title"placeholder="Title"requiredclass="border p-2 rounded"/><inputtype="url"name="url"placeholder="URL"requiredclass="border p-2 rounded"/>{/* Description and Tags (optional) */}<inputtype="text"name="description"placeholder="Description"class="border p-2 rounded"/><inputtype="text"name="tags"placeholder="Tags (comma-separated)"class="border p-2 rounded"/><buttontype="submit"class="bg-blue-600 text-white py-2 px-4 rounded hover:bg-blue-700"> Add Bookmark</button></form></div><ulid="bookmarkList"class="space-y-2 max-w-xl w-full mx-auto">{bookmarks.map((b)=>(<liclass="p-2 border rounded flex justify-between items-center bg-white"id={`bookmark-${b.id}`}><divclass="flex flex-col"><spanclass="font-semibold">{b.title}</span><small>{b.description}</small><smallclass="text-gray-500">{b.tags??''}</small></div><divclass="space-x-2"><ahref={b.url}target="_blank"class="text-blue-600 hover:underline"> Visit</a><buttonhx-delete={`/api/bookmark/${b.id}`}hx-target={`#bookmark-${b.id}`}hx-swap="outerHTML"class="bg-red-500 text-white px-2 py-1 rounded hover:bg-red-600"> Delete</button></div></li>))}</ul></body></html>);});
To serve the frontend with JSX, rename your entry files to .tsx (for example, index.tsx) instead of .ts, ensuring that Hono can properly compile and serve JSX. For the full code checkout theGitHub Repo.
Deploy Everything to Cloudflare
Afterwards, run the migration script for production and optionally seed the database:
npm run db:migrate:prodnpm run db:seed:prod
Finally, deploy to production:
npm run deploy
The Bookmark Manager is now live with a minimal frontend!
Wrapping Up
The HONC stack makes it easy to build modern, efficient applications. Try it out and start building today!
Top comments(2)

- LocationNetherlands
- WorkDeveloper Advocate at Cloudflare
- Joined
Yes! App lives here:bookmark-app.lauragift.workers.dev/
For further actions, you may consider blocking this person and/orreporting abuse