@pylonsync/next is the Next.js-specific layer on top of @pylonsync/react. It provides:
createPylonServer— server-side fetch helpers (pylon.requireAuth(),pylon.getMe(),pylon.json()) that forward the user’s session cookiecreatePylonClient— a same-origin client fetcher for Client Components that respects Next’s request lifecyclecreatePylonProxy— middleware that gates protected routes on session presence so the UI doesn’t flash before redirect@pylonsync/next/auth— cookie-aware sign-up / sign-in / OAuth flows
@pylonsync/react directly.
The fastest path to a Next.js + Pylon project is npm create @pylonsync/pylon — pick the todo (or any) template with --platforms web and you get a working App Router setup with all of this wired up. The rest of this page documents the pieces so you can integrate Pylon into an existing Next.js app.
Install
@pylonsync/sdk + @pylonsync/react install transitively.
1. Configure the backend URL
SetPYLON_TARGET to the Pylon backend’s origin. In dev it defaults to http://localhost:4321 (the pylon dev default), so you only need to set it explicitly when the backend lives elsewhere.
PYLON_TARGET in your project’s Environment Variables for both Production and Preview environments — point it at your Pylon Cloud project’s URL (https://pylon-<slug>.fly.dev for the default hostname, or your custom domain).
See Deploying to Vercel for the full checklist.
2. Server helpers — createPylonServer
Build a single pylon server-helper that every Server Component, Route Handler, or Server Action imports from.
pylon:
All paths are relative to the configured
target and the session cookie rides along automatically.
3. Client fetcher — createPylonClient / api
For Client Components, the package exports a same-origin api() helper that the useQuery / useMutation hooks build on top of. Most apps don’t construct one directly — just import { api } from "@pylonsync/next/client":
/api/* paths same-origin so the session cookie rides natively. If you split your frontend onto a different origin than your Pylon backend, set up a Next.js rewrite in next.config.js:
4. Live data — <Providers> + db.useQuery
Live queries from React Server Components are tricky (RSC has no client store). For live data, render a Client Component and use the db.useQuery hook from @pylonsync/react:
db.useQuery subscribes to the local sync replica — server-pushed inserts, your own optimistic mutations, and cross-tab updates all re-render automatically.
5. Middleware gate — createPylonProxy
Block protected routes from rendering before auth resolves. Saves a flash of UI before the client-side redirect:
pylon.requireAuth() inside the page. It’s a UX optimization, not a security boundary.
6. Auth flows — @pylonsync/next/auth
Sign-up, sign-in, and OAuth from Client Components or Server Actions:
await pylon.requireAuth() in any Server Component resolves to the freshly-authenticated user.
OAuth providers follow the same pattern via startOAuthLogin({ provider: "google", returnTo: "/dashboard" }).
Environment variables
There is intentionally no
NEXT_PUBLIC_PYLON_URL — the client always talks same-origin via the Next rewrite, so the browser doesn’t need to know the backend URL. If you don’t want the rewrite, pass an explicit baseUrl to configureClient in your Providers.
Common pitfalls
- Cookie name mismatch. Pylon emits
${app_name}_session. If yourapp.tssaysname: "notes", the cookie isnotes_session— notpylon_session. Pass the right name tocreatePylonServer({ cookieName })andcreatePylonProxy({ cookieName }). - Cross-origin without rewrite. If your Next.js app is on
app.example.comand Pylon is onapi.example.com, you need either a rewrite (recommended) or matchingDomain=.example.comcookie config on the backend. See Sessions for the cookie-domain checklist. - Server fetch timeouts.
pylon.json()andpylon.fetch()apply a 5s timeout by default — a stuck Pylon backend won’t hang your Next.js page indefinitely. Useloading.tsxanderror.tsxboundaries to render gracefully when the backend is unreachable. - Empty
baseUrlonly works when rewrites are in place.configureClient({ baseUrl: "" })uses the current origin, which only works if/api/*reaches your Pylon backend. Without the Next rewrite, pass the absolute Pylon URL.