Next.js Setup
This guide explains how to integrate TApi with the Next.js App Router.
Installation
Section titled “Installation”First, install the package:
npm install @farbenmeer/tapi# orpnpm add @farbenmeer/tapi1. Define your API
Section titled “1. Define your API”Create a central file to define your API structure. This acts as the source of truth for your routes.
import { defineApi } from "@farbenmeer/tapi/server";
export const api = defineApi() // We'll add routes here later // .route("/hello", import("./routes/hello"))2. Create the Route Handler
Section titled “2. Create the Route Handler”Next.js App Router uses a catch-all route to handle dynamic API requests. Create a file at src/app/api/[...tapi]/route.ts.
This handler captures all requests to /api/* and routes them through TApi.
import { createRequestHandler } from "@farbenmeer/tapi/server";import { api } from "@/api"; // Adjust import path as needed
const handler = createRequestHandler(api, { basePath: "/api"});
export const GET = handler;export const POST = handler;export const PUT = handler;export const PATCH = handler;export const DELETE = handler;3. Create the Client
Section titled “3. Create the Client”To consume your API from client components, create a type-safe fetch client.
"use client";
import { createFetchClient } from "@farbenmeer/tapi/client";import type { api } from "@/api";
// Assuming your API is mounted at /apiexport const client = createFetchClient<typeof api>("/api");4. Add a Route
Section titled “4. Add a Route”Create a route handler file. For example, src/routes/hello.ts:
import { defineHandler, TResponse } from "@farbenmeer/tapi/server";
export const GET = defineHandler({ authorize: () => true}, async () => { return TResponse.json({ message: "Hello from TApi!" });});And register it in your src/api.ts:
import { defineApi } from "@farbenmeer/tapi/server";
export const api = defineApi() .route("/hello", import("./routes/hello"));5. Usage in Components
Section titled “5. Usage in Components”Client Components
Section titled “Client Components”Use the client in your interactive components:
"use client";
import { useState, useEffect } from "react";import { client } from "@/client";
export default function ClientPage() { const [msg, setMsg] = useState("");
useEffect(() => { client.hello.get().then((data) => setMsg(data.message)); }, []);
if (!msg) return <div>Loading...</div>;
return <h1>{msg}</h1>;}Server Components
Section titled “Server Components”For Server Components, you can skip the HTTP overhead by using createLocalClient. This calls your handlers directly.
Create a server-only client instance:
import { createLocalClient } from "@farbenmeer/tapi/server";import { api } from "@/api";
export const serverClient = createLocalClient(api);Then use it in your Server Component:
import { serverClient } from "@/server-client";
export default async function ServerPage() { const data = await serverClient.hello.get();
return <h1>{data.message}</h1>;}6. Revalidation Stream
Section titled “6. Revalidation Stream”To enable tag-based revalidation across all cache layers, set up a shared PubSub instance and a revalidation endpoint.
First, create a shared module for the PubSub instance:
import { PubSub } from "@farbenmeer/tapi/server";
export const pubsub = new PubSub();Update your route handler to use it:
import { createRequestHandler } from "@farbenmeer/tapi/server";import { api } from "@/api";import { pubsub } from "@/pubsub";
const handler = createRequestHandler(api, { basePath: "/api", cache: pubsub,});
export const GET = handler;export const POST = handler;export const PUT = handler;export const PATCH = handler;export const DELETE = handler;Then add a revalidation endpoint at src/app/api/revalidate/route.ts:
import { streamRevalidatedTags } from "@farbenmeer/tapi/server";import { pubsub } from "@/pubsub";
export const GET = () => { return streamRevalidatedTags({ cache: pubsub, buildId: process.env.BUILD_ID!, });};Set BUILD_ID to a value that changes on every deployment (e.g. a git commit hash) so the service worker cache is fresh after each deploy.
For setting up a service worker that connects to this endpoint, see the Service Worker guide. For details on how the cache layers interact, see Caching Strategies.