TausiDocs

Vue, Svelte, Remix and other JavaScript frameworks

@tausi-auth/js works in any framework. The browser client is a small store you can subscribe to; the server helper works with any Fetch-style Request (Nuxt, SvelteKit, Remix, Astro, Hono, Bun, Deno).

The client

@tausi-auth/js on npmRequires React 18+ for the React helpers, Next.js 15+ for the Next.js helpers
Shell
npm install @tausi-auth/js
tausi.tsTypeScript
import { TausiClient } from "@tausi-auth/js";

export const tausi = new TausiClient({
  baseUrl: "https://auth.tausi.app",
  publishableKey: "pk_…",
  mode: "cookie",            // with a server proxy (recommended); omit for token mode
});

const unsubscribe = tausi.subscribe((state) => {
  // state.status: "loading" | "signedIn" | "signedOut"; state.user; state.session
});
tausi.getState();             // the current state, synchronously
Methods
Email + passwordsignUp, signIn, signOut, sendVerificationEmail, verifyEmail, forgotPassword, resetPassword, changePassword
ProfilegetUser, updateUser, deleteAccount
SessionsgetSession, listSessions, revokeSession, revokeOtherSessions, getToken
SocialgetProviders, signInWithOAuth, handleOAuthCallback

Server and cookie mode

Create one server client. It verifies sessions with the secret key and, in cookie mode, proxies the browser's calls so the session stays in an HttpOnly cookie:

tausi.server.tsTypeScript
import { createTausiServer } from "@tausi-auth/js/server";

export const tausi = createTausiServer({
  baseUrl: process.env.TAUSI_URL!,
  publishableKey: process.env.TAUSI_PUBLISHABLE_KEY!,
  secretKey: process.env.TAUSI_SECRET_KEY!,
});

// 1. Mount the proxy at /api/tausi/* (GET, POST, PATCH, DELETE):
//      return tausi.proxy(request)
// 2. In any handler:
//      const auth = await tausi.authenticate(request); // { user, session } | null
Cookie security
The cookie is HttpOnly, SameSite=Lax and Secure on https. Writes must come from your own origin. The proxy only forwards end-user endpoints, never the backend API.

Vue 3 and Nuxt

composables/useAuth.tsTypeScript
import { TausiClient, type AuthState } from "@tausi-auth/js";
import { onScopeDispose, shallowRef } from "vue";

export const tausi = new TausiClient({ baseUrl: "https://auth.tausi.app", publishableKey: "pk_…", mode: "cookie" });

export function useAuth() {
  const state = shallowRef<AuthState>(tausi.getState());
  onScopeDispose(tausi.subscribe((s) => (state.value = s)));
  return state; // state.value.status, state.value.user
}
server/api/tausi/[...path].ts (Nuxt)TypeScript
import { tausi } from "~/server/tausi";

export default defineEventHandler((event) => tausi.proxy(toWebRequest(event)));

// Other server routes:
// const auth = await tausi.authenticate(toWebRequest(event));
// if (!auth) throw createError({ statusCode: 401 });

Svelte and SvelteKit

TausiClient follows the Svelte store contract, so $tausi works directly:

Header.svelteSvelte
<script lang="ts">
  import { tausi } from "$lib/tausi"; // new TausiClient({ ..., mode: "cookie" })
</script>

{#if $tausi.status === "signedIn"}
  Hello {$tausi.user?.name} <button on:click={() => tausi.signOut()}>Sign out</button>
{:else if $tausi.status === "signedOut"}
  <a href="/sign-in">Sign in</a>
{/if}
src/hooks.server.tsTypeScript
import { createTausiServer } from "@tausi-auth/js/server";
import { TAUSI_PUBLISHABLE_KEY, TAUSI_SECRET_KEY, TAUSI_URL } from "$env/static/private";

export const tausi = createTausiServer({ baseUrl: TAUSI_URL, publishableKey: TAUSI_PUBLISHABLE_KEY, secretKey: TAUSI_SECRET_KEY });

export const handle = async ({ event, resolve }) => {
  event.locals.auth = await tausi.authenticate(event.request);
  return resolve(event);
};

// src/routes/api/tausi/[...path]/+server.ts
// export const GET = ({ request }) => tausi.proxy(request);   // and POST, PATCH, DELETE

To reload server data after sign-in: tausi.subscribe(watchAuthChanges(() => invalidateAll())), with watchAuthChanges from @tausi-auth/js/react (a plain function).

Remix and React Router 7

app/tausi.server.tsTypeScript
import { createTausiServer } from "@tausi-auth/js/server";
import { redirect } from "react-router";

export const tausi = createTausiServer({
  baseUrl: process.env.TAUSI_URL!, publishableKey: process.env.TAUSI_PUBLISHABLE_KEY!, secretKey: process.env.TAUSI_SECRET_KEY!,
});

// app/routes/api.tausi.$.ts
export const loader = ({ request }: { request: Request }) => tausi.proxy(request);
export const action = ({ request }: { request: Request }) => tausi.proxy(request);

// any protected route
export async function loader({ request }: { request: Request }) {
  const auth = await tausi.authenticate(request);
  if (!auth) throw redirect("/sign-in");
  return { user: auth.user };
}

On the client: <TausiProvider mode="cookie" onAuthChange={() => revalidator.revalidate()} …> from @tausi-auth/js/react.

Angular

auth.service.tsTypeScript
import { Injectable, signal } from "@angular/core";
import { TausiClient } from "@tausi-auth/js";

@Injectable({ providedIn: "root" })
export class AuthService {
  readonly client = new TausiClient({ baseUrl: "https://auth.tausi.app", publishableKey: "pk_…" });
  readonly state = signal(this.client.getState());
  constructor() {
    this.client.subscribe((s) => this.state.set(s));
  }
}

// An HttpInterceptor can add Authorization: Bearer ${await client.getToken()} to your API calls.

Astro, Solid, Qwik

Same pattern: subscribe to the client (tausi.subscribe(fn) calls fn now and on every change and returns an unsubscribe function). On the server, any endpoint or middleware with a Fetch Request can call tausi.authenticate(request) and mount tausi.proxy(request) at /api/tausi/*.

src/middleware.ts (Astro)TypeScript
import { defineMiddleware } from "astro:middleware";
import { tausi } from "./tausi.server";

export const onRequest = defineMiddleware(async (ctx, next) => {
  ctx.locals.auth = await tausi.authenticate(ctx.request);
  if (ctx.url.pathname.startsWith("/account") && !ctx.locals.auth) return ctx.redirect("/sign-in");
  return next();
});

Plain JavaScript (no build step)

index.htmlHTML
<script type="module">
  import { TausiClient } from "https://esm.sh/@tausi-auth/js";

  const tausi = new TausiClient({ baseUrl: "https://auth.tausi.app", publishableKey: "pk_…" });
  tausi.subscribe(({ status, user }) => {
    document.querySelector("#who").textContent = status === "signedIn" ? user.email : "Signed out";
  });

  document.querySelector("form").addEventListener("submit", async (e) => {
    e.preventDefault();
    const f = new FormData(e.target);
    try {
      await tausi.signIn({ email: f.get("email"), password: f.get("password") });
    } catch (err) {
      alert(err.message);
    }
  });
</script>