--- title: "StackApp" description: "Reference documentation for HexclaveClientApp and HexclaveServerApp objects." sidebarTitle: "StackApp" mode: "wide" --- import { AsideSection, ContentSection, MethodAside, MethodContent, MethodLayout, MethodReturns, } from "/snippets/sdk-type-components.jsx"; This is a detailed reference for the `StackApp` object. If you're looking for a more high-level overview, please read the [respective page in the Concepts section](/guides/going-further/hexclave-app). ## Overview - [HexclaveClientApp](#stackclientapp) - Client-level permissions for frontend code - [HexclaveServerApp](#stackserverapp) - Server-level permissions with full access --- # HexclaveClientApp A `StackApp` with client-level permissions. It contains most of the useful methods and hooks for your client-side code. Most commonly you get an instance of `HexclaveClientApp` by calling [`useHexclaveApp()`](/sdk/hooks/use-hexclave-app) in a Client Component. ## Table of Contents ```typescript type HexclaveClientApp = { new(options): HexclaveClientApp; getUser([options]): Promise; useUser([options]): User; getProject(): Promise; useProject(): Project; signInWithOAuth(provider): void; signInWithCredential([options]): Promise<...>; signUpWithCredential([options]): Promise<...>; sendForgotPasswordEmail(email): Promise<...>; sendMagicLinkEmail(email): Promise<...>; }; ``` ## Constructor Creates a new `HexclaveClientApp` instance. Because each app creates a new connection to Hexclave's backend, you should re-use existing instances wherever possible. This object is not usually constructed directly. More commonly, you would construct a [`HexclaveServerApp`](#stackserverapp) instead, pass it into your app setup (see the [setup guide](/guides/getting-started/setup)), and then use the `useHexclaveApp()` hook to obtain a `HexclaveClientApp`. The [setup wizard](/guides/getting-started/setup) does these steps for you, so you don't need to worry about it unless you are manually setting up Hexclave. If you're building a client-only app and don't have a `SECRET_SERVER_KEY`, you can construct a `HexclaveClientApp` directly. Token storage configuration. Base URL for the Hexclave API. Project ID. Defaults to the `NEXT_PUBLIC_STACK_PROJECT_ID` environment variable. Publishable client key. Defaults to the `NEXT_PUBLIC_STACK_PUBLISHABLE_CLIENT_KEY` environment variable. Redirect URL configuration. Disable automatic prefetching. ```typescript declare class HexclaveClientApp { constructor(options: { tokenStore: "nextjs-cookie" | "cookie" | { accessToken: string; refreshToken: string; } | Request; baseUrl?: string; projectId?: string; publishableClientKey?: string; urls?: object; noAutomaticPrefetch?: boolean; }); } ``` ```typescript const hexclaveClientApp = new HexclaveClientApp({ tokenStore: "nextjs-cookie", baseUrl: "https://api.hexclave.com", projectId: "123", publishableClientKey: "123", urls: { home: "/", }, }); ``` ```typescript "use client"; function MyReactComponent() { const hexclaveClientApp = useHexclaveApp(); } ``` ## User Management ### `hexclaveClientApp.getUser([options])` Gets the current user. What to do if the user is not found. ```typescript declare function getUser(options?: { or?: "return-null" | "redirect" | "throw"; }): Promise; ``` ```typescript const userOrNull = await hexclaveClientApp.getUser(); console.log(userOrNull); const user = await hexclaveClientApp.getUser({ or: "redirect" }); console.log(user); ``` ### `hexclaveClientApp.useUser([options])` React hook version of `getUser()`. Equivalent to the [`useUser()`](/sdk/hooks/use-user) standalone hook, which is an alias for `useHexclaveApp().useUser()`. What to do if the user is not found. ```typescript declare function useUser(options?: { or?: "return-null" | "redirect" | "throw"; }): CurrentUser | null; ``` ```jsx "use client"; function MyReactComponent() { const user = useUser(); return user ?
Hello, {user.name}
:
Not signed in
; } ``` ```tsx "use client"; function MyProtectedComponent() { useUser({ or: "redirect" }); return
You can only see this if you are authenticated
; } ```
### `hexclaveClientApp.getProject()` Gets the current project. ```typescript declare function getProject(): Promise; ``` ```typescript const project = await hexclaveClientApp.getProject(); ``` ### `hexclaveClientApp.useProject()` React hook version of `getProject()`. ```typescript declare function useProject(): Project; ``` ```typescript function MyReactComponent() { const project = useProject(); } ``` ## Authentication ### `hexclaveClientApp.signInWithOAuth(provider)` Initiates the OAuth sign-in process with the specified provider. The OAuth provider type. ```typescript declare function signInWithOAuth(provider: string): Promise; ``` ```typescript await hexclaveClientApp.signInWithOAuth("google"); ``` ### `hexclaveClientApp.signInWithCredential([options])` Sign in using email and password credentials. User's email. User's password. Whether to skip redirect after sign-in. ```typescript declare function signInWithCredential(options?: { email?: string; password?: string; noRedirect?: boolean; }): Promise>; ``` ```typescript const result = await hexclaveClientApp.signInWithCredential({ email: "test@example.com", password: "password", }); if (result.status === "error") { console.error("Sign in failed", result.error.message); } ``` ### `hexclaveClientApp.signUpWithCredential([options])` Sign up using email and password credentials. User's email. User's password. Whether to skip redirect after sign-up. ```typescript declare function signUpWithCredential(options?: { email?: string; password?: string; noRedirect?: boolean; }): Promise>; ``` ```typescript const result = await hexclaveClientApp.signUpWithCredential({ email: "test@example.com", password: "password", }); if (result.status === "error") { console.error("Sign up failed", result.error.message); } ``` ### `hexclaveClientApp.sendForgotPasswordEmail(email)` Send a forgot-password email to an email address. The email to send the forgot-password email to. ```typescript declare function sendForgotPasswordEmail( email: string, ): Promise>; ``` ```typescript const result = await hexclaveClientApp.sendForgotPasswordEmail("test@example.com"); if (result.status === "success") { console.log("Forgot password email sent"); } else { console.error("Failed to send forgot password email", result.error.message); } ``` ### `hexclaveClientApp.sendMagicLinkEmail(email)` Send a magic-link or OTP sign-in email to an email address. The email to send the magic link to. ```typescript declare function sendMagicLinkEmail( email: string, ): Promise>; ``` ```typescript const result = await hexclaveClientApp.sendMagicLinkEmail("test@example.com"); ``` --- # HexclaveServerApp Like `HexclaveClientApp`, but with [server permissions](/guides/going-further/hexclave-app#client-vs-server). Has full read and write access to all users. Since this functionality should only be available in environments you trust (ie. your own server), it requires a `SECRET_SERVER_KEY`. In some cases, you may want to use a `HexclaveServerApp` on the client; an example for this is an internal dashboard that only your own employees have access to. We generally recommend against doing this unless you are aware of and protected against the (potentially severe) security implications of exposing `SECRET_SERVER_KEY` on the client. ## Table of Contents ```typescript type HexclaveServerApp = // Inherits all functionality from HexclaveClientApp & HexclaveClientApp & { new(options): HexclaveServerApp; getUser([id][, options]): Promise; useUser([id][, options]): ServerUser; listUsers([options]): Promise; useUsers([options]): ServerUser[]; createUser([options]): Promise; sendEmail(options): Promise>; getTeam(id): Promise; useTeam(id): ServerTeam; listTeams([options]): Promise; useTeams([options]): ServerTeam[]; listTeamsPaginated([options]): Promise<{ items: ServerTeam[]; nextCursor: string | null }>; useTeamsPaginated([options]): { items: ServerTeam[]; nextCursor: string | null }; createTeam([options]): Promise; } ``` ## Constructor Creates a new `HexclaveServerApp` instance. Token storage configuration. Base URL for the Hexclave API. Project ID. Publishable client key. Secret server key. Defaults to the `SECRET_SERVER_KEY` environment variable. Redirect URL configuration. Disable automatic prefetching. ```typescript declare class HexclaveServerApp { constructor(options: { tokenStore: "nextjs-cookie" | "cookie" | { accessToken: string; refreshToken: string; } | Request; baseUrl?: string; projectId?: string; publishableClientKey?: string; secretServerKey?: string; urls?: object; noAutomaticPrefetch?: boolean; }); } ``` ```typescript const hexclaveServerApp = new HexclaveServerApp({ tokenStore: "nextjs-cookie", urls: { signIn: "/my-custom-sign-in-page", }, }); ``` ## User Operations ### `hexclaveServerApp.getUser([id], [options])` Enhanced version of `HexclaveClientApp.getUser()` with server permissions. **Overloads:** 1. `getUser(id: string): Promise` to get a user by ID. 2. `getUser(options?: { or?: "return-null" | "redirect" | "throw" }): Promise` to get the current user. ```typescript declare function getUser(id: string): Promise; declare function getUser(options?: { or?: "return-null" | "redirect" | "throw"; }): Promise; ``` ```typescript const currentUser = await hexclaveServerApp.getUser(); console.log(currentUser); const serverUser = await hexclaveServerApp.getUser( "12345678-1234-1234-1234-123456789abc", ); console.log(serverUser); ``` ### `hexclaveServerApp.useUser([id], [options])` Functionally equivalent to [`getUser()`](#stackserverappgetuserid-options), but as a React hook. This should be used on the server-side only. ```typescript declare function useUser( idOrOptions?: string | { or?: "return-null" | "redirect" | "throw" }, options?: { or?: "return-null" | "redirect" | "throw" }, ): ServerUser | CurrentServerUser | null; ``` ### `hexclaveServerApp.listUsers([options])` Lists all users on the project. The cursor to start the result set from. Maximum number of items to return. If omitted, all users are returned. The field to sort results by. Whether to sort in descending order. Defaults to `false`. Free-text search on the user's display name and emails. ```typescript declare function listUsers(options?: { cursor?: string; limit?: number; orderBy?: "signedUpAt"; desc?: boolean; query?: string; }): Promise; ``` ```typescript const users = await hexclaveServerApp.listUsers({ limit: 20 }); console.log(users); if (users.nextCursor) { const nextPageUsers = await hexclaveServerApp.listUsers({ cursor: users.nextCursor, limit: 20, }); console.log(nextPageUsers); } ``` ### `hexclaveServerApp.useUsers([options])` Functionally equivalent to [`listUsers()`](#stackserverapplistusersoptions), but as a React hook. This should be used on the server-side only. ```typescript declare function useUsers(options?: { cursor?: string; limit?: number; orderBy?: "signedUpAt"; desc?: boolean; query?: string; }): ServerUser[]; ``` ### `hexclaveServerApp.createUser([options])` Creates a new user from the server. User's primary email. Whether the email is verified. Whether email auth is enabled. User's password. Enable OTP or magic-link auth. User's display name. ```typescript declare function createUser(options?: { primaryEmail?: string; primaryEmailVerified?: boolean; primaryEmailAuthEnabled?: boolean; password?: string; otpAuthEnabled?: boolean; displayName?: string; }): Promise; ``` ```typescript const passwordUser = await hexclaveServerApp.createUser({ primaryEmail: "test@example.com", primaryEmailAuthEnabled: true, password: "password123", }); const magicLinkUser = await hexclaveServerApp.createUser({ primaryEmail: "test@example.com", primaryEmailVerified: true, primaryEmailAuthEnabled: true, otpAuthEnabled: true, }); ``` ### `hexclaveServerApp.sendEmail(options)` Send custom emails to users. You can send either custom HTML emails or use predefined templates with variables. Email configuration and content. The method returns a `Result` that can include `RequiresCustomEmailServer`, `SchemaError`, and `UserIdDoesNotExist`. ```typescript declare function sendEmail( options: SendEmailOptions, ): Promise>; ``` ```typescript const htmlResult = await hexclaveServerApp.sendEmail({ userIds: ["user-1", "user-2"], subject: "Welcome to our platform!", html: "

Welcome!

Thanks for joining us.

", }); if (htmlResult.status === "error") { console.error("Failed to send email:", htmlResult.error); } ``` ```typescript const templateResult = await hexclaveServerApp.sendEmail({ userIds: ["user-1"], templateId: "welcome-template", variables: { userName: "John Doe", activationUrl: "https://app.com/activate/token123", }, }); ```
## Team Management ### `hexclaveServerApp.getTeam(id)` Get a team by its ID. Team ID. ```typescript declare function getTeam(id: string): Promise; ``` ```typescript const team = await hexclaveServerApp.getTeam("team_id_123"); ``` ### `hexclaveServerApp.useTeam(id)` Functionally equivalent to [`getTeam(id)`](#stackserverappgetteamid), but as a React hook. This should be used on the server-side only. ```typescript declare function useTeam(id: string): ServerTeam; ``` ### `hexclaveServerApp.listTeams([options])` Lists all teams on the current project. For cursor-based pagination over teams, see [`listTeamsPaginated`](#stackserverapplistteamspaginatedoptions). The field to sort results by. Whether to sort in descending order. Defaults to `false`. ```typescript declare function listTeams(options?: { orderBy?: "createdAt"; desc?: boolean; }): Promise; ``` ```typescript const teams = await hexclaveServerApp.listTeams(); console.log(teams); ``` ### `hexclaveServerApp.useTeams([options])` Functionally equivalent to [`listTeams()`](#stackserverapplistteamsoptions), but as a React hook. This should be used on the server-side only. ```typescript declare function useTeams(options?: { orderBy?: "createdAt"; desc?: boolean; }): ServerTeam[]; ``` ### `hexclaveServerApp.listTeamsPaginated([options])` Lists teams on the current project with cursor-based pagination, optional filtering, and ordering. The returned array carries an extra `nextCursor` property; pass it back as `cursor` to load the next page. Cursor returned as `nextCursor` from a previous response. Maximum number of items to return. If omitted, all matching teams are returned. The field to sort results by. Whether to sort in descending order. Defaults to `false`. Free-text search on the team's display name (and team ID if the query is a UUID). ```typescript declare function listTeamsPaginated(options?: { cursor?: string; limit?: number; orderBy?: "createdAt"; desc?: boolean; query?: string; }): Promise<{ items: ServerTeam[]; nextCursor: string | null }>; ``` ```typescript const teams = await hexclaveServerApp.listTeamsPaginated({ limit: 20 }); console.log(teams); if (teams.nextCursor) { const nextPageTeams = await hexclaveServerApp.listTeamsPaginated({ cursor: teams.nextCursor, limit: 20, }); console.log(nextPageTeams); } ``` ### `hexclaveServerApp.useTeamsPaginated([options])` Functionally equivalent to [`listTeamsPaginated()`](#stackserverapplistteamspaginatedoptions), but as a React hook. This should be used on the server-side only. ```typescript declare function useTeamsPaginated(options?: { cursor?: string; limit?: number; orderBy?: "createdAt"; desc?: boolean; query?: string; }): { items: ServerTeam[]; nextCursor: string | null }; ``` ### `hexclaveServerApp.createTeam([options])` Creates a team without adding a user to it. Team display name. Team profile image URL. ```typescript declare function createTeam(options?: { displayName?: string; profileImageUrl?: string | null; }): Promise; ``` ```typescript const team = await hexclaveServerApp.createTeam({ displayName: "New Team", profileImageUrl: "https://example.com/profile.jpg", }); ```