Next.js Usage

Recommended patterns for using glyde with Next.js App Router. Framework-agnostic core, framework-specific patterns.

Key insight: Server Components cannot write cookies. Token refresh must happen in Next.js middleware (before SSR), not in the HTTP client. glyde provides the interceptor hooks — you wire the auth logic where it belongs.

Naming Convention

TermWhereJob
towerRoute Handlers, Server ActionsCalls external API with auth headers from cookies
passengerClient Components, browserCalls /api/* proxy routes, redirects on 401

Server Instance (tower)

// lib/api/server.ts — "tower" (server-side instance)
import plane from "glyde"
import { cookies } from "next/headers"

export async function tower() {
  const api = plane({ baseURL: process.env.API_BASE_URL })
  const cookieStore = await cookies()

  api.interceptors.request.use((config) => {
    const token = cookieStore.get("access_token")?.value
    if (token) {
      config.headers = { ...config.headers, Authorization: `Bearer ${token}` }
    }
    return config
  })

  return api
}

Client Instance (passenger)

// lib/api/client.ts — "passenger" (client-side instance)
"use client"
import plane from "glyde"

export const passenger = plane({ baseURL: "/api/proxy" })

passenger.interceptors.response.use(
  (response) => response,
  (error) => {
    if (error?.status === 401) window.location.href = "/login"
    throw error
  }
)

Route Handler

// app/api/users/route.ts
import { tower } from "@/lib/api/server"
import { isHttpError } from "glyde"

export async function GET(request: Request) {
  const api = await tower()

  try {
    const { data } = await api.get("/users/", { signal: request.signal })
    return Response.json(data)
  } catch (err) {
    if (isHttpError(err)) {
      return new Response(null, { status: err.status })
    }
    throw err
  }
}

Token Refresh via Middleware

Since Server Components cannot write cookies, handle token refresh proactively in Next.js middleware. This ensures Server Components always have a valid token.

// middleware.ts — proactive token refresh before SSR
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"

export async function middleware(request: NextRequest) {
  const access = request.cookies.get("access_token")?.value
  const refresh = request.cookies.get("refresh_token")?.value

  // If access token is missing/expired but refresh exists — refresh proactively
  if (!access && refresh) {
    const res = await fetch(`${process.env.API_BASE_URL}/auth/refresh`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ refresh }),
    })

    if (res.ok) {
      const { access: newToken } = await res.json()
      const response = NextResponse.next()
      response.cookies.set("access_token", newToken, {
        httpOnly: true,
        secure: process.env.NODE_ENV === "production",
        sameSite: "lax",
        path: "/",
      })
      return response
    } else {
      // Refresh failed — clear cookies and redirect to login
      const response = NextResponse.redirect(new URL("/login", request.url))
      response.cookies.delete("access_token")
      response.cookies.delete("refresh_token")
      return response
    }
  }

  return NextResponse.next()
}

export const config = {
  matcher: ["/dashboard/:path*", "/api/proxy/:path*"],
}

Architecture

Browser (passenger)
    │
    ▼
Next.js Route Handler (/api/proxy/*)
    │  ← tower() adds auth headers
    ▼
External API (Django, FastAPI, etc.)

Middleware runs BEFORE SSR:
  ├── Check access_token cookie
  ├── If expired + refresh_token exists → refresh proactively
  └── Server Components always get fresh token