Skip to content

Hono Next

Directory Structure

.
├── app
│   ├── api
│   │   └── [...route]
│   │       └── route.ts
│   ├── layout.tsx
│   └── page.tsx
├── package.json
└── tsconfig.json
sh
npm install next@latest react@latest react-dom@latest hono
sh
npm install -D @types/node @types/react typescript

app/api/[...route]/route.ts

ts
import { Hono } from 'hono'
import { hc } from 'hono/client'
import { handle } from 'hono/vercel'

const app = new Hono().basePath('/api')

const api = app.get('/hello', async (c) => {
  return c.json({
    message: 'Hono🔥 Next',
  })
})

type AddType = typeof api

export const client = hc<AddType>('/').api

export const GET = handle(app)

Zod OpenAPI

ts
import { createRoute, OpenAPIHono, z } from '@hono/zod-openapi'
import { swaggerUI } from '@hono/swagger-ui'
import { hc } from 'hono/client'
import { handle } from 'hono/vercel'

const app = new OpenAPIHono().basePath('/api')

export const helloSchema = z.object({
  message: z.string().openapi({
    example: 'Hono🔥 Next',
  }),
})

const route = createRoute({
  method: 'get',
  path: '/hello',
  responses: {
    200: {
      content: {
        'application/json': {
          schema: helloSchema,
        },
      },
      description: 'Hono🔥 Next',
    },
  },
})

const api = app.openapi(route, (c) => {
  return c.json({ message: 'Hono🔥 Next' })
})

app.get('/ui', swaggerUI({ url: '/api/doc' }))

app.doc('/doc', {
  info: {
    title: 'Hono API',
    version: 'v1',
  },
  openapi: '3.1.0',
})

type AddType = typeof api

export const client = hc<AddType>('/').api

export const GET = handle(app)

app/page.tsx

tsx
'use client'

import { useState } from 'react'
import { client } from './api/[...route]/route'

export default function Home() {
  const [message, setMessage] = useState('')

  const onSubmit = async () => {
    const res = await client.hello.$get()
    const data = await res.json()
    setMessage(data.message)
  }
  return (
    <>
      <h1>Hono🔥 Next</h1>
      <button type='button' onClick={onSubmit}>
        Get Message
      </button>
      <h1>{message}</h1>
    </>
  )
}

Demo

demo