Menu

Start

Get a signed-in user.

Two ways in. Build sign-in from scratch, or bring an app that already has users. Both end with a working session in your app.

Quickstart

From zero to a signed-in user.

There is no Signet SDK to learn. Install the stock better-auth client, point it at your instance’s /api/auth, and the calls you already write just work. Five actual frameworks, one copy-paste path each, plus React and vanilla-client foundations.

Next.jsReact RouterExpressVueSvelteReactVanillaStarters

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 });

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 requests are identical, hosted or on-prem.
  3. Call the methods you already know: signUp.email, signIn.email, useSession, getSession, signOut.
Signet supports EdDSA and RS256 for ID-token signing. The client's stored id_token_signed_response_alg selects an available active signing algorithm. Discovery lists the available algorithms with the default first. New installs default an omitted value to RS256; migrated installs with an existing signing key stay explicitly pinned to EdDSA. See the OAuth provider guide before choosing your client's setting.

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. Nothing Signet-specific to add; the client package is the integration path.

Pinned client: better-auth 1.6.23. The certification receipt covers this version exactly; newer clients are not known to break and are not covered.

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();

Browser clients should call /api/auth on their own origin, as the Next.js starter demonstrates with a same-origin gateway; when the app and Signet use different origins, add the app's origin to the instance's [server].trusted_origins.

To read the session in a Server Component or Route Handler, forward the request cookies with the vanilla better-auth/client, as shown in the React Router v7 card.

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. Nothing Signet-specific to add; the client package is the integration path.

Pinned client: better-auth 1.6.23. The certification receipt covers this version exactly; newer clients are not known to break and are not covered.

app/*.ts(x)
// app/lib/auth-client.ts: the React client for components.
import { createAuthClient as createReactAuthClient } from "better-auth/react";
export const authClient = createReactAuthClient({ 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.
import { createAuthClient as createServerAuthClient } from "better-auth/client";
const serverAuth = createServerAuthClient({ baseURL: "https://auth.example.com/api/auth" });
export async function loader({ request }) {
  const session = await serverAuth.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.

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. Nothing Signet-specific to add; the client package is the integration path.

Pinned client: better-auth 1.6.23. The certification receipt covers this version exactly; newer clients are not known to break and are not covered.

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.

Vue 3

The stock package has a dedicated better-auth/vue entry point. Its useSession state is a Vue ref, so sign-in and reactive session rendering use the framework’s native model.

Install the stock client: bun add better-auth. Nothing Signet-specific to add; the client package is the integration path.

Pinned client: better-auth 1.6.23. The certification receipt covers this version exactly; newer clients are not known to break and are not covered.

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

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

// In a Vue setup block: useSession() returns a Vue ref.
const session = authClient.useSession();
await authClient.signIn.email({ email, password });
// In the template: session.data?.user

Use session.value in script and Vue’s automatic ref unwrapping in templates. The HTTP calls remain the same certified wire.

Svelte

The stock better-auth/svelte entry point exposes session state as a nanostore. Svelte’s $session subscription updates after the same signIn.email call.

Install the stock client: bun add better-auth. Nothing Signet-specific to add; the client package is the integration path.

Pinned client: better-auth 1.6.23. The certification receipt covers this version exactly; newer clients are not known to break and are not covered.

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

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

// In a component module: Svelte auto-subscribes with $session.
const session = authClient.useSession();
await authClient.signIn.email({ email, password });
// In markup: {$session.data?.user.email}

For SvelteKit, keep the browser client shown here and put the same-origin /api/auth gateway at the framework boundary; Signet remains the auth server.

React · single-page client foundation

React itself is the client library under the Next.js and React Router paths above. This supplemental recipe isolates better-auth/react: signUp.email, useSession, and signOut.

Install the stock client: bun add better-auth. Nothing Signet-specific to add; the client package is the integration path.

Pinned client: better-auth 1.6.23. The certification receipt covers this version exactly; newer clients are not known to break and are not covered.

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();

Browser clients should call /api/auth on their own origin, as the Next.js starter demonstrates with a same-origin gateway; when the app and Signet use different origins, add the app's origin to the instance's [server].trusted_origins.

The Express starter demonstrates session verification on the server with the incoming request cookies.

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. Nothing Signet-specific to add; the client package is the integration path.

Pinned client: better-auth 1.6.23. The certification receipt covers this version exactly; newer clients are not known to break and are not covered.

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.

Two runnable starters.

Your Signet delivery includes two standalone, secret-free apps. Each has its own manifest, setup guide, and executable smoke test against a local Signet stub.

  • The Next.js starter ships with your Signet delivery at examples/starters/next-app (hosted onboarding or the enterprise source delivery); there is no public download. It includes an App Router sign-up/sign-in page plus a same-origin /api/auth/* gateway that preserves each Set-Cookie header.
  • The Express starter ships in the same delivery at examples/starters/express-api. Its /api/me guard forwards the caller’s cookie through the stock better-auth/client.

Run npm ci && npm test in either directory. Set only the public SIGNET_URL; neither starter contains a server secret, database credential, or Signet-specific SDK.

Why there is no Signet SDK.

The stock better-auth client is the integration. Open if you want the reason, and the ADK.

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. Vue and Svelte use their dedicated stock client entry points; React Router uses the React client in components and 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 the checks in the public compatibility profile, not a claim that every better-auth route is implemented; the full statement is on /compatibility). What Signet ships instead is an ADK, an AI Development Kit: the agent on-ramp served by the engine itself (/llms.txt and /llms-full.txt, version-matched and air-gap capable, plus the OpenAPI schema and the machine-readable certification receipt), so an agent can wire this integration without a library to learn. Since v0.1.0 the ADK also has an executable form: signetctl agent runs that loop from your terminal against your own OpenAI-compatible endpoint, and signetctl mcp serve exposes the same operator verbs to any MCP client; the reference is on /signetctl.

Docs that live inside the engine.

Every deployed instance serves its own /docs and certification receipt from inside the engine, so the reference always matches the build you are running, even on a host with no internet. Get an instance and point your client at it.

Enter to open · Esc to close