Fetch Client With Next.js
Use the fetch client with Next.js server-side cache tags.
Use @rest-rpc/next when calling a REST API from Next.js server code. As long
as you describe the API with a rest-rpc contract, the backend itself can be
implemented with any framework or language.
It wraps the core fetch client and can attach deterministic tags to GET requests
through Next’s fetch options.
Install
pnpm add @rest-rpc/core @rest-rpc/next
Create A Next Client
import { initNextClient } from "@rest-rpc/next";
import { api } from "./contract";
export const client = initNextClient(api, {
origin: process.env.API_BASE_URL!,
automaticFetchTags: {
enabled: true,
},
});
Use this client from Server Components, Server Actions, route handlers, or other server-side Next.js code.
export default async function TodoPage({
params,
}: {
params: Promise<{ id: string }>;
}) {
const { id } = await params;
const todo = await client.todos.get.fetch({ id });
return <h1>{todo.title}</h1>;
}
Automatic Tags
Automatic tags are added to GET requests only. Existing next options and
manual tags are preserved.
const todo = await client.todos.get.fetch(
{ id: "todo_1", filter: "open" },
{
next: {
revalidate: 60,
tags: ["manual"],
},
},
);
For a request like /todos/todo_1?filter=open, the client attaches both the
exact tag and the broader path tag.
[
"rest-rpc:/todos/todo_1?filter=open",
"rest-rpc:/todos/todo_1",
]
The exact tag invalidates one query variant. The path tag invalidates cached GET requests for that path across query variants.
Use tagPrefix when one Next app talks to multiple APIs.
export const client = initNextClient(api, {
origin: process.env.API_BASE_URL!,
automaticFetchTags: {
enabled: true,
tagPrefix: "admin-api",
},
});
Revalidate After Mutations
Use getRouteCacheTags() when a mutation, Server Action, route handler, or
webhook needs to invalidate data loaded through the fetch client.
"use server";
import { revalidateTag } from "next/cache";
import { getRouteCacheTags } from "@rest-rpc/core";
import { api } from "./contract";
import { client } from "./client";
export async function renameTodo(id: string, title: string) {
await client.todos.update.fetch({ id, title });
for (const tag of getRouteCacheTags(api.todos.get, { request: { id } })) {
revalidateTag(tag);
}
}
getRouteCacheTags() is exported from @rest-rpc/core, so non-Next backends
can generate the same invalidation tags for webhooks or queues.