Netlify is a modern web development platform that provides hosting and serverless functions. Deploy your Hono applications to Netlify with seamless integration.
Quick Start
Create a new Hono project for Netlify:
npm create hono@latest my-app
Select “netlify” as your template when prompted.
Installation
Add Hono to your existing Netlify project:
Basic Usage
Create your API in the netlify/functions directory:
import { Hono } from 'hono'
import { handle } from 'hono/netlify'
const app = new Hono ()
app . get ( '/' , ( c ) => c . text ( 'Hello Netlify!' ))
app . get ( '/api/hello' , ( c ) => {
return c . json ({ message: 'Hello from Netlify!' })
})
app . post ( '/api/data' , async ( c ) => {
const body = await c . req . json ()
return c . json ({ received: body })
})
export default handle ( app )
The handle adapter converts your Hono app into a Netlify Function handler.
Catch-All Routes
Handle all routes in a single function using catch-all:
netlify/functions/[[route]].ts
import { Hono } from 'hono'
import { handle } from 'hono/netlify'
const app = new Hono ()
app . get ( '/' , ( c ) => c . text ( 'Home' ))
app . get ( '/about' , ( c ) => c . text ( 'About' ))
app . get ( '/api/users' , ( c ) => c . json ([{ id: 1 , name: 'John' }]))
app . get ( '/api/users/:id' , ( c ) => {
const id = c . req . param ( 'id' )
return c . json ({ id , name: 'John' })
})
export default handle ( app )
Accessing Netlify Context
Access the Netlify context in your handlers:
import { Hono } from 'hono'
import { handle } from 'hono/netlify'
type Bindings = {
context : {
requestId : string
geo : {
city ?: string
country ?: { code : string ; name : string }
}
}
}
const app = new Hono <{ Bindings : Bindings }>()
app . get ( '/context' , ( c ) => {
const context = c . env . context
return c . json ({
requestId: context . requestId ,
country: context . geo . country ?. name ,
})
})
export default handle ( app )
Connection Info
Get connection information:
import { Hono } from 'hono'
import { handle , getConnInfo } from 'hono/netlify'
const app = new Hono ()
app . get ( '/info' , ( c ) => {
const info = getConnInfo ( c )
return c . json ({
remote: info . remote ,
})
})
export default handle ( app )
Environment Variables
Access environment variables:
import { Hono } from 'hono'
import { handle } from 'hono/netlify'
const app = new Hono ()
app . get ( '/config' , ( c ) => {
return c . json ({
apiKey: process . env . API_KEY ,
environment: process . env . CONTEXT , // production, deploy-preview, branch-deploy
})
})
export default handle ( app )
Add environment variables in Netlify:
Go to Site settings → Environment variables
Add your variables
Redeploy your site
Configuration
Create a netlify.toml configuration file:
[ build ]
command = "npm run build"
publish = "dist"
functions = "netlify/functions"
[[ redirects ]]
from = "/api/*"
to = "/.netlify/functions/api/:splat"
status = 200
[[ headers ]]
for = "/api/*"
[ headers . values ]
Access-Control-Allow-Origin = "*"
Access-Control-Allow-Methods = "GET, POST, PUT, DELETE, OPTIONS"
Middleware
CORS
import { Hono } from 'hono'
import { handle } from 'hono/netlify'
import { cors } from 'hono/cors'
const app = new Hono ()
app . use ( '/*' , cors ({
origin: 'https://yourdomain.com' ,
allowMethods: [ 'GET' , 'POST' , 'PUT' , 'DELETE' ],
}))
app . get ( '/data' , ( c ) => c . json ({ message: 'CORS enabled' }))
export default handle ( app )
Logger
import { Hono } from 'hono'
import { handle } from 'hono/netlify'
import { logger } from 'hono/logger'
const app = new Hono ()
app . use ( '*' , logger ())
app . get ( '/' , ( c ) => c . text ( 'Hello!' ))
export default handle ( app )
Deployment
Install Netlify CLI
npm install -g netlify-cli
Deploy via Git
Connect your Git repository to Netlify:
Push your code to GitHub, GitLab, or Bitbucket
Go to Netlify Dashboard
Click “Add new site” → “Import an existing project”
Select your repository
Configure build settings:
Build command: npm run build
Publish directory: dist
Functions directory: netlify/functions
Deploy
Netlify will automatically deploy on every push to your main branch.
Project Structure
Typical Netlify + Hono project structure:
my-netlify-app/
├── netlify/
│ └── functions/
│ ├── api.ts
│ └── [[route]].ts
├── public/
│ └── index.html
├── src/
├── package.json
├── netlify.toml
└── tsconfig.json
Edge Functions
Use Netlify Edge Functions for globally distributed compute:
netlify/edge-functions/api.ts
import { Hono } from 'hono'
const app = new Hono ()
app . get ( '/edge' , ( c ) => {
return c . json ({
message: 'Hello from the edge!' ,
location: c . req . header ( 'x-nf-geo' )
})
})
export default app . fetch
export const config = { path: "/edge/*" }
Edge Functions run on Deno at the edge, closer to your users.
Database Integration
Netlify Blobs
npm install @netlify/blobs
netlify/functions/storage.ts
import { Hono } from 'hono'
import { handle } from 'hono/netlify'
import { getStore } from '@netlify/blobs'
const app = new Hono ()
app . get ( '/blob/:key' , async ( c ) => {
const key = c . req . param ( 'key' )
const store = getStore ( 'my-store' )
const value = await store . get ( key )
if ( ! value ) return c . notFound ()
return c . text ( value )
})
app . post ( '/blob/:key' , async ( c ) => {
const key = c . req . param ( 'key' )
const body = await c . req . text ()
const store = getStore ( 'my-store' )
await store . set ( key , body )
return c . json ({ success: true })
})
export default handle ( app )
External Databases
Connect to external databases like Supabase, PlanetScale, or MongoDB:
import { Hono } from 'hono'
import { handle } from 'hono/netlify'
import { createClient } from '@supabase/supabase-js'
const supabase = createClient (
process . env . SUPABASE_URL ! ,
process . env . SUPABASE_KEY !
)
const app = new Hono ()
app . get ( '/users' , async ( c ) => {
const { data , error } = await supabase
. from ( 'users' )
. select ( '*' )
if ( error ) return c . json ({ error: error . message }, 500 )
return c . json ( data )
})
export default handle ( app )
Handle Netlify Forms:
netlify/functions/form-handler.ts
import { Hono } from 'hono'
import { handle } from 'hono/netlify'
const app = new Hono ()
app . post ( '/submit-form' , async ( c ) => {
const formData = await c . req . formData ()
const name = formData . get ( 'name' )
const email = formData . get ( 'email' )
// Process form data
console . log ({ name , email })
return c . json ({ message: 'Form submitted successfully' })
})
export default handle ( app )
Best Practices
Use [[route]].ts to handle all routes in a single function for better organization.
Use Edge Functions for globally distributed, low-latency APIs.
Use netlify.toml to configure redirects and rewrites.
Use environment variables
Store secrets in Netlify’s environment variables, not in code.
Development
Run locally with Netlify Dev:
This starts a local development server at http://localhost:8888 with hot reload and simulates the production environment.
Use Edge Functions for global distribution
Implement caching with Netlify Blobs
Optimize function bundle size
Use background functions for long-running tasks
Enable HTTP/2 Server Push
Resources
Netlify Documentation Official Netlify documentation
Netlify Functions Learn about Netlify Functions