Prerequisites
Before you begin, make sure you have the following:- A GitHub account (for version control and deploying to platforms like Vercel or Cloudflare)
- Node.js installed (with npm or pnpm)
- VS Code (recommended IDE for TypeScript development)
- A PlanetScale account (for MySQL, if chosen)
- A Neon account (for PostgreSQL, if chosen)
- An Upstash account (for Redis caching)
- A Growthbook account (for feature flagging)
- A Clerk account (for authentication)
- A Vercel account (for Vercel deployment)
- A Cloudflare account (for Cloudflare Workers deployment)
api.example.com as a placeholder for your custom API domain.
Step 1: Local setup
First, you’ll need to initialize your Hono project and set up the development environment. This guide emphasizes a clean and organized approach from the start.Initialize Hono project
source directory with an index.ts (sometimes like in my case its case, its app.ts)file for your main Hono application. You can specify a project name like “tasks API” and choose Node.js for deployment, but note Hono’s runtime-agnostic nature and I prefer Cloudflare Workers as Client has limited initial set budget.Install dependencies
tsx for serving the application locally, and you’ll add others like Prisma and Drizzle later.Set up ESLint
Set up environment variables
.env file in your project root to store your environment variables. This file will hold sensitive information like API keys and database connection strings. You will fill in more variables in the following steps for your database, caching, and authentication services.Step 2: Configure Hono Application Structure and Core Utilities
Organize your Hono application for clarity and maintainability, especially when integrating with OpenAPI. This guide emphasizes a scalable approach where route definitions are separated from handlers, while maintaining full type safety.Define application files
app.ts file, keeping it distinct from Node-specific configurations (like index.ts for local server setup). This makes your Hono app runtime-agnostic and flexible for deployment to different platforms like Vercel or Cloudflare Workers.Implement Custom Not Found Handler
notFound handler to gracefully manage 404 errors in your API. You can use a utility from a library like “Stoker” for this purpose. The source code for “Stoker” is available on GitHub if you prefer not to add another dependency.Implement Global Error Handler
Configure Logger (hono-pino)
hono-pino for robust logging. This includes configuring environment-based logging to enable pretty-printed logs in development and JSON logs in production. You can also integrate a custom Pino logger for unique request IDs per incoming request using the Crypto API, ensuring better log traceability. You’ll also need to set up custom TypeScript types to resolve type errors related to the logger.OpenAPI and Zod Integration
Zod OpenAPI middleware, which allows defining schemas with Zod, creating route contracts, and ensuring type safety in request handlers, all automatically converted into interactive documentation.Drizzle and Zod for Database Type Safety
Step 3: Set up Your Database (PlanetScale MySQL or Neon PostgreSQL)
You have the option to use either a MySQL database via PlanetScale or a PostgreSQL database via Neon for your application data. Both integrate well with Prisma or Drizzle.pg installation). For Cloudflare Workers, Turso is suggested for local database simulation.Choose and Create Your Database
Set up Database Environment Variables
DATABASE_URL from the “Add credentials to .env” section into your .env file.For Neon: Navigate to the “Connection Details” for your database and copy the “Direct Connection String”. Paste this as your DATABASE_URL in your .env file.Generate ORM client and create database tables
prisma/schema.prisma or your Drizzle schema file) to define your data models.Then, run the following command to generate the ORM client based on your schema:Step 4: Set up Upstash Redis database
Next, you’ll need to set up the Upstash Redis database. This can be used for caching, rate limiting, session management, or other real-time data needs in your Hono API. Upstash provides a serverless Redis solution.Create Upstash database
Set up Upstash environment variables
UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN from the REST API section into your .env file.Step 5: Set up Clerk for Authentication
Clerk provides a complete user management solution, including authentication, user profiles, and backend verification. It simplifies implementing robust authentication flows.Create Clerk Application
Configure Callback URLs
http://localhost:8888/(or your local Hono API URL)https://api.example.com/(or your deployed Hono API URL)- You might also need to configure specific callback paths for OAuth providers if you enable them within Clerk (e.g.,
https://api.example.com/api/auth/callback/github).
Set up Clerk Environment Variables
.env file. The Secret Key is essential for backend verification.Integrate Clerk with Hono
Step 6: Set up Growthbook for Feature Flagging
Growthbook allows you to implement feature flags and A/B tests in your application, enabling dynamic feature control without redeploying your code.Create Growthbook Account and Project
Get API Key
.env file:Integrate Growthbook with Hono
Step 7: Deploy to Vercel
Once you’ve set up your Hono application and all integrated services, you can now deploy your API to Vercel. Vercel is well-suited for Node.js-based applications.Deploy code to GitHub
Create a new Vercel project
vercel.json or build process to ensure your Hono app builds correctly for the Vercel Edge Runtime or Node.js Runtime.In the Environment Variables section, add all of the environment variables from your .env file.Click on Deploy to deploy your project.Add required environment variables and domains
PROJECT_ID_VERCEL environment variable – both in your .env file and in your newly created Vercel project’s settings (under Settings > Environment Variables).Add your API domain (e.g., api.example.com) as a domain in your Vercel project’s settings (under Settings > Domains). You can follow this guide to learn how to set up a custom domain on Vercel.Redeploy your Vercel project
https://api.example.com) and interact with your deployed Hono API, complete with database integration, caching, feature flags, and robust authentication.Step 8: Deploy to Cloudflare Workers (Alternative to Vercel)
Hono was initially built with Cloudflare Workers in mind, making it an excellent choice for highly performant and scalable serverless functions. The setup differs slightly, particularly in how environment variables are handled.Clone Repository and Install Wrangler
Wrangler, Cloudflare’s CLI tool, as a development dependency for local testing and deployment.Configure Wrangler (`wrangler.toml`)
wrangler.toml file in your project root for Cloudflare Workers configuration. Set the main entry point to your Hono application file (e.g., src/app.ts), which exports the Hono app itself, not a Node.js server.compatibility_date should be set to the current date or a recent date to ensure you’re using the latest Workers features.Update Package.json Scripts
package.json scripts to include dev and deploy commands suitable for Cloudflare Workers using Wrangler.Handle Environment Variables for Cloudflare Workers
fetch event handler, not through process.env. You’ll need to refactor your environment variable handling.Define an Environment type:Rename yourEnvtype toEnvironment(or similar) to align with Hono’s built-in types forc.env.Create a parseEnv function:Export aparseEnvfunction that accepts an object (yourc.envfrom the request context), validates it with Zod (or similar), and returns the validated environment variables. This function should throw an error if validation fails.- Add a middleware for validation: Implement a Hono middleware that runs first, validates
c.envusing yourparseEnvfunction, and ensures environment variables are correctly typed and accessible within request handlers. - Update type bindings: Ensure
c.envis correctly typed asEnvironmentin yourapp.d.tsor similar type definition file. runtime-env.ts for local tools:Create aruntime-env.tsfile to provide a way to accessprocess.envfor local tools (like Drizzle Kit) that run outside the Cloudflare Worker context. This file can export a default parsedprocess.env.
Refactor Database Connection for Workers
- Export a
createDBfunction from your database module (e.g.,src/db/index.ts) that takes theEnvironmentobject (or your parsed environment variables) and returns the database client and instances. - Call this
createDBfunction within each request handler where database access is needed, ensuring the connection uses the environment variables available in the request context.
Local Development with Wrangler and Turso
Wrangler with Turso..dev.vars file:Create a.dev.varsfile (by copying your.env) to store local environment variables for Wrangler. Add this file to your.gitignore.- Install Turso CLI:
pnpm add -D turso dev:db script:Add adev:dbscript topackage.jsonto runturso devfor a local database instance, using a file likedev.db.- Push schema to local DB: Push your Drizzle Kit schema to this local
dev.db. Update DATABASE_URL:Update theDATABASE_URLin.dev.varsto point to the local Turso HTTP API (e.g.,http://127.0.0.1:8080).- Gitignore local DB files: Add
dev.db.*to.gitignore.
Deploy to Cloudflare
- Authenticate: Ensure you are logged into Cloudflare via
wrangler login. - Add Secrets: Manually add your sensitive environment variables (like
CLERK_SECRET_KEY,DATABASE_URL,DATABASE_AUTH_TOKENfor remote DBs) as secrets in the Cloudflare dashboard for your Worker. - Deploy: Run
pnpm run deploy.
Caveats
This guide is meant to be a comprehensive starting point for setting up your Hono API. It currently relies on the following services:- Database: PlanetScale (MySQL) or Neon (PostgreSQL) with Prisma or Drizzle as the ORM. For Cloudflare Workers local development, Turso is recommended.
- Caching/Real-time data: Upstash (Redis)
- Authentication: Clerk for user management and backend verification
- Feature Flagging: Growthbook
- Hosting: Vercel or Cloudflare Workers
- Developer Experience: “Stoker” for boilerplate reduction,
hono-pinofor robust logging, and integration with Zod and OpenAPI for type safety and documentation.