zeta
Configuration

Middleware

Middleware options and customization in Zeta Registry.

What is Middleware?

Middleware in Next.js allows you to run code before a request is completed. It's ideal for authentication, access control, and request rewriting—making it a perfect fit for protecting registry components in Zeta.

Zeta Registry Middleware

Zeta's middleware ensures that only users with a valid license token can access protected components in your registry. It works by intercepting requests to /registry/* routes and enforcing license validation.

How It Works

  • Route Matching: The middleware only runs for paths under /registry/*.
  • Public Access: The license validation page and API are always accessible.
  • Token Requirement: All other registry routes require a ?token= query parameter.
  • Validation: If the token is missing or invalid, the user is redirected to the license validation page or receives a 401 error.

Middleware Code

Important

This middleware code is automatically provided when you install Zeta using the shadcn add command (e.g., pnpm dlx shadcn@latest add https://zeta-registry.vercel.app/r/registry-nextjs.json). You do not need to create it from scratch—just review or customize as needed.
middleware.ts
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"
import { verifyToken } from "@/lib/shadcn/registry/utils"

export async function middleware(request: NextRequest) {
  // First, check if the path actually starts with /registry/
  // This is a safety check in addition to the matcher
  if (!request.nextUrl.pathname.startsWith("/registry/")) {
    return NextResponse.next()
  }
  
  // Allow access to the license validation page without token
  if (request.nextUrl.pathname === '/registry/access/validate-license') {
    return NextResponse.next()
  }

  // Allow access to the license validation api without token but ensure is a POST request
  if (request.nextUrl.pathname === '/registry/api/validate-license' && request.method === 'POST') {
    return NextResponse.next()
  }

  // Get the authorization token from ?token=
  const token = request.nextUrl.searchParams.get('token')

  if (!token) {
    return NextResponse.redirect(new URL('/registry/access/validate-license?return=' + request.nextUrl.pathname, request.url))
  }

  const isValidToken = await verifyToken(token)

  if (!isValidToken) {
    return NextResponse.json(
      { error: "Invalid or expired token" },
      { status: 401 }
    )
  }

  return NextResponse.next()
}

// Configure the paths that should be matched by this middleware
export const config = {
  matcher: [
    '/registry/:path*',
  ]
} 

Customization

You can adapt this middleware to:

  • Use different authentication methods (e.g., cookies, headers).
  • Protect additional routes.
  • Customize error handling or redirect logic.

Best Practices

  • Always validate tokens server-side.
  • Never expose sensitive logic or secrets to the client.
  • Keep your middleware logic simple and focused on access control.

On this page