Quickstart

From zero to a signed-in user.

Signet speaks the better-auth wire, so there is no Signet SDK to learn. Install the stock better-auth client, point its baseURL at your instance’s /api/auth, and the calls you already write just work. Five frameworks, one copy-paste path each.

auth-client.ts
import { createAuthClient } from "better-auth/client";

// Your existing better-auth client — point baseURL
// at your Signet instance. The wire is the contract.
export const authClient = createAuthClient({
  baseURL: "https://auth.example.com/api/auth",
});

// The same calls you already write — they just work.
await authClient.signIn.email({ email, password });

The shape

Three constants, every framework.

Whatever you build with, the path is the same three moves. The frameworks below differ only in where they hold state.

  1. Install the stock client — bun add better-auth (or npm i better-auth). No Signet package.
  2. Point baseURL at your instance’s /api/auth. The wire is the contract, and it reads the same hosted or on-prem.
  3. Call the methods you already know — signUp.email, signIn.email, useSession, getSession, signOut.

Quickstart I

Next.js — App Router

The React client (better-auth/react) gives you signIn.email and the useSession hook inside your "use client" components.

Install the stock client — bun add better-auth. It speaks the certified better-auth wire, so there is nothing Signet-specific to add.

lib/auth-client.ts
import { createAuthClient } from "better-auth/react";

// One client for the whole app — the stock better-auth
// React client, pointed at your Signet instance.
export const authClient = createAuthClient({
  baseURL: "https://auth.example.com/api/auth",
});

// In a "use client" component: sign in, then read the
// session with the hook. Same calls you already write.
await authClient.signIn.email({ email, password });
const { data, isPending } = authClient.useSession();

To read the session in a Server Component or Route Handler, forward the request cookies with the vanilla better-auth/client — the same pattern as Quickstart IV.

Quickstart II

React — single-page app

A pure browser app talks to your instance directly. The React client (better-auth/react) carries signUp.email, useSession, and signOut — no backend of your own required.

Install the stock client — bun add better-auth. It speaks the certified better-auth wire, so there is nothing Signet-specific to add.

src/auth-client.ts
import { createAuthClient } from "better-auth/react";

export const authClient = createAuthClient({
  baseURL: "https://auth.example.com/api/auth",
});

// Create an account (swap for signIn.email to log in).
await authClient.signUp.email({ email, password, name });

// Read the session with the hook; sign out when done.
const { data, isPending } = authClient.useSession();
await authClient.signOut();

Everything runs in the browser against your instance. Hosted or on-prem, this client does not change — the wire is the contract.

Quickstart III

React Router v7

There is no React-Router-specific better-auth package, and none is needed: use the React client in components, and the vanilla client inside a server loader to read the session with the incoming request headers.

Install the stock client — bun add better-auth. It speaks the certified better-auth wire, so there is nothing Signet-specific to add.

app/*.ts(x)
// app/lib/auth-client.ts — the React client for components.
import { createAuthClient } from "better-auth/react";
export const authClient = createAuthClient({ baseURL: "https://auth.example.com/api/auth" });
await authClient.signIn.email({ email, password });

// app/routes/dashboard.tsx — read the session in a loader by
// forwarding the request cookies to your Signet instance.
export async function loader({ request }) {
  const session = await authClient.getSession({
    fetchOptions: { headers: request.headers },
  });
  if (!session.data) throw redirect("/login");
  return { user: session.data.user };
}

Gate any route by redirecting when session.data is null; the loader runs on the server, so the check never reaches the browser.

Quickstart IV

Node / Express — session verification

Your backend becomes a resource server. The vanilla better-auth/client forwards the caller’s session cookie to Signet and reads session.data.user — Signet holds the credentials, your API just checks the session.

Install the stock client — npm i better-auth. It speaks the certified better-auth wire, so there is nothing Signet-specific to add.

server.ts
import express from "express";
import { createAuthClient } from "better-auth/client";

const authClient = createAuthClient({
  baseURL: "https://auth.example.com/api/auth",
});

// Verify the caller's session against Signet on each request.
async function requireUser(req, res, next) {
  const session = await authClient.getSession({
    fetchOptions: { headers: { cookie: req.headers.cookie ?? "" } },
  });
  if (!session.data) return res.status(401).json({ error: "not signed in" });
  req.user = session.data.user;
  next();
}

Attach requireUser to any route that needs a signed-in caller; a missing or expired session returns 401 without your backend ever storing a password.

Quickstart V

Plain JavaScript — no framework

The vanilla client (better-auth/client) is the one every other quickstart builds on: createAuthClient, signIn.email, getSession, signOut. It runs in any JavaScript runtime.

Install the stock client — bun add better-auth. It speaks the certified better-auth wire, so there is nothing Signet-specific to add.

auth.js
import { createAuthClient } from "better-auth/client";

const authClient = createAuthClient({
  baseURL: "https://auth.example.com/api/auth",
});

// Every call returns { data, error } — it does not throw.
const { data, error } = await authClient.signIn.email({ email, password });

// Read the current session; sign out to end it.
const session = await authClient.getSession();
await authClient.signOut();

This is the whole integration surface. Any framework is this client plus that framework’s own way of holding state — there is nothing Signet-specific to learn.

Why there is no Signet SDK. Signet is the auth server, so you never mount a better-auth server of your own — these quickstarts use the client only. Frameworks with no dedicated better-auth package (React Router, plain JavaScript) use the React client in components and the vanilla better-auth/client for server-side session reads. Every method shown traces to better-auth 1.6.23, the release Signet is certified against (compatibility gap 0 — scoped to what better-auth's own suite exercises here, not a claim that every better-auth route is implemented; the full statement is on /compatibility).

The wire is the same at 2am.

Every deployed instance serves its own /docs and certification receipt from inside the binary — the reference never drifts from the build you run. Get an instance and point your client at it.