Auth
Auth is the primitive for application user identity and sessions. ViteHub owns the server-side Auth Definition, route exposure, storage placement, and runtime resolution. Your application owns the client UI.
Use Better Auth's client libraries from the browser. ViteHub does not ship framework-specific auth hooks or login components.
Install Auth
Examples on this page assume pnpm, Node 24 or newer, and a Vite server app.
pnpm add @vite-hub/auth better-auth
Register the Vite Integration.
import { hubAuth } from '@vite-hub/auth/vite'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [hubAuth()],
})
Define Auth
Create one Auth Definition for the app.
import { defineAuth } from '@vite-hub/auth'
export default defineAuth({
appName: 'My app',
database: true,
})
server/auth.ts is the canonical Auth Definition Location. You can use server.auth.ts instead when a flat server file fits the project better.
Better Auth options stay top-level. ViteHub reserves database, secondaryStorage, basePath, and route for package-owned wiring.
Expose the Auth route
The Canonical Auth Route Path is /api/auth/**. In local Vite development, the Vite Integration exposes that route by default.
When your host needs an explicit server route, or when you set route: false, mount the Auth handler yourself.
import { auth } from '@vite-hub/auth/server'
export default auth.handler
Use Manual Auth Mount only when automatic Auth Route Exposure is unavailable or intentionally disabled.
Use Better Auth on the client
Create the application client with Better Auth's own client package.
import { createAuthClient } from 'better-auth/client'
export const authClient = createAuthClient()
The default client works when the app and Auth route share the same origin and the Auth Base Path is /api/auth.
For React, Vue, Svelte, Solid, and other framework-specific clients, import from the Better Auth entrypoint for that framework. ViteHub's job is to expose the Auth server route; Better Auth owns client hooks, sign-in actions, session state, client plugins, and framework integration.
import { createAuthClient } from 'better-auth/react'
export const authClient = createAuthClient()
import { authClient } from '../lib/auth-client'
export function UserMenu() {
const { data: session, isPending } = authClient.useSession()
if (isPending) return null
if (!session) {
return <a href="/sign-in">Sign in</a>
}
return (
<button type="button" onClick={() => authClient.signOut()}>
Sign out
</button>
)
}
Read Better Auth's client documentation for framework entrypoints, fetch options, client plugins, and error handling. Read Better Auth's basic usage guide for session examples.
Customize the Auth Base Path
Set basePath when the app should expose Auth somewhere other than /api/auth.
import { defineAuth } from '@vite-hub/auth'
export default defineAuth({
appName: 'My app',
basePath: '/auth',
database: true,
})
Pass the same path to the Better Auth client.
import { createAuthClient } from 'better-auth/client'
export const authClient = createAuthClient({
basePath: '/auth',
})
basePath is route metadata. Do not put baseURL, secret, or secrets in defineAuth(). Those values are resolved at runtime by the Auth Package.
Use baseURL in the client only when the browser talks to an Auth server on a different origin.
import { createAuthClient } from 'better-auth/client'
export const authClient = createAuthClient({
baseURL: 'https://api.example.com',
})
Choose Auth storage
Auth Database Placement defaults to the selected application database when the project has a Default Database.
import { defineAuth } from '@vite-hub/auth'
export default defineAuth({
appName: 'My app',
database: true,
})
Use a named database when the app has multiple databases.
import { defineAuth } from '@vite-hub/auth'
export default defineAuth({
appName: 'My app',
database: { name: 'primary' },
})
A dedicated Auth database is explicit.
import { defineAuth } from '@vite-hub/auth'
export default defineAuth({
appName: 'My app',
database: { name: 'auth', dedicated: true },
})
Auth Secondary Storage is opt-in even when the KV Package is installed.
import { defineAuth } from '@vite-hub/auth'
export default defineAuth({
appName: 'My app',
database: true,
secondaryStorage: { store: 'auth' },
})
Storage placement is metadata in the current package layer. Runtime adapters are passed through @vite-hub/auth/server today and will be wired into the Database and KV packages in follow-up iterations.
Keep Auth separate from Agent Invokers
An Auth Session identifies an Auth User. An Agent Invocation receives an Agent Invoker. Those are separate concepts.
Use the Authenticated Agent Helper when an Agent should derive its Agent Invoker from the current Auth Session.
import { defineAgent } from '@vite-hub/agent'
import { authenticated } from '@vite-hub/auth/agent'
export default defineAgent({
invoker: authenticated(),
})
authenticated() is opt-in at the Agent or Entry Surface boundary. Merely defining Auth does not make every Agent Invocation require Auth.
For the default same-app path, authenticated() reads the Better Auth session from the request and maps the Auth User to an Agent Invoker with kind: 'authUser'. Use its id, kind, label, and meta options for common identity shaping, or provide source or map when the Agent consumes JWTs, bearer tokens, OAuth/OIDC provider output, or product-specific identity.
Auth does not move into the Agent Package and Agent identity does not become login UI.

