Skip to content

<seva-auth>

The <seva-auth> component renders a complete authentication UI. It supports email/password sign-in, account creation, forgot password, magic link, SMS OTP, and Google OAuth — all in a single element.

When the user is not authenticated, the component displays a sign-in form with links to alternate auth methods. After successful authentication, it shows the user’s name, email, and a sign-out button. Auth state is persisted in localStorage and restored on page load.

<seva-event-register> embeds its own sign-in form internally — if event registration is the only authenticated feature on your page, you do not need a standalone <seva-auth>. Users will be prompted to sign in directly within the registration flow.

Add a standalone <seva-auth> when you want to:

  • Provide a visible sign-in/sign-out UI outside the registration flow
  • Authenticate users before they interact with other components like <seva-my-profile>, <seva-my-registrations>, or <seva-member-directory>
  • Give users a dedicated sign-out button on the page
<script type="module" src="YOUR_COMPONENTS_URL/seva-auth.js"></script>
<seva-auth tenant-slug="my-club" api-url="https://api.seva.tools"> </seva-auth>
<script>
const auth = document.querySelector("seva-auth");
auth.addEventListener("seva:authenticated", (e) => {
console.log("User:", e.detail.user);
console.log("Token:", e.detail.token);
});
</script>
AttributeTypeDefaultDescription
tenant-slugstring''Required. Your organization’s tenant slug.
api-urlstring'https://api.seva.tools'Base URL of the Seva API.
viewAuthView'sign-in'Initial view. One of: 'sign-in', 'sign-up', 'forgot-password', 'sms-otp', 'magic-link'.
theme'light' | 'dark''light'Color theme. Set via JavaScript property.
hide-sign-upbooleanfalseWhen present, hides the “Sign up” link and sign-up form. Useful when the component is embedded inside <seva-event-register>.
EventPayloadWhen it fires
seva:authenticated{ user: AuthUser, token: string }User successfully signs in or signs up.
seva:signed-out{}User signs out (via UI or signOut() method).
seva:error{ message: string }An auth error occurs (bad credentials, network failure, etc.).
seva:view-changed{ view: AuthView }The component switches between views (sign-in, sign-up, etc.).
seva:pending{ message: string }Sign-up succeeded but the account requires admin approval.
interface AuthUser {
id: string;
email: string;
name: string;
}
type AuthView =
| "sign-in"
| "sign-up"
| "forgot-password"
| "sms-otp"
| "magic-link";
MethodSignatureDescription
getToken()() => string | nullReturns the current session token, or null if not authenticated.
getUser()() => AuthUser | nullReturns the current user object, or null if not authenticated.
signOut()() => voidClears auth state and fires seva:signed-out.
setView(view)(view: AuthView) => voidProgrammatically switch to a different auth view.

The default view. The user enters email and password. On success, seva:authenticated fires.

Available unless hide-sign-up is set. Collects first name, last name, email, and password. If the tenant requires approval, the component shows a pending message and fires seva:pending instead.

Sends a password-reset email. Always shows a success message regardless of whether the email exists (to prevent email enumeration).

Sends a sign-in link to the user’s email. When the user clicks the link, they are redirected back with a seva-token query parameter. The component detects this automatically, validates the token, and fires seva:authenticated.

Two-step flow: (1) user enters phone number and receives a code, (2) user enters the code. On successful verification, seva:authenticated fires.

Opens a popup window for Google sign-in. The popup communicates back via postMessage. If popups are blocked, an error is shown.

Auth state is stored in localStorage under the key seva-auth-{tenant-slug}. Sessions work like this:

  • A login session lasts 30 days.
  • As long as the user visits the site at least once a day, their session is automatically extended in the background — they won’t be interrupted or asked to sign in again.
  • If a user is inactive for more than 30 days, they will need to sign in again the next time they visit.

A session ends when:

  • 30 days pass with no activity on the site
  • The user clicks Sign Out (clears localStorage and fires seva:signed-out)
  • The user clears browser localStorage for the host domain
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Sign In</title>
<script type="module" src="YOUR_COMPONENTS_URL/seva-auth.js"></script>
<style>
body {
font-family: system-ui, sans-serif;
max-width: 400px;
margin: 2rem auto;
}
#status {
margin-top: 1rem;
padding: 0.75rem;
border-radius: 0.5rem;
font-size: 0.875rem;
}
.signed-in {
background: #dcfce7;
color: #166534;
}
.signed-out {
background: #fef3c7;
color: #92400e;
}
</style>
</head>
<body>
<seva-auth id="auth" tenant-slug="my-club" api-url="https://api.seva.tools">
</seva-auth>
<div id="status" class="signed-out">Not signed in</div>
<script>
const auth = document.getElementById("auth");
const status = document.getElementById("status");
auth.addEventListener("seva:authenticated", (e) => {
status.textContent = "Signed in as " + e.detail.user.name;
status.className = "signed-in";
});
auth.addEventListener("seva:signed-out", () => {
status.textContent = "Not signed in";
status.className = "signed-out";
});
auth.addEventListener("seva:error", (e) => {
console.error("Auth error:", e.detail.message);
});
</script>
</body>
</html>