Using generated client in Next.js 13 with per-request config

I’ve settled on a handy way for configuring a generated client in Next.js 13.

It uses the cache function to memoize values for the duration of a single request. In this example it generates a random request ID which is provided as the X-Request-ID header to all calls made by the client.

The X-Request-ID header is particularly helpful because it can be used to filter traces in the dashboard. With this, you can see the whole set of calls Encore received in order to perform a server-render on Next.js.

// lib/client.ts
import Client, { ClientOptions, Fetcher, Local } from "@/lib/client.gen";
import { nanoid } from "nanoid/non-secure";
import { cache } from "react";

 * Generate a random string to be used as a request ID. Result is cached for the
 * duration of a single request.
export const useRequestID = cache(nanoid);

 * Retrieve a configured client. All requests include a `X-Request-ID` header
 * which can be used to filter traces in the Encore UI. With this you can see
 * how many calls your Next.js app is making to Encore in order to server-render
 * pages.
export const useClient = cache((auth?: ClientOptions["auth"]) => {
  const requestID = useRequestID();

  const fetcher: Fetcher = (input, init = {}) => {
    const headers = new Headers(init.headers);
    headers.append("X-Request-ID", requestID);

    return fetch(input, { ...init, headers });

  return new Client(Local, { fetcher, auth });