forrealtime

TanStack Start

Use forrealtime with TanStack Start for full-stack React with SSR.

1. Server route

// src/routes/api.realtime.ts
import { createFileRoute } from "@tanstack/react-router";
import { getRequest } from "@tanstack/react-start/server";
import Redis from "ioredis";
import { z } from "zod/v4";
import { Realtime, handle } from "forrealtime";
import { createIORedisAdapter } from "forrealtime/adapters/ioredis";

export const realtime = new Realtime({
  schema: {
    notification: {
      alert: z.string(),
    },
  },
  redis: createIORedisAdapter(new Redis(process.env.REDIS_URL)),
});

export const Route = createFileRoute("/api/realtime")({
  server: {
    handlers: {
      GET: () => {
        const request = getRequest();
        return handle({ realtime })(request);
      },
    },
  },
});

2. Add the provider at the root

// src/routes/__root.tsx
import {
  HeadContent,
  Scripts,
  createRootRouteWithContext,
} from "@tanstack/react-router";
import type { QueryClient } from "@tanstack/react-query";
import { RealtimeProvider } from "forrealtime/client";

interface MyRouterContext {
  queryClient: QueryClient;
}

export const Route = createRootRouteWithContext<MyRouterContext>()({
  shellComponent: RootDocument,
});

function RootDocument({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <HeadContent />
      </head>
      <body>
        <RealtimeProvider api={{ url: "/api/realtime" }}>
          {children}
        </RealtimeProvider>
        <Scripts />
      </body>
    </html>
  );
}

3. Use the hook in a route

// src/routes/index.tsx
import { createFileRoute } from "@tanstack/react-router";
import { useState } from "react";
import { createRealtime } from "forrealtime/client";
import type { realtime } from "./api.realtime"; // type-only import

const { useRealtime } = createRealtime<typeof realtime>();

export const Route = createFileRoute("/")({
  component: RouteComponent,
});

function RouteComponent() {
  const [messages, setMessages] = useState<string[]>([]);

  const { status } = useRealtime({
    channels: ["default"],
    events: ["notification.alert"],
    onData(payload) {
      if (payload.event === "notification.alert") {
        setMessages((prev) => [...prev, `alert: ${payload.data}`]);
      }
    },
  });

  return (
    <div>
      <p>Status: {status}</p>
      <pre>{JSON.stringify(messages, null, 2)}</pre>
    </div>
  );
}

4. Emit from the server

await realtime.emit("notification.alert", "TanStack Start is live");

On this page