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 helpersnpm install @tausi-auth/jsimport { TausiClient } from "@tausi-auth/js";
export const tausi = new TausiClient({
baseUrl: "https://tausi-auth.onrender.com",
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 + password | signUp, signIn, signOut, sendVerificationEmail, verifyEmail, forgotPassword, resetPassword, changePassword |
| Profile | getUser, updateUser, deleteAccount |
| Sessions | getSession, listSessions, revokeSession, revokeOtherSessions, getToken |
| Social | getProviders, 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:
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 } | nullVue 3 and Nuxt
import { TausiClient, type AuthState } from "@tausi-auth/js";
import { onScopeDispose, shallowRef } from "vue";
export const tausi = new TausiClient({ baseUrl: "https://tausi-auth.onrender.com", 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
}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:
<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}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, DELETETo 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
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
import { Injectable, signal } from "@angular/core";
import { TausiClient } from "@tausi-auth/js";
@Injectable({ providedIn: "root" })
export class AuthService {
readonly client = new TausiClient({ baseUrl: "https://tausi-auth.onrender.com", 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/*.
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)
<script type="module">
import { TausiClient } from "https://esm.sh/@tausi-auth/js";
const tausi = new TausiClient({ baseUrl: "https://tausi-auth.onrender.com", 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>