hexclaveClientApp), plus a server app (hexclaveServerApp) if you read the user on the server. If you don’t have that yet, follow Setup first.
1. Choose your sign-in methods
New projects come with the Authentication app already enabled and email & password sign-in already turned on, so you have a working way in before you configure anything. Everything else — OTP, passkeys, and every OAuth provider — starts off, so step 1 is really about changing the mix. In a development environment, set the mix inhexclave.config.ts so it’s versioned with your code:
hexclave.config.ts
password: { allowSignIn: true } instead if you want classic email and password, and add passkey: { allowSignIn: true } for WebAuthn.
auth.allowSignUp is also on by default, so anyone can create an account until you say otherwise — step 8 covers narrowing that. If the Authentication app was ever turned off for this project, re-enable it with apps: { installed: { authentication: { enabled: true } } } or the dashboard’s app list.
Google, GitHub, Microsoft, and Spotify work immediately on Hexclave’s shared OAuth keys, so you can enable them without registering an app anywhere. Client IDs and secrets are environment-specific and live in the cloud dashboard, not in hexclave.config.ts — you’ll swap in your own before production in step 9.
accountMergeStrategy: "link_method" means someone who signed up with a password and later clicks “Sign in with Google” on the same email lands on their existing account rather than a duplicate. See Connected accounts for the other strategies.
2. Decide where your auth pages live
Hexclave renders sign-in, sign-up, password reset, and account settings for you. You only choose where those pages are served, via theurls option on your app object.
For new projects, use hosted components:
src/hexclave/client.ts
{ type: "handler-component" } plus a catch-all route on your own domain, which you want when auth UI has to be same-origin. Hosted vs. Handler covers the tradeoff and how to mix the two.
3. Add sign-in, sign-out, and account entry points
With the pages in place, your app needs to send people to them. The quickest route is<UserButton />, which covers both states on its own — an avatar menu with account settings and sign-out when someone is signed in, and sign-in and sign-up items when they aren’t. It brings its own Suspense boundary, so you can drop it straight into a header:
app.redirectToSignUp() and app.redirectToAccountSettings() round out the set. user.signOut() clears the session and then follows your afterSignOut or home URL.
Prefer auth pages inside your own layout? Mount the prebuilt <SignIn />, <SignUp />, or <AccountSettings /> components on a route you own, then point the matching urls key at that route so the redirect helpers agree with reality:
accountSettings: "/settings") still works but is deprecated, so prefer the { type: "custom", ... } form for new code.
4. Read the current user
The current user is available on the client as a hook and on the server as an async call, fully typed in both places. Both returnnull when nobody is signed in. The server version is a superset: it can read and write serverMetadata and other privileged fields, but it drops session-only methods like signOut(), which only make sense where there’s a browser session.
useUser() suspends while it loads, so it needs a Suspense boundary above it — Setup has a dedicated step for adding one. Store your own fields on the user with clientMetadata, clientReadOnlyMetadata, and serverMetadata instead of standing up a separate users table; see User fundamentals.
5. Protect a page or route
Passor to turn “maybe a user” into “definitely a user”. The return type becomes non-nullable, so there’s no null branch to forget:
Cache-Control: private, no-store on authenticated responses.
6. Collect extra information on sign-up (optional)
If you need a name, company, or address before the app is usable, don’t redirect to an onboarding page straight after sign-up — users close that tab, and it fights with the “return to the page I originally wanted” redirect. Store a flag on the user instead and check it where onboarding matters:clientReadOnlyMetadata from a server endpoint if onboarding must not be skippable, since clients can write their own clientMetadata. Full implementation, including the redirect hook: Onboarding.
7. Verify sessions on a separate backend
If your API is a different service, the browser sends the user’s access token and your backend verifies it. Hexclave issues standard JWTs you can verify locally against a JWKS endpoint, so there’s no round-trip to Hexclave per request — fast enough for middleware and edge functions. Send the token from the frontend:https://api.hexclave.com/api/v1/projects/<project-id>/.well-known/jwks.json. Note that anonymous and restricted users are signed with different issuers and audiences, so decide deliberately whether to accept them. See JWTs & session verification and Restricted users.
8. Control who can sign up (optional)
By default anyone can create an account. Sign-up rules are ordered checks overemail, emailDomain, authMethod, and oauthProvider that fire during sign-up for every method. The first matching rule wins; if none match, the default action applies.
Start with
log rules to see what they’d catch, then promote them to reject or restrict. The dashboard has a tester that simulates sign-ups without touching real users, and Fraud protection adds risk signals you can reference in the same conditions.
9. Before you ship to production
The defaults that make development frictionless are exactly the ones you need to replace. The Launch checklist tracks these four in this order:- Domains — add your production domain as a trusted domain.
- OAuth providers — swap Hexclave’s shared keys for your own client ID and secret per provider, and register the matching redirect URLs. Shared keys are development-only.
- Email server — connect a custom server so verification, reset, and magic link mail comes from your domain. See the Emails guide.
- Production mode — turn it on once the first three are done.
hexclave.config.ts.
What you should have now
- The sign-in methods you want, enabled in config
- Auth pages served either by Hexclave or from your own handler route
- Sign-in, sign-out, and account settings reachable from your UI
useUser()/getUser()reading the session on client and server- At least one route that unauthenticated visitors cannot reach
- A plan for verifying sessions on any separate backend
Related
- Authentication overview — capability FAQ
- Hosted vs. Handler — where auth pages live
- All auth providers — per-provider setup
- User fundamentals — the user object, metadata, and sessions
- Ship production-ready auth — hardening walkthrough