Oliver Servín

Integrar Hono en Next.js.

Instalamos la dependencia de Hono con npm:

npm install hono

Agregamos una ruta del tipo catch-all para la API creando el archivo app/api/[[...route]]/route.ts.

Dentro del archivo route.ts inicializamos Hono y especificamos las constantes GET y POST para que Next.js maneje las rutas API pero a través de Hono.

import { Hono } from 'hono'
import { handle } from 'hono/vercel'
 
export const runtime = 'edge'
 
const app = new Hono().basePath('/api')
 
app.get('/hello', (c) => {
return c.json({
message: 'Hello Next.js!',
})
})
 
export const GET = handle(app)
export const POST = handle(app)

Ahora podemos ir al endpoint http://localhost:3000/api/hello para verificar que la integración esté correcta.

Hola Next.js

También podemos utilizar Zod para validar parámetros o cualquier otra entrada en Hono.

Instalamos Zod y Zod Validator para Hono:

npm install zod
npm install @hono/zod-validator

Ahora, para probar Zod, añadimos otro endpoint /hello/:test y utilizamos el middleware de zValidator y especificamos el tipo de parámetro que será test, por ejemplo string().

+import { zValidator } from '@hono/zod-validator'
import { Hono } from 'hono'
import { handle } from 'hono/vercel'
+import { z } from 'zod'
 
export const runtime = 'edge'
 
const app = new Hono().basePath('/api')
 
app
.get('/hello', (c) => {
return c.json({
message: '¡Hola Next.js!',
})
})
+ .get(
+ '/hello/:test',
+ zValidator(
+ 'param',
+ z.object({
+ test: z.string(),
+ })
+ ),
+ (c) => {
+ const { test } = c.req.valid('param')
+ 
+ return c.json({
+ message: `¡Hola Next.js!`,
+ test: test,
+ })
+ }
+ )
 
export const GET = handle(app)
export const POST = handle(app)

Para proteger nuestros endpoints de la API con Clerk, podemos hacerlo mediante un middleware.

Instalamos Clerk para Hono y el backend:

npm install @hono/clerk-auth @clerk/backend

Ahora, en nuestro route.ts para las APIs, agregamos el middleware de clerkMiddleware para validar que el usuario esté autorizado para utilizar nuestra API.

+import { clerkMiddleware, getAuth } from '@hono/clerk-auth'
import { Hono } from 'hono'
import { handle } from 'hono/vercel'
 
export const runtime = 'edge'
 
const app = new Hono().basePath('/api')
 
app
.get('/hello', clerkMiddleware(), (c) => {
const auth = getAuth(c)
 
if (!auth?.userId) {
return c.json({
message: 'Unauthorized',
}, 401)
}
 
return c.json({
message: '¡Hola Next.js!',
userId: auth.userId,
})
})
 
export const GET = handle(app)
export const POST = handle(app)

Si visitamos el endpoint http://localhost:3000/api/hello y no hemos iniciado sesión, obtendremos un error 401.

401 error

Y si iniciamos sesión, obtenemos nuestro mensaje de bienvenida y el id del usuario.

endpoint con sesión iniciada