Sessions

Call getSession(c, secret) from a loader or action to read and write a signed session cookie. Read session.data, await session.set({ … }) to update it, and session.destroy() to log out. Empty data means no session — a fresh visitor, an expired session, or a cookie that failed its signature — so guard on it.

// app/routes/dashboard.tsx  →  guard on a session in the loader
import type { PageLoader } from "chevalier";
import { getSession } from "chevalier";

export const loader: PageLoader = async (c) => {
  const session = await getSession<{ userId: number }>(
    c,
    Deno.env.get("SESSION_SECRET")!,
  );
  if (!session.data.userId) return c.redirect("/login");
  return { userId: session.data.userId };
};

The cookie is HttpOnly by default and Secure except on localhost / 127.0.0.1, so it survives plain-HTTP dev.

Sessions expire after 7 days: the expiry is signed into the payload and checked on read, so a captured cookie stops verifying too — and each set restamps it, so an active session keeps rolling.

Pass { name } to rename the cookie or { cookie } to override its attributes — e.g. { cookie: { secure: true } } behind a TLS-terminating proxy, or { cookie: { maxAge } } for a different lifetime.

Secrets and rotation

Set SESSION_SECRET to a long random string. To rotate it without logging everyone out, pass an array with the new secret first:

const session = await getSession(c, [newSecret, oldSecret]);

Then drop the old one once its cookies have aged out.