Volt v0.1 · TypeScript APIs on Bun · Get started
Docs/Plugins Ecosystem/Signed Cookies

Signed Cookies

Sign cookie values with the plugin’s actual context helper.

Configure and run

Set COOKIE_SECRET before running the sample. Signed values provide integrity, not encryption. Do not put secrets in a signed cookie.

bash
export COOKIE_SECRET='replace-with-a-long-random-cookie-secret'
index.ts
import { Volt, cookiesPlugin, type CookieContextHelper } from 'voltts';

const secret = process.env.COOKIE_SECRET;
if (!secret) throw new Error('Set COOKIE_SECRET');
const app = new Volt();
app.plugin(cookiesPlugin({ secret }));
app.post('/preference', (c) => {
  const cookies: CookieContextHelper = c.store.cookies;
  cookies.setSigned('theme', 'dark', {
    httpOnly: true,
    sameSite: 'lax',
    secure: process.env['NODE_ENV'] === 'production',
    maxAge: 86400,
  });
  return c.json({ saved: true });
});
app.get('/preference', (c) => {
  const cookies: CookieContextHelper = c.store.cookies;
  const theme = cookies.getSigned('theme');
  if (theme === false) return c.json({ error: 'Invalid signature' }, 400);
  return c.json({ theme: theme ?? 'light' });
});
if (globalThis._importMeta_.main) app.listen(3000);
export default app;

Save and read a preference

bash
bun run index.ts
curl -i -c cookies.txt -X POST http://localhost:3000/preference
curl -i -b cookies.txt http://localhost:3000/preference

The helper provides get, getSigned, set, setSigned, and delete. getSigned returns false for tampering and undefined for a missing value. The core c.setCookie method does not accept a signed flag; use setSigned.

Use httpOnly, secure on HTTPS, and an appropriate sameSite policy. maxAge is seconds. Cookie helpers are injected through middleware and reference a request context. Since c.store is shared in the current core, do not retain the helper between requests; read it immediately in the handler and avoid using it after awaiting unrelated work.