docs: minor updates to docs

This commit is contained in:
KinfeMichael Tariku
2025-04-14 13:35:07 +03:00
committed by GitHub
65 changed files with 163 additions and 163 deletions

View File

@@ -10,7 +10,7 @@ jobs:
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
- name: Github Releases To Discord - name: GitHub Releases To Discord
uses: SethCohen/github-releases-to-discord@v1.15.1 uses: SethCohen/github-releases-to-discord@v1.15.1
with: with:
webhook_url: ${{ secrets.WEBHOOK_URL }} webhook_url: ${{ secrets.WEBHOOK_URL }}

View File

@@ -37,7 +37,7 @@ export default async function Home() {
<div className="border-y py-2 border-dotted bg-secondary/60 opacity-80"> <div className="border-y py-2 border-dotted bg-secondary/60 opacity-80">
<div className="text-xs flex items-center gap-2 justify-center text-muted-foreground "> <div className="text-xs flex items-center gap-2 justify-center text-muted-foreground ">
<span className="text-center"> <span className="text-center">
All features on this demo are Implemented with better auth All features on this demo are implemented with Better Auth
without any custom backend code without any custom backend code
</span> </span>
</div> </div>

View File

@@ -149,7 +149,7 @@ export default function SignIn() {
d="M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5c.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34c-.46-1.16-1.11-1.47-1.11-1.47c-.91-.62.07-.6.07-.6c1 .07 1.53 1.03 1.53 1.03c.87 1.52 2.34 1.07 2.91.83c.09-.65.35-1.09.63-1.34c-2.22-.25-4.55-1.11-4.55-4.92c0-1.11.38-2 1.03-2.71c-.1-.25-.45-1.29.1-2.64c0 0 .84-.27 2.75 1.02c.79-.22 1.65-.33 2.5-.33s1.71.11 2.5.33c1.91-1.29 2.75-1.02 2.75-1.02c.55 1.35.2 2.39.1 2.64c.65.71 1.03 1.6 1.03 2.71c0 3.82-2.34 4.66-4.57 4.91c.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2" d="M12 2A10 10 0 0 0 2 12c0 4.42 2.87 8.17 6.84 9.5c.5.08.66-.23.66-.5v-1.69c-2.77.6-3.36-1.34-3.36-1.34c-.46-1.16-1.11-1.47-1.11-1.47c-.91-.62.07-.6.07-.6c1 .07 1.53 1.03 1.53 1.03c.87 1.52 2.34 1.07 2.91.83c.09-.65.35-1.09.63-1.34c-2.22-.25-4.55-1.11-4.55-4.92c0-1.11.38-2 1.03-2.71c-.1-.25-.45-1.29.1-2.64c0 0 .84-.27 2.75 1.02c.79-.22 1.65-.33 2.5-.33s1.71.11 2.5.33c1.91-1.29 2.75-1.02 2.75-1.02c.55 1.35.2 2.39.1 2.64c.65.71 1.03 1.6 1.03 2.71c0 3.82-2.34 4.66-4.57 4.91c.36.31.69.92.69 1.85V21c0 .27.16.59.67.5C19.14 20.16 22 16.42 22 12A10 10 0 0 0 12 2"
></path> ></path>
</svg> </svg>
Sign in with Github Sign in with GitHub
</Button> </Button>
<Button <Button
variant="outline" variant="outline"

View File

@@ -22,7 +22,7 @@ export const ResetPasswordEmail = ({
username, username,
resetLink, resetLink,
}: BetterAuthResetPasswordEmailProps) => { }: BetterAuthResetPasswordEmailProps) => {
const previewText = `Reset your BetterAuth password`; const previewText = `Reset your Better Auth password`;
return ( return (
<Html> <Html>
<Head /> <Head />

View File

@@ -10,7 +10,7 @@ export default function CommunityHeader() {
</h1> </h1>
<p className="dark:text-gray-400 max-w-md mx-auto text-stone-800"> <p className="dark:text-gray-400 max-w-md mx-auto text-stone-800">
join <span className="italic font-bold">better-auth</span> community join <span className="italic font-bold">better-auth</span> community
to get help, share ideas, and stay up-to-date. to get help, share ideas, and stay up to date.
</p> </p>
<div className="flex justify-center items-center mt-6 space-x-6"> <div className="flex justify-center items-center mt-6 space-x-6">
<IconLink <IconLink

View File

@@ -38,8 +38,8 @@ const grid = [
description: "Manage user accounts and sessions with ease", description: "Manage user accounts and sessions with ease",
}, },
{ {
title: "Built In Rate Limiter", title: "Built-In Rate Limiter",
description: "Built in rate limiter with custom rules", description: "Built-in rate limiter with custom rules",
}, },
{ {
title: "Automatic Database Management", title: "Automatic Database Management",

View File

@@ -100,7 +100,7 @@ const frameworks = [
), ),
}, },
{ {
title: "Solid Start", title: "SolidStart",
description: "Fine-grained reactivity goes fullstack", description: "Fine-grained reactivity goes fullstack",
Icon: () => ( Icon: () => (
<svg <svg

View File

@@ -329,7 +329,7 @@ export const contents: Content[] = [
), ),
}, },
{ {
title: "Typescript", title: "TypeScript",
href: "/docs/concepts/typescript", href: "/docs/concepts/typescript",
icon: () => ( icon: () => (
<svg <svg
@@ -1070,7 +1070,7 @@ C0.7,239.6,62.1,0.5,62.2,0.4c0,0,54,13.8,119.9,30.8S302.1,62,302.2,62c0.2,0,0.2,
href: "/docs/integrations/svelte-kit", href: "/docs/integrations/svelte-kit",
}, },
{ {
title: "Solid Start", title: "SolidStart",
icon: Icons.solidStart, icon: Icons.solidStart,
href: "/docs/integrations/solid-start", href: "/docs/integrations/solid-start",
}, },
@@ -1812,7 +1812,7 @@ export const examples: Content[] = [
icon: Icons.remix, icon: Icons.remix,
}, },
{ {
title: "Next JS", title: "Next.js",
href: "/docs/examples/next-js", href: "/docs/examples/next-js",
icon: Icons.nextJS, icon: Icons.nextJS,
}, },

View File

@@ -19,7 +19,7 @@ export const techStackIcons: TechStackIconType = {
icon: <Icons.svelteKit className="w-10 h-10" />, icon: <Icons.svelteKit className="w-10 h-10" />,
}, },
solidStart: { solidStart: {
name: "Solid Start", name: "SolidStart",
icon: <Icons.solidStart className="w-10 h-10" />, icon: <Icons.solidStart className="w-10 h-10" />,
}, },
react: { react: {

View File

@@ -101,7 +101,7 @@ Read the [Organization Plugin docs](/docs/plugins/organization#teams) for more i
### **Init CLI** ### **Init CLI**
The CLI now includes an `init` command to add better auth to your project. The CLI now includes an `init` command to add Better Auth to your project.
```bash title="terminal" ```bash title="terminal"
npx @better-auth/cli init npx @better-auth/cli init

View File

@@ -1,6 +1,6 @@
--- ---
title: v1.0 title: v1.0
description: Built in CLI for managing your project. description: Built-in CLI for managing your project.
date: 2021-10-01 date: 2021-10-01
--- ---

View File

@@ -91,7 +91,7 @@ await authClient.signOut({
To enable email verification, you need to pass a function that sends a verification email with a link. The `sendVerificationEmail` function takes a data object with the following properties: To enable email verification, you need to pass a function that sends a verification email with a link. The `sendVerificationEmail` function takes a data object with the following properties:
- `user`: The user object. - `user`: The user object.
- `url`: The url to send to the user which contains the token. - `url`: The URL to send to the user which contains the token.
- `token`: A verification token used to complete the email verification. - `token`: A verification token used to complete the email verification.
and a `request` object as the second parameter. and a `request` object as the second parameter.
@@ -171,7 +171,7 @@ await authClient.sendVerificationEmail({
To allow users to reset a password first you need to provide `sendResetPassword` function to the email and password authenticator. The `sendResetPassword` function takes a data object with the following properties: To allow users to reset a password first you need to provide `sendResetPassword` function to the email and password authenticator. The `sendResetPassword` function takes a data object with the following properties:
- `user`: The user object. - `user`: The user object.
- `url`: The url to send to the user which contains the token. - `url`: The URL to send to the user which contains the token.
- `token`: A verification token used to complete the password reset. - `token`: A verification token used to complete the password reset.
and a `request` object as the second parameter. and a `request` object as the second parameter.

View File

@@ -52,7 +52,7 @@ const authClient = createAuthClient();
const signIn = async () => { const signIn = async () => {
const data = await authClient.signIn.social({ const data = await authClient.signIn.social({
provider: "microsoft", provider: "microsoft",
callbackURL: "/dashboard", //the url to redirect to after the sign in callbackURL: "/dashboard", // The URL to redirect to after the sign in
}); });
}; };
``` ```

View File

@@ -35,8 +35,8 @@ const { data, error } = await authClient.signUp.email({
email, // user email address email, // user email address
password, // user password -> min 8 characters by default password, // user password -> min 8 characters by default
name, // user display name name, // user display name
image, // user image url (optional) image, // User image URL (optional)
callbackURL: "/dashboard" // a url to redirect to after the user verifies their email (optional) callbackURL: "/dashboard" // A URL to redirect to after the user verifies their email (optional)
}, { }, {
onRequest: (ctx) => { onRequest: (ctx) => {
//show loading //show loading
@@ -80,7 +80,7 @@ const { data, error } = await authClient.signIn.email({
*/ */
password, password,
/** /**
* a url to redirect to after the user verifies their email (optional) * A URL to redirect to after the user verifies their email (optional)
*/ */
callbackURL: "/dashboard", callbackURL: "/dashboard",
/** /**
@@ -134,7 +134,7 @@ export const auth = betterAuth({
}) })
``` ```
### Signin with social providers ### Sign in with social providers
To sign in using a social provider you need to call `signIn.social`. It takes an object with the following properties: To sign in using a social provider you need to call `signIn.social`. It takes an object with the following properties:
@@ -148,16 +148,16 @@ await authClient.signIn.social({
*/ */
provider: "github", provider: "github",
/** /**
* a url to redirect after the user authenticates with the provider * A URL to redirect after the user authenticates with the provider
* @default "/" * @default "/"
*/ */
callbackURL: "/dashboard", callbackURL: "/dashboard",
/** /**
* a url to redirect if an error occurs during the sign in process * A URL to redirect if an error occurs during the sign in process
*/ */
errorCallbackURL: "/error", errorCallbackURL: "/error",
/** /**
* a url to redirect if the user is newly registered * A URL to redirect if the user is newly registered
*/ */
newUserCallbackURL: "/welcome", newUserCallbackURL: "/welcome",
/** /**
@@ -296,8 +296,8 @@ The server provides a `session` object that you can use to access the session da
**Example: Using some popular frameworks** **Example: Using some popular frameworks**
<Tabs items={["NextJs", "Nuxt", "Svelte", "Astro", "Hono", "TanStack"]}> <Tabs items={["Next.js", "Nuxt", "Svelte", "Astro", "Hono", "TanStack"]}>
<Tab value="NextJs"> <Tab value="Next.js">
```ts title="server.ts" ```ts title="server.ts"
import { auth } from "./auth"; // path to your Better Auth server instance import { auth } from "./auth"; // path to your Better Auth server instance
import { headers } from "next/headers"; import { headers } from "next/headers";

View File

@@ -3,7 +3,7 @@ title: API
description: Better Auth API. description: Better Auth API.
--- ---
When you create a new Better Auth instance, it provides you with an `api` object. This object exposes every endpoint that exist in your better auth instance. And you can use this to interact with Better Auth server side. When you create a new Better Auth instance, it provides you with an `api` object. This object exposes every endpoint that exist in your Better Auth instance. And you can use this to interact with Better Auth server side.
Any endpoint added to Better Auth, whether from plugins or the core, will be accessible through the `api` object. Any endpoint added to Better Auth, whether from plugins or the core, will be accessible through the `api` object.

View File

@@ -1,6 +1,6 @@
--- ---
title: CLI title: CLI
description: Built in CLI for managing your project. description: Built-in CLI for managing your project.
--- ---
Better Auth comes with a built-in CLI to help you manage the database schemas, initialize your project, and generate a secret key for your application. Better Auth comes with a built-in CLI to help you manage the database schemas, initialize your project, and generate a secret key for your application.

View File

@@ -28,7 +28,7 @@ If you're using a different base path other than `/api/auth`, make sure to pass
```ts title="lib/auth-client.ts" ```ts title="lib/auth-client.ts"
import { createAuthClient } from "better-auth/client" import { createAuthClient } from "better-auth/client"
export const authClient = createAuthClient({ export const authClient = createAuthClient({
baseURL: "http://localhost:3000" // the base url of your auth server // [!code highlight] baseURL: "http://localhost:3000" // The base URL of your auth server // [!code highlight]
}) })
``` ```
</Tab> </Tab>
@@ -36,7 +36,7 @@ If you're using a different base path other than `/api/auth`, make sure to pass
```ts title="lib/auth-client.ts" ```ts title="lib/auth-client.ts"
import { createAuthClient } from "better-auth/react" import { createAuthClient } from "better-auth/react"
export const authClient = createAuthClient({ export const authClient = createAuthClient({
baseURL: "http://localhost:3000" // the base url of your auth server // [!code highlight] baseURL: "http://localhost:3000" // The base URL of your auth server // [!code highlight]
}) })
``` ```
</Tab> </Tab>
@@ -44,7 +44,7 @@ If you're using a different base path other than `/api/auth`, make sure to pass
```ts title="lib/auth-client.ts" ```ts title="lib/auth-client.ts"
import { createAuthClient } from "better-auth/vue" import { createAuthClient } from "better-auth/vue"
export const authClient = createAuthClient({ export const authClient = createAuthClient({
baseURL: "http://localhost:3000" // the base url of your auth server // [!code highlight] baseURL: "http://localhost:3000" // The base URL of your auth server // [!code highlight]
}) })
``` ```
</Tab> </Tab>
@@ -52,7 +52,7 @@ If you're using a different base path other than `/api/auth`, make sure to pass
```ts title="lib/auth-client.ts" ```ts title="lib/auth-client.ts"
import { createAuthClient } from "better-auth/svelte" import { createAuthClient } from "better-auth/svelte"
export const authClient = createAuthClient({ export const authClient = createAuthClient({
baseURL: "http://localhost:3000" // the base url of your auth server // [!code highlight] baseURL: "http://localhost:3000" // The base URL of your auth server // [!code highlight]
}) })
``` ```
</Tab> </Tab>
@@ -60,7 +60,7 @@ If you're using a different base path other than `/api/auth`, make sure to pass
```ts title="lib/auth-client.ts" ```ts title="lib/auth-client.ts"
import { createAuthClient } from "better-auth/solid" import { createAuthClient } from "better-auth/solid"
export const authClient = createAuthClient({ export const authClient = createAuthClient({
baseURL: "http://localhost:3000" // the base url of your auth server // [!code highlight] baseURL: "http://localhost:3000" // The base URL of your auth server // [!code highlight]
}) })
``` ```
</Tab> </Tab>
@@ -121,7 +121,7 @@ On top of normal methods, the client provides hooks to easily access different r
<button v-if="!session.data" @click="() => authClient.signIn.social({ <button v-if="!session.data" @click="() => authClient.signIn.social({
provider: 'github' provider: 'github'
})"> })">
Continue with github Continue with GitHub
</button> </button>
<div> <div>
<pre>{{ session.data }}</pre> <pre>{{ session.data }}</pre>
@@ -169,7 +169,7 @@ On top of normal methods, the client provides hooks to easily access different r
}); });
}} }}
> >
Continue with github Continue with GitHub
</button> </button>
{/if} {/if}
</div> </div>

View File

@@ -434,7 +434,7 @@ res.user.lang; // > "fr"
<Callout> <Callout>
See the See the
[Typescript](/docs/concepts/typescript#inferring-additional-fields-on-client) [TypeScript](/docs/concepts/typescript#inferring-additional-fields-on-client)
documentation for more information on how to infer additional fields on the documentation for more information on how to infer additional fields on the
client side. client side.
</Callout> </Callout>
@@ -585,4 +585,4 @@ To add new tables and columns to your database, you have two options:
`CLI`: Use the migrate or generate command. These commands will scan your database and guide you through adding any missing tables or columns. `CLI`: Use the migrate or generate command. These commands will scan your database and guide you through adding any missing tables or columns.
`Manual Method`: Follow the instructions in the plugin documentation to manually add tables and columns. `Manual Method`: Follow the instructions in the plugin documentation to manually add tables and columns.
Both methods ensure your database schema stays up-to-date with your plugins' requirements. Both methods ensure your database schema stays up to date with your plugins' requirements.

View File

@@ -6,7 +6,7 @@ description: Better Auth Hooks let you customize BetterAuth's behavior
Hooks in Better Auth let you "hook into" the lifecycle and execute custom logic. They provide a way to customize Better Auth's behavior without writing a full plugin. Hooks in Better Auth let you "hook into" the lifecycle and execute custom logic. They provide a way to customize Better Auth's behavior without writing a full plugin.
<Callout> <Callout>
We highly recommend using hooks if you need to make custom adjustments to an endpoint rather than making another endpoint outside of better auth. We highly recommend using hooks if you need to make custom adjustments to an endpoint rather than making another endpoint outside of Better Auth.
</Callout> </Callout>
## Before Hooks ## Before Hooks
@@ -227,7 +227,7 @@ The password object provider `hash` and `verify`
#### Adapter #### Adapter
Adapter exposes the adapter methods used by better auth. Including `findOne`, `findMany`, `create`, `delete`, `update` and `updateMany`. You generally should use your actually `db` instance from your orm rather than this adapter. Adapter exposes the adapter methods used by Better Auth. Including `findOne`, `findMany`, `create`, `delete`, `update` and `updateMany`. You generally should use your actually `db` instance from your orm rather than this adapter.
#### Internal Adapter #### Internal Adapter

View File

@@ -506,7 +506,7 @@ const myPluginClient = {
} satisfies BetterAuthClientPlugin } satisfies BetterAuthClientPlugin
``` ```
See built in plugins for examples of how to use atoms properly. See built-in plugins for examples of how to use atoms properly.
### Path methods ### Path methods

View File

@@ -6,7 +6,7 @@ description: Better Auth TypeScript integration.
Better Auth is designed to be type-safe. Both the client and server are built with TypeScript, allowing you to easily infer types. Better Auth is designed to be type-safe. Both the client and server are built with TypeScript, allowing you to easily infer types.
## Typescript Config ## TypeScript Config
### Strict Mode ### Strict Mode

View File

@@ -138,7 +138,7 @@ export const auth = betterAuth({
**How callback verification works:** **How callback verification works:**
- **Callback URL**: The url provided in `sendDeleteAccountVerification` is a pre-generated link that deletes the user data when accessed. - **Callback URL**: The URL provided in `sendDeleteAccountVerification` is a pre-generated link that deletes the user data when accessed.
```ts title="delete-user.ts" ```ts title="delete-user.ts"
await authClient.deleteUser({ await authClient.deleteUser({

View File

@@ -20,7 +20,7 @@ See [Demo](https://demo.better-auth.com)
borderRadius: "4px", borderRadius: "4px",
overflow: "hidden" overflow: "hidden"
}} }}
title="Better Auth Next Js Example" title="Better Auth Next.js Example"
allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking" allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking"
sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts"
> >

View File

@@ -10,7 +10,7 @@ If you would like to view a completed example, you can check out the <Link href=
<Callout type="warn"> <Callout type="warn">
The Plasmo framework does not provide a backend for the browser extension. The Plasmo framework does not provide a backend for the browser extension.
This guide assumes you have{" "} This guide assumes you have{" "}
<Link href="/docs/integrations/hono">a backend setup</Link> of BetterAuth and <Link href="/docs/integrations/hono">a backend setup</Link> of Better Auth and
are ready to create a browser extension to connect to it. are ready to create a browser extension to connect to it.
</Callout> </Callout>
@@ -25,7 +25,7 @@ If you would like to view a completed example, you can check out the <Link href=
pnpm create plasmo --with-tailwindcss --with-src pnpm create plasmo --with-tailwindcss --with-src
``` ```
Then, install the BetterAuth package. Then, install the Better Auth package.
```bash ```bash
pnpm add better-auth pnpm add better-auth
@@ -79,7 +79,7 @@ If you would like to view a completed example, you can check out the <Link href=
import { createAuthClient } from "better-auth/react" import { createAuthClient } from "better-auth/react"
export const authClient = createAuthClient({ export const authClient = createAuthClient({
baseURL: "http://localhost:3000" /* base url of your Better Auth backend. */, baseURL: "http://localhost:3000" /* Base URL of your Better Auth backend. */,
plugins: [], plugins: [],
}); });
``` ```
@@ -88,7 +88,7 @@ If you would like to view a completed example, you can check out the <Link href=
<Step> <Step>
## Configure the manifest ## Configure the manifest
We must ensure the extension knows the URL to the BetterAuth backend. We must ensure the extension knows the URL to the Better Auth backend.
Head to your package.json file, and add the following code. Head to your package.json file, and add the following code.
@@ -108,11 +108,11 @@ If you would like to view a completed example, you can check out the <Link href=
<Step> <Step>
## You're now ready! ## You're now ready!
You have now setup BetterAuth for your browser extension. You have now set up Better Auth for your browser extension.
Add your desired UI and create your dream extension! Add your desired UI and create your dream extension!
To learn more about the client BetterAuth API, check out the <Link href="/docs/concepts/client">client documentation</Link>. To learn more about the client Better Auth API, check out the <Link href="/docs/concepts/client">client documentation</Link>.
Heres a quick example 😎 Heres a quick example 😎
@@ -195,9 +195,9 @@ If you would like to view a completed example, you can check out the <Link href=
## Wrapping Up ## Wrapping Up
Congratulations! Youve successfully created a browser extension using BetterAuth and Plasmo. Congratulations! Youve successfully created a browser extension using Better Auth and Plasmo.
We highly recommend you visit the <Link href="https://docs.plasmo.com/">Plasmo documentation</Link> to learn more about the framework. We highly recommend you visit the <Link href="https://docs.plasmo.com/">Plasmo documentation</Link> to learn more about the framework.
If you would like to view a completed example, you can check out the <Link href="https://github.com/better-auth/better-auth/tree/main/examples/browser-extension-example">browser extension example</Link>. If you would like to view a completed example, you can check out the <Link href="https://github.com/better-auth/better-auth/tree/main/examples/browser-extension-example">browser extension example</Link>.
If you have any questions, feel free to open an issue on our <Link href="https://github.com/better-auth/better-auth/issues">Github repo</Link>, or join our <Link href="https://discord.gg/6jHcdYMzyq">Discord server</Link> for support. If you have any questions, feel free to open an issue on our <Link href="https://github.com/better-auth/better-auth/issues">GitHub repo</Link>, or join our <Link href="https://discord.gg/6jHcdYMzyq">Discord server</Link> for support.

View File

@@ -32,7 +32,7 @@ Read more about [cookie caching](/docs/concepts/session-management#cookie-cache)
Here are examples of how you can do caching in different frameworks and environments: Here are examples of how you can do caching in different frameworks and environments:
<Tabs items={["NextJs", "Remix", "Solid Start", "React Query"]}> <Tabs items={["Next.js", "Remix", "SolidStart", "React Query"]}>
<Tab value="NextJS"> <Tab value="NextJS">
Since Next v15, we can use the `"use cache"` directive to cache the response of a server function. Since Next v15, we can use the `"use cache"` directive to cache the response of a server function.
@@ -68,8 +68,8 @@ Here are examples of how you can do caching in different frameworks and environm
</Tab> </Tab>
<Tab value="Solid Start"> <Tab value="SolidStart">
In Solid Start, you can use the `query` function to cache data. Heres an example: In SolidStart, you can use the `query` function to cache data. Heres an example:
```tsx ```tsx
const getUsers = query( const getUsers = query(
@@ -78,7 +78,7 @@ Here are examples of how you can do caching in different frameworks and environm
); );
``` ```
Learn more about Solid Start `query` function <Link href="https://docs.solidjs.com/solid-router/reference/data-apis/query">here</Link>. Learn more about SolidStart `query` function <Link href="https://docs.solidjs.com/solid-router/reference/data-apis/query">here</Link>.
</Tab> </Tab>
<Tab value="React Query"> <Tab value="React Query">

View File

@@ -125,7 +125,7 @@ This tables will be created on the `public` schema.
<Step> <Step>
### Copy the migration script ### Copy the migration script
Now that we have the necessary tables in our database, we can run the migration script to migrate the users and accounts from supabase to better auth. Now that we have the necessary tables in our database, we can run the migration script to migrate the users and accounts from Supabase to Better Auth.
Start by creating a `.ts` file in your project. Start by creating a `.ts` file in your project.
@@ -259,7 +259,7 @@ migrateFromSupabase();
<Step> <Step>
### Run the migration script ### Run the migration script
Run the migration script to migrate the users and accounts from supabase to better auth. Run the migration script to migrate the users and accounts from Supabase to Better Auth.
```bash title="Terminal" ```bash title="Terminal"
bun migration.ts # or use node, ts-node, etc. bun migration.ts # or use node, ts-node, etc.
@@ -268,9 +268,9 @@ bun migration.ts # or use node, ts-node, etc.
<Step> <Step>
### Update your code ### Update your code
Update your codebase from supabase auth calls to better auth api. Update your codebase from Supabase auth calls to Better Auth API.
Here's a list of the supabase auth api calls and their better auth counterparts. Here's a list of the Supabase auth API calls and their Better Auth counterparts.
- `supabase.auth.signUp` -> `authClient.signUp.email` - `supabase.auth.signUp` -> `authClient.signUp.email`
- `supabase.auth.signInWithPassword` -> `authClient.signIn.email` - `supabase.auth.signInWithPassword` -> `authClient.signIn.email`

View File

@@ -86,7 +86,7 @@ export const birthdayPlugin = () =>
<Step> <Step>
### Authorization logic ### Authorization logic
For this example guide, well setup authentication logic to check and ensure that the user who signs-up is older than 5. For this example guide, well set up authentication logic to check and ensure that the user who signs-up is older than 5.
But the same concept could be applied for something like verifying users agreeing to the TOS or anything alike. But the same concept could be applied for something like verifying users agreeing to the TOS or anything alike.
To do this, well utilize <Link href="/docs/concepts/plugins#hooks">Hooks</Link>, which allows us to run code `before` or `after` an action is performed. To do this, well utilize <Link href="/docs/concepts/plugins#hooks">Hooks</Link>, which allows us to run code `before` or `after` an action is performed.

View File

@@ -228,7 +228,7 @@ You can use even more authentication methods like [passkey](/docs/plugins/passke
<Step> <Step>
### Mount Handler ### Mount Handler
To handle api requests, you need to set up a route handler on your server. To handle API requests, you need to set up a route handler on your server.
Create a new file or route in your framework's designated catch-all route handler. This route should handle requests for the path `/api/auth/*` (unless you've configured a different base path). Create a new file or route in your framework's designated catch-all route handler. This route should handle requests for the path `/api/auth/*` (unless you've configured a different base path).
@@ -391,10 +391,10 @@ The client-side library helps you interact with the auth server. Better Auth com
1. Import `createAuthClient` from the package for your framework (e.g., "better-auth/react" for React). 1. Import `createAuthClient` from the package for your framework (e.g., "better-auth/react" for React).
2. Call the function to create your client. 2. Call the function to create your client.
3. Pass the base url of your auth server. (If the auth server is running on the same domain as your client, you can skip this step.) 3. Pass the base URL of your auth server. (If the auth server is running on the same domain as your client, you can skip this step.)
<Callout type="info"> <Callout type="info">
If you're using a different base path other than `/api/auth` make sure to pass the whole url including the path. (e.g. `http://localhost:3000/custom-path/auth`) If you're using a different base path other than `/api/auth` make sure to pass the whole URL including the path. (e.g. `http://localhost:3000/custom-path/auth`)
</Callout> </Callout>
<Tabs items={["react", "vue", "svelte", "solid", <Tabs items={["react", "vue", "svelte", "solid",
@@ -403,7 +403,7 @@ If you're using a different base path other than `/api/auth` make sure to pass t
```ts title="lib/auth-client.ts" ```ts title="lib/auth-client.ts"
import { createAuthClient } from "better-auth/client" import { createAuthClient } from "better-auth/client"
export const authClient = createAuthClient({ export const authClient = createAuthClient({
/** the base url of the server (optional if you're using the same domain) */ // [!code highlight] /** The base URL of the server (optional if you're using the same domain) */ // [!code highlight]
baseURL: "http://localhost:3000" // [!code highlight] baseURL: "http://localhost:3000" // [!code highlight]
}) })
``` ```
@@ -412,7 +412,7 @@ If you're using a different base path other than `/api/auth` make sure to pass t
```ts title="lib/auth-client.ts" ```ts title="lib/auth-client.ts"
import { createAuthClient } from "better-auth/react" import { createAuthClient } from "better-auth/react"
export const authClient = createAuthClient({ export const authClient = createAuthClient({
/** the base url of the server (optional if you're using the same domain) */ // [!code highlight] /** The base URL of the server (optional if you're using the same domain) */ // [!code highlight]
baseURL: "http://localhost:3000" // [!code highlight] baseURL: "http://localhost:3000" // [!code highlight]
}) })
``` ```
@@ -421,7 +421,7 @@ If you're using a different base path other than `/api/auth` make sure to pass t
```ts title="lib/auth-client.ts" ```ts title="lib/auth-client.ts"
import { createAuthClient } from "better-auth/vue" import { createAuthClient } from "better-auth/vue"
export const authClient = createAuthClient({ export const authClient = createAuthClient({
/** the base url of the server (optional if you're using the same domain) */ // [!code highlight] /** The base URL of the server (optional if you're using the same domain) */ // [!code highlight]
baseURL: "http://localhost:3000" // [!code highlight] baseURL: "http://localhost:3000" // [!code highlight]
}) })
``` ```
@@ -430,7 +430,7 @@ If you're using a different base path other than `/api/auth` make sure to pass t
```ts title="lib/auth-client.ts" ```ts title="lib/auth-client.ts"
import { createAuthClient } from "better-auth/svelte" import { createAuthClient } from "better-auth/svelte"
export const authClient = createAuthClient({ export const authClient = createAuthClient({
/** the base url of the server (optional if you're using the same domain) */ // [!code highlight] /** The base URL of the server (optional if you're using the same domain) */ // [!code highlight]
baseURL: "http://localhost:3000" // [!code highlight] baseURL: "http://localhost:3000" // [!code highlight]
}) })
``` ```
@@ -439,7 +439,7 @@ If you're using a different base path other than `/api/auth` make sure to pass t
```ts title="lib/auth-client.ts" ```ts title="lib/auth-client.ts"
import { createAuthClient } from "better-auth/solid" import { createAuthClient } from "better-auth/solid"
export const authClient = createAuthClient({ export const authClient = createAuthClient({
/** the base url of the server (optional if you're using the same domain) */ // [!code highlight] /** The base URL of the server (optional if you're using the same domain) */ // [!code highlight]
baseURL: "http://localhost:3000" // [!code highlight] baseURL: "http://localhost:3000" // [!code highlight]
}) })
``` ```

View File

@@ -69,7 +69,7 @@ Expo is a popular framework for building cross-platform apps with React Native.
<Step> <Step>
## Initialize Better Auth Client ## Initialize Better Auth Client
To initialize Better Auth in your Expo app, you need to call `createAuthClient` with the base url of your Better Auth backend. Make sure to import the client from `/react`. To initialize Better Auth in your Expo app, you need to call `createAuthClient` with the base URL of your Better Auth backend. Make sure to import the client from `/react`.
You need to also import client plugin from `@better-auth/expo/client` and pass it to the `plugins` array when initializing the auth client. You need to also import client plugin from `@better-auth/expo/client` and pass it to the `plugins` array when initializing the auth client.
@@ -84,7 +84,7 @@ Expo is a popular framework for building cross-platform apps with React Native.
import * as SecureStore from "expo-secure-store"; import * as SecureStore from "expo-secure-store";
export const authClient = createAuthClient({ export const authClient = createAuthClient({
baseURL: "http://localhost:8081", /* base url of your Better Auth backend. */ baseURL: "http://localhost:8081", /* Base URL of your Better Auth backend. */
plugins: [ plugins: [
expoClient({ expoClient({
scheme: "myapp", scheme: "myapp",
@@ -126,7 +126,7 @@ Expo is a popular framework for building cross-platform apps with React Native.
<Step> <Step>
## Configure Metro Bundler ## Configure Metro Bundler
To resolve better auth exports you'll need to enable `unstable_enablePackageExports` in your metro config. To resolve Better Auth exports you'll need to enable `unstable_enablePackageExports` in your metro config.
```js title="metro.config.js" ```js title="metro.config.js"
const { getDefaultConfig } = require("expo/metro-config"); const { getDefaultConfig } = require("expo/metro-config");

View File

@@ -73,7 +73,7 @@ Here's an example of how to use `getSession` in an Express route:
```ts title="server.ts" ```ts title="server.ts"
import { fromNodeHeaders } from "better-auth/node"; import { fromNodeHeaders } from "better-auth/node";
import { auth } from "./auth"; //your better auth instance import { auth } from "./auth"; // Your Better Auth instance
app.get("/api/me", async (req, res) => { app.get("/api/me", async (req, res) => {
const session = await auth.api.getSession({ const session = await auth.api.getSession({

View File

@@ -78,7 +78,7 @@ npx prisma db push
Follow steps 1 & 2 from the [installation guide](/docs/installation) to install Better Auth in your Nitro application & set up the environment variables. Follow steps 1 & 2 from the [installation guide](/docs/installation) to install Better Auth in your Nitro application & set up the environment variables.
Once that is done, create your better auth instance within the `server/utils/auth.ts` file. Once that is done, create your Better Auth instance within the `server/utils/auth.ts` file.
```ts title="server/utils/auth.ts" ```ts title="server/utils/auth.ts"
import { betterAuth } from "better-auth"; import { betterAuth } from "better-auth";

View File

@@ -56,7 +56,7 @@ const session = authClient.useSession()
<button v-if="!session?.data" @click="() => authClient.signIn.social({ <button v-if="!session?.data" @click="() => authClient.signIn.social({
provider: 'github' provider: 'github'
})"> })">
Continue with github Continue with GitHub
</button> </button>
<div> <div>
<pre>{{ session.data }}</pre> <pre>{{ session.data }}</pre>
@@ -127,5 +127,5 @@ export default defineNuxtRouteMiddleware(async (to, from) => {
### Resources & Examples ### Resources & Examples
- [Nuxt and Nuxt Hub example](https://github.com/atinux/nuxthub-better-auth) on GitHub. - [Nuxt and Nuxt Hub example](https://github.com/atinux/nuxthub-better-auth) on GitHub.
- [NuxtZzle is Nuxt,Drizzle ORM example](https://github.com/leamsigc/nuxt-better-auth-drizzle) on github [preview](https://nuxt-better-auth.giessen.dev/) - [NuxtZzle is Nuxt,Drizzle ORM example](https://github.com/leamsigc/nuxt-better-auth-drizzle) on GitHub [preview](https://nuxt-better-auth.giessen.dev/)
- [Nuxt example](https://stackblitz.com/github/better-auth/better-auth/tree/main/examples/nuxt-example) on StackBlitz. - [Nuxt example](https://stackblitz.com/github/better-auth/better-auth/tree/main/examples/nuxt-example) on StackBlitz.

View File

@@ -61,8 +61,8 @@ Some of the actions are reactive. The client use [nano-store](https://github.com
}); });
}} }}
> >
Continue with github Continue with GitHub
</button> </button>
{/if} {/if}
</div> </div>
``` ```

View File

@@ -7,7 +7,7 @@ Better Auth is a framework-agnostic authentication and authorization framework f
## Why Better Auth? ## Why Better Auth?
*Authentication in the TypeScript ecosystem has long been a half-solved problem. Other open-source libraries often require a lot of additional code for anything beyond basic authentication features. Rather than just pushing third-party services as the solution, I believe we can do better as a community—hence, Better Auth* *Authentication in the TypeScript ecosystem has long been a half-solved problem. Other open-source libraries often require a lot of additional code for anything beyond basic authentication features. Rather than just pushing third-party services as the solution, I believe we can do better as a community—hence, Better Auth.*
## Features ## Features

View File

@@ -535,7 +535,7 @@ console.log(apiKey.metadata.plan); // "premium"
`apiKeyHeaders` <span className="opacity-70">`string | string[];`</span> `apiKeyHeaders` <span className="opacity-70">`string | string[];`</span>
The header name to check for api key. Default is `x-api-key`. The header name to check for API key. Default is `x-api-key`.
`customAPIKeyGetter` <span className="opacity-70">`(ctx: GenericEndpointContext) => string | null`</span> `customAPIKeyGetter` <span className="opacity-70">`(ctx: GenericEndpointContext) => string | null`</span>
@@ -656,7 +656,7 @@ Customize the rate-limiting.
`schema` <span className="opacity-70">`InferOptionSchema<ReturnType<typeof apiKeySchema>>`</span> `schema` <span className="opacity-70">`InferOptionSchema<ReturnType<typeof apiKeySchema>>`</span>
Custom schema for the api key plugin. Custom schema for the API key plugin.
`disableSessionForAPIKeys` <span className="opacity-70">`boolean`</span> `disableSessionForAPIKeys` <span className="opacity-70">`boolean`</span>
@@ -687,7 +687,7 @@ Table: `apiKey`
{ {
name: "id", name: "id",
type: "string", type: "string",
description: "The ID of the api key.", description: "The ID of the API key.",
isUnique: true, isUnique: true,
isPrimaryKey: true, isPrimaryKey: true,
}, },

View File

@@ -3,7 +3,7 @@ title: Email OTP
description: Email OTP plugin for Better Auth. description: Email OTP plugin for Better Auth.
--- ---
The Email OTP plugin allows user to sign-in, verify their email, or reset their password using a one-time password (OTP) sent to their email address. The Email OTP plugin allows user to sign in, verify their email, or reset their password using a one-time password (OTP) sent to their email address.
## Installation ## Installation
@@ -59,7 +59,7 @@ const { data, error } = await authClient.emailOtp.sendVerificationOtp({
}) })
``` ```
### SignIn with OTP ### Sign in with OTP
Once the user provides the OTP, you can sign in the user using the `signIn.emailOTP()` method. Once the user provides the OTP, you can sign in the user using the `signIn.emailOTP()` method.

View File

@@ -122,8 +122,8 @@ async function validateToken(token: string) {
new URL('http://localhost:3000/api/auth/jwks') new URL('http://localhost:3000/api/auth/jwks')
) )
const { payload } = await jwtVerify(token, JWKS, { const { payload } = await jwtVerify(token, JWKS, {
issuer: 'http://localhost:3000', // Should match your JWT issuer which is the BASE_URL issuer: 'http://localhost:3000', // Should match your JWT issuer, which is the BASE_URL
audience: 'http://localhost:3000', // Should match your JWT audience which is the BASE_URL by default audience: 'http://localhost:3000', // Should match your JWT audience, which is the BASE_URL by default
}) })
return payload return payload
} catch (error) { } catch (error) {
@@ -158,8 +158,8 @@ async function validateToken(token: string) {
keys: storedJWKS.data?.keys!, keys: storedJWKS.data?.keys!,
}) })
const { payload } = await jwtVerify(token, JWKS, { const { payload } = await jwtVerify(token, JWKS, {
issuer: 'http://localhost:3000', // Should match your JWT issuer which is the BASE_URL issuer: 'http://localhost:3000', // Should match your JWT issuer, which is the BASE_URL
audience: 'http://localhost:3000', // Should match your JWT audience which is the BASE_URL by default audience: 'http://localhost:3000', // Should match your JWT audience, which is the BASE_URL by default
}) })
return payload return payload
} catch (error) { } catch (error) {

View File

@@ -70,7 +70,7 @@ When you send the URL generated by the `sendMagicLink` function to a user, click
If no `callbackURL` is provided, the user will be redirected to the root URL. If no `callbackURL` is provided, the user will be redirected to the root URL.
</Callout> </Callout>
If you want to handle the verification manually, (e.g, if you send the user a different url), you can use the `verify` function. If you want to handle the verification manually, (e.g, if you send the user a different URL), you can use the `verify` function.
```ts title="magic-link.ts" ```ts title="magic-link.ts"
const { data, error } = await authClient.magicLink.verify({ const { data, error } = await authClient.magicLink.verify({
@@ -85,8 +85,8 @@ const { data, error } = await authClient.magicLink.verify({
**sendMagicLink**: The `sendMagicLink` function is called when a user requests a magic link. It takes an object with the following properties: **sendMagicLink**: The `sendMagicLink` function is called when a user requests a magic link. It takes an object with the following properties:
- `email`: The email address of the user. - `email`: The email address of the user.
- `url`: The url to be sent to the user. This url contains the token. - `url`: The URL to be sent to the user. This URL contains the token.
- `token`: The token if you want to send the token with custom url. - `token`: The token if you want to send the token with custom URL.
and a `request` object as the second parameter. and a `request` object as the second parameter.

View File

@@ -58,7 +58,7 @@ await authClient.signIn.social({
When the OAuth provider returns the user to your server, the plugin automatically redirects them to the intended callback URL. When the OAuth provider returns the user to your server, the plugin automatically redirects them to the intended callback URL.
<Callout> <Callout>
To share cookies between the proxy server and your main server it uses url query parameters to pass the cookies encrypted in the URL. This is secure as the cookies are encrypted and can only be decrypted by the server. To share cookies between the proxy server and your main server it uses URL query parameters to pass the cookies encrypted in the URL. This is secure as the cookies are encrypted and can only be decrypted by the server.
</Callout> </Callout>
## Options ## Options

View File

@@ -5,7 +5,7 @@ description: Passkey
Passkeys are a secure, passwordless authentication method using cryptographic key pairs, supported by WebAuthn and FIDO2 standards in web browsers. They replace passwords with unique key pairs: a private key stored on the users device and a public key shared with the website. Users can log in using biometrics, PINs, or security keys, providing strong, phishing-resistant authentication without traditional passwords. Passkeys are a secure, passwordless authentication method using cryptographic key pairs, supported by WebAuthn and FIDO2 standards in web browsers. They replace passwords with unique key pairs: a private key stored on the users device and a public key shared with the website. Users can log in using biometrics, PINs, or security keys, providing strong, phishing-resistant authentication without traditional passwords.
The passkey plugin implementation is powered by [simple-web-authn](https://simplewebauthn.dev/) behind the scenes. The passkey plugin implementation is powered by [SimpleWebAuthn](https://simplewebauthn.dev/) behind the scenes.
## Installation ## Installation
@@ -20,7 +20,7 @@ The passkey plugin implementation is powered by [simple-web-authn](https://simpl
`rpName`: Human-readable title for your website `rpName`: Human-readable title for your website
`origin`: The URL at which registrations and authentications should occur. 'http://localhost' and 'http://localhost:PORT' are also valid. Do **NOT** include any trailing / `origin`: The URL at which registrations and authentications should occur. `http://localhost` and `http://localhost:PORT` are also valid. Do **NOT** include any trailing /
`authenticatorSelection`: Allows customization of WebAuthn authenticator selection criteria. Leave unspecified for default settings. `authenticatorSelection`: Allows customization of WebAuthn authenticator selection criteria. Leave unspecified for default settings.
- `authenticatorAttachment`: Specifies the type of authenticator - `authenticatorAttachment`: Specifies the type of authenticator
@@ -109,7 +109,7 @@ const { data, error } = await authClient.passkey.addPasskey();
This will prompt the user to register a passkey. And it'll add the passkey to the user's account. This will prompt the user to register a passkey. And it'll add the passkey to the user's account.
You can also specify the type of authenticator you want to register. The authenticatorAttachment can be either `platform` or `cross-platform`. You can also specify the type of authenticator you want to register. The `authenticatorAttachment` can be either `platform` or `cross-platform`.
```ts title="auth-client.ts" ```ts title="auth-client.ts"
// Register a cross-platform passkey showing only a QR code // Register a cross-platform passkey showing only a QR code
@@ -119,9 +119,9 @@ const { data, error } = await authClient.passkey.addPasskey({
}); });
``` ```
### Signin with a passkey ### Sign in with a passkey
To signin with a passkey you can use the passkeySignIn method. This will prompt the user to sign in with their passkey. To sign in with a passkey you can use the passkeySignIn method. This will prompt the user to sign in with their passkey.
Signin method accepts: Signin method accepts:
@@ -267,6 +267,6 @@ Table Name: `passkey`
**rpName**: Human-readable title for your website. **rpName**: Human-readable title for your website.
**origin**: The URL at which registrations and authentications should occur. 'http://localhost' and 'http://localhost:PORT' are also valid. Do NOT include any trailing /. **origin**: The URL at which registrations and authentications should occur. `http://localhost` and `http://localhost:PORT` are also valid. Do NOT include any trailing /.
**authenticatorSelection**: Allows customization of WebAuthn authenticator selection criteria. When unspecified, both platform and cross-platform authenticators are allowed with `preferred` settings for `residentKey` and `userVerification`. **authenticatorSelection**: Allows customization of WebAuthn authenticator selection criteria. When unspecified, both platform and cross-platform authenticators are allowed with `preferred` settings for `residentKey` and `userVerification`.

View File

@@ -111,7 +111,7 @@ export const auth = betterAuth({
}) })
``` ```
### SignIn with Phone number ### Sign In with Phone Number
In addition to signing in a user using send-verify flow, you can also use phone number as an identifier and sign in a user using phone number and password. In addition to signing in a user using send-verify flow, you can also use phone number as an identifier and sign in a user using phone number and password.

View File

@@ -170,7 +170,7 @@ const res = await authClient.signIn.sso({
}); });
``` ```
To use the server api you can use `signInSSO` To use the server API you can use `signInSSO`
```ts title="sign-in-org.ts" ```ts title="sign-in-org.ts"
const res = await auth.api.signInSSO({ const res = await auth.api.signInSSO({
@@ -216,7 +216,7 @@ The plugin requires additional fields in the `ssoProvider` table to store the pr
{ name: "domain", type: "string", description: "The domain of the provider", isRequired: true }, { name: "domain", type: "string", description: "The domain of the provider", isRequired: true },
{ name: "oidcConfig", type: "string", description: "The OIDC configuration", isRequired: false }, { name: "oidcConfig", type: "string", description: "The OIDC configuration", isRequired: false },
{ name: "userId", type: "string", description: "The user id", isRequired: true, references: { model: "user", field: "id" } }, { name: "userId", type: "string", description: "The user id", isRequired: true, references: { model: "user", field: "id" } },
{ name: "providerId", type: "string", description: "The provider id. Used to identify a provider and to generate a redirect url.", isRequired: true, isUnique: true }, { name: "providerId", type: "string", description: "The provider id. Used to identify a provider and to generate a redirect URL.", isRequired: true, isUnique: true },
{ name: "organizationId", type: "string", description: "The organization Id. If provider is linked to an organization.", isRequired: false }, { name: "organizationId", type: "string", description: "The organization Id. If provider is linked to an organization.", isRequired: false },
]} ]}
/> />

View File

@@ -59,7 +59,7 @@ The username plugin wraps the email and password authenticator and adds username
## Usage ## Usage
### Signup with username ### Sign up with username
To sign up a user with username, you can use the existing `signUp.email` function provided by the client. The `signUp` function should take a new `username` property in the object. To sign up a user with username, you can use the existing `signUp.email` function provided by the client. The `signUp` function should take a new `username` property in the object.
@@ -72,9 +72,9 @@ const data = await authClient.signUp.email({
}) })
``` ```
### Signin with username ### Sign in with username
To signin a user with username, you can use the `signIn.username` function provided by the client. The `signIn` function takes an object with the following properties: To sign in a user with username, you can use the `signIn.username` function provided by the client. The `signIn` function takes an object with the following properties:
- `username`: The username of the user. - `username`: The username of the user.
- `password`: The password of the user. - `password`: The password of the user.

View File

@@ -137,7 +137,7 @@ We welcome contributions to support more frameworks:
- Fix typos and errors - Fix typos and errors
- Add examples and clarify existing content - Add examples and clarify existing content
- Ensure documentation is up-to-date with code changes - Ensure documentation is up to date with code changes
## Testing ## Testing

View File

@@ -78,7 +78,7 @@ For all other situations where you shouldn't use `useSession`, is when you shoul
</Callout> </Callout>
</Accordion> </Accordion>
<Accordion title="Common Typescript Errors"> <Accordion title="Common TypeScript Errors">
If you're facing typescript errors, make sure your tsconfig has `strict` set to `true`: If you're facing typescript errors, make sure your tsconfig has `strict` set to `true`:
```json title="tsconfig.json" ```json title="tsconfig.json"
{ {
@@ -97,7 +97,7 @@ if you can't set strict to true, you can enable strictNullChecks:
} }
``` ```
You can learn more in our <Link href="/docs/concepts/typescript#typescript-config">Typescript docs</Link>. You can learn more in our <Link href="/docs/concepts/typescript#typescript-config">TypeScript docs</Link>.
</Accordion> </Accordion>
</Accordions> </Accordions>

View File

@@ -59,7 +59,7 @@ export default function Index() {
}} }}
> >
<Ionicons name="github" size={16} /> <Ionicons name="github" size={16} />
<Text>Sign In with Github</Text> <Text>Sign In with GitHub</Text>
</Button> </Button>
</View> </View>
<View className="flex-row gap-2 w-full items-center px-6 my-4"> <View className="flex-row gap-2 w-full items-center px-6 my-4">

View File

@@ -43,7 +43,7 @@ const { data: session } = await useSession(useFetch);
<div class="border-y py-2 border-dotted bg-secondary/60 opacity-80"> <div class="border-y py-2 border-dotted bg-secondary/60 opacity-80">
<div class="text-xs flex items-center gap-2 justify-center text-muted-foreground"> <div class="text-xs flex items-center gap-2 justify-center text-muted-foreground">
<span class="text-center"> <span class="text-center">
All features on this demo are Implemented with better auth without All features on this demo are Implemented with Better Auth without
any custom backend code any custom backend code
</span> </span>
</div> </div>

View File

@@ -31,7 +31,7 @@ $: to = $session.data ? "/dashboard" : "/sign-in";
class="text-xs flex items-center gap-2 justify-center text-muted-foreground" class="text-xs flex items-center gap-2 justify-center text-muted-foreground"
> >
<span class="text-center"> <span class="text-center">
All features on this demo are Implemented with better auth without All features on this demo are Implemented with Better Auth without
any custom backend code any custom backend code
</span> </span>
</div> </div>

View File

@@ -518,7 +518,7 @@ describe("api-key", async () => {
expect(apiKey.metadata.test).toEqual(metadata.test); expect(apiKey.metadata.test).toEqual(metadata.test);
}); });
it("create api key with with metadata when metadata is disabled (should fail)", async () => { it("create API key with with metadata when metadata is disabled (should fail)", async () => {
const { client, auth, signInWithTestUser } = await getTestInstance( const { client, auth, signInWithTestUser } = await getTestInstance(
{ {
plugins: [ plugins: [
@@ -673,7 +673,7 @@ describe("api-key", async () => {
// VERIFY API KEY // VERIFY API KEY
// ========================================================================= // =========================================================================
it("verify api key without key and userId", async () => { it("verify API key without key and userId", async () => {
const apiKey = await auth.api.verifyApiKey({ const apiKey = await auth.api.verifyApiKey({
body: { body: {
key: firstApiKey.key, key: firstApiKey.key,
@@ -683,7 +683,7 @@ describe("api-key", async () => {
expect(apiKey.valid).toBe(true); expect(apiKey.valid).toBe(true);
}); });
it("verify api key with invalid key (should fail)", async () => { it("verify API key with invalid key (should fail)", async () => {
const apiKey = await auth.api.verifyApiKey({ const apiKey = await auth.api.verifyApiKey({
body: { body: {
key: "invalid", key: "invalid",
@@ -719,7 +719,7 @@ describe("api-key", async () => {
const { headers: rateLimitUserHeaders } = await rateLimitTestUser(); const { headers: rateLimitUserHeaders } = await rateLimitTestUser();
it("should fail to verify api key 20 times in a row due to rate-limit", async () => { it("should fail to verify API key 20 times in a row due to rate-limit", async () => {
const { data: apiKey2 } = await rateLimitClient.apiKey.create( const { data: apiKey2 } = await rateLimitClient.apiKey.create(
{}, {},
{ headers: rateLimitUserHeaders }, { headers: rateLimitUserHeaders },
@@ -741,7 +741,7 @@ describe("api-key", async () => {
} }
}); });
it("should allow us to verify api key after rate-limit window has passed", async () => { it("should allow us to verify API key after rate-limit window has passed", async () => {
vi.useFakeTimers(); vi.useFakeTimers();
await vi.advanceTimersByTimeAsync(1000); await vi.advanceTimersByTimeAsync(1000);
const response = await rateLimitAuth.api.verifyApiKey({ const response = await rateLimitAuth.api.verifyApiKey({
@@ -754,7 +754,7 @@ describe("api-key", async () => {
expect(response?.valid).toBe(true); expect(response?.valid).toBe(true);
}); });
it("should check if verifying an api key's remaining count does go down", async () => { it("should check if verifying an API key's remaining count does go down", async () => {
const remaining = 10; const remaining = 10;
const { data: apiKey } = await client.apiKey.create( const { data: apiKey } = await client.apiKey.create(
{ {
@@ -781,7 +781,7 @@ describe("api-key", async () => {
expect(afterVerificationTwice?.key?.remaining).toEqual(remaining - 2); expect(afterVerificationTwice?.key?.remaining).toEqual(remaining - 2);
}); });
it("should fail if the api key has no remaining", async () => { it("should fail if the API key has no remaining", async () => {
const apiKey = await auth.api.createApiKey({ const apiKey = await auth.api.createApiKey({
body: { body: {
remaining: 1, remaining: 1,
@@ -805,7 +805,7 @@ describe("api-key", async () => {
expect(afterVerification.error?.code).toBe("USAGE_EXCEEDED"); expect(afterVerification.error?.code).toBe("USAGE_EXCEEDED");
}); });
it("should fail if the api key is expired", async () => { it("should fail if the API key is expired", async () => {
vi.useRealTimers(); vi.useRealTimers();
const { headers } = await signInWithTestUser(); const { headers } = await signInWithTestUser();
const apiKey2 = await client.apiKey.create( const apiKey2 = await client.apiKey.create(
@@ -830,7 +830,7 @@ describe("api-key", async () => {
// UPDATE API KEY // UPDATE API KEY
// ========================================================================= // =========================================================================
it("should fail to update api key name without headers or userId", async () => { it("should fail to update API key name without headers or userId", async () => {
let error: APIError | null = null; let error: APIError | null = null;
await auth.api await auth.api
.updateApiKey({ .updateApiKey({
@@ -846,7 +846,7 @@ describe("api-key", async () => {
expect(error).toBeInstanceOf(APIError); expect(error).toBeInstanceOf(APIError);
}); });
it("should update api key name with headers", async () => { it("should update API key name with headers", async () => {
const newName = "Hello World"; const newName = "Hello World";
const apiKey = await auth.api.updateApiKey({ const apiKey = await auth.api.updateApiKey({
body: { body: {
@@ -860,7 +860,7 @@ describe("api-key", async () => {
expect(apiKey.name).toEqual(newName); expect(apiKey.name).toEqual(newName);
}); });
it("should fail to update api key name with a length larger than the allowed maximum", async () => { it("should fail to update API key name with a length larger than the allowed maximum", async () => {
let error: APIError | null = null; let error: APIError | null = null;
await auth.api await auth.api
.updateApiKey({ .updateApiKey({
@@ -880,7 +880,7 @@ describe("api-key", async () => {
expect(error).not.toBeNull(); expect(error).not.toBeNull();
}); });
it("should fail to update api key name with a length smaller than the allowed minimum", async () => { it("should fail to update API key name with a length smaller than the allowed minimum", async () => {
let error: APIError | null = null; let error: APIError | null = null;
await auth.api await auth.api
.updateApiKey({ .updateApiKey({
@@ -900,7 +900,7 @@ describe("api-key", async () => {
expect(error).not.toBeNull(); expect(error).not.toBeNull();
}); });
it("should fail to update api key with no values to update", async () => { it("should fail to update API key with no values to update", async () => {
let error: APIError | null = null; let error: APIError | null = null;
await auth.api await auth.api
.updateApiKey({ .updateApiKey({
@@ -919,7 +919,7 @@ describe("api-key", async () => {
expect(error).not.toBeNull(); expect(error).not.toBeNull();
}); });
it("should update api key expiresIn value", async () => { it("should update API key expiresIn value", async () => {
const expiresIn = 60 * 60 * 24 * 7; // 7 days const expiresIn = 60 * 60 * 24 * 7; // 7 days
const expectedResult = new Date().getTime() + expiresIn; const expectedResult = new Date().getTime() + expiresIn;
const apiKey = await auth.api.updateApiKey({ const apiKey = await auth.api.updateApiKey({
@@ -1156,7 +1156,7 @@ describe("api-key", async () => {
expect(apiKey.refillAmount).toEqual(refillAmount); expect(apiKey.refillAmount).toEqual(refillAmount);
}); });
it("should update api key enable value", async () => { it("should update API key enable value", async () => {
const newValue = false; const newValue = false;
const apiKey = await auth.api.updateApiKey({ const apiKey = await auth.api.updateApiKey({
body: { body: {
@@ -1211,7 +1211,7 @@ describe("api-key", async () => {
expect(apiKey.metadata).toEqual(metadata); expect(apiKey.metadata).toEqual(metadata);
}); });
it("update api key's returned metadata should be an object", async () => { it("update API key's returned metadata should be an object", async () => {
const metadata = { const metadata = {
test: "test-12345", test: "test-12345",
}; };
@@ -1334,7 +1334,7 @@ describe("api-key", async () => {
expect(session?.session).toBeDefined(); expect(session?.session).toBeDefined();
}); });
it("should get session from an API key with custom api key getter", async () => { it("should get session from an API key with custom API key getter", async () => {
const { client, auth, signInWithTestUser } = await getTestInstance( const { client, auth, signInWithTestUser } = await getTestInstance(
{ {
plugins: [ plugins: [
@@ -1367,7 +1367,7 @@ describe("api-key", async () => {
expect(session?.session).toBeDefined(); expect(session?.session).toBeDefined();
}); });
it("should fail to get session from an API key with invalid api key", async () => { it("should fail to get session from an API key with invalid API key", async () => {
const headers = new Headers(); const headers = new Headers();
headers.set("x-api-key", "invalid"); headers.set("x-api-key", "invalid");

View File

@@ -85,7 +85,7 @@ export function verifyApiKey({
], ],
}); });
// No api key found // No API key found
if (!apiKey) { if (!apiKey) {
return ctx.json({ return ctx.json({
valid: false, valid: false,

View File

@@ -3,16 +3,16 @@ import type { Statements } from "../access";
import type { apiKeySchema } from "./schema"; import type { apiKeySchema } from "./schema";
export interface ApiKeyOptions { export interface ApiKeyOptions {
/** /**
* The header name to check for api key * The header name to check for API key
* @default "x-api-key" * @default "x-api-key"
*/ */
apiKeyHeaders?: string | string[]; apiKeyHeaders?: string | string[];
/** /**
* The function to get the api key from the context * The function to get the API key from the context
*/ */
customAPIKeyGetter?: (ctx: GenericEndpointContext) => string | null; customAPIKeyGetter?: (ctx: GenericEndpointContext) => string | null;
/** /**
* A custom function to validate the api key * A custom function to validate the API key
*/ */
customAPIKeyValidator?: (options: { customAPIKeyValidator?: (options: {
ctx: GenericEndpointContext; ctx: GenericEndpointContext;
@@ -154,7 +154,7 @@ export interface ApiKeyOptions {
maxRequests?: number; maxRequests?: number;
}; };
/** /**
* custom schema for the api key plugin * custom schema for the API key plugin
*/ */
schema?: InferOptionSchema<ReturnType<typeof apiKeySchema>>; schema?: InferOptionSchema<ReturnType<typeof apiKeySchema>>;
/** /**
@@ -242,7 +242,7 @@ export type ApiKey = {
*/ */
requestCount: number; requestCount: number;
/** /**
* Remaining requests (every time api key is used this should updated and should be updated on refill as well) * Remaining requests (every time API key is used this should updated and should be updated on refill as well)
*/ */
remaining: number | null; remaining: number | null;
/** /**
@@ -266,7 +266,7 @@ export type ApiKey = {
*/ */
metadata: Record<string, any> | null; metadata: Record<string, any> | null;
/** /**
* Permissions for the api key * Permissions for the API key
*/ */
permissions?: { permissions?: {
[key: string]: string[]; [key: string]: string[];

View File

@@ -101,7 +101,7 @@ describe("magic link", async () => {
); );
}); });
it("should signup with magic link", async () => { it("should sign up with magic link", async () => {
const email = "new-email@email.com"; const email = "new-email@email.com";
await client.signIn.magicLink({ await client.signIn.magicLink({
email, email,

View File

@@ -7,7 +7,7 @@ describe("open-api", async (it) => {
plugins: [openAPI()], plugins: [openAPI()],
}); });
it("should generate open api schema", async () => { it("should generate OpenAPI schema", async () => {
const schema = await auth.api.generateOpenAPISchema(); const schema = await auth.api.generateOpenAPISchema();
expect(schema).toBeDefined(); expect(schema).toBeDefined();
}); });

View File

@@ -661,7 +661,7 @@ describe("organization", async (it) => {
name: "name", name: "name",
}; };
// test api method // test API method
const newUser = await auth.api.signUpEmail({ const newUser = await auth.api.signUpEmail({
body: { body: {
email: userOverLimit.email, email: userOverLimit.email,

View File

@@ -55,7 +55,7 @@ export interface PasskeyOptions {
rpName?: string; rpName?: string;
/** /**
* The URL at which registrations and authentications should occur. * The URL at which registrations and authentications should occur.
* 'http://localhost' and 'http://localhost:PORT' are also valid. * `http://localhost` and `http://localhost:PORT` are also valid.
* Do NOT include any trailing / * Do NOT include any trailing /
* *
* if this isn't provided. The client itself will * if this isn't provided. The client itself will

View File

@@ -140,7 +140,7 @@ describe("SSO", async () => {
} }
}); });
it("should signin with SSO provider with email matching", async () => { it("should sign in with SSO provider with email matching", async () => {
const res = await auth.api.signInSSO({ const res = await auth.api.signInSSO({
body: { body: {
email: "my-email@localhost.com", email: "my-email@localhost.com",
@@ -156,7 +156,7 @@ describe("SSO", async () => {
expect(callbackURL).toContain("/dashboard"); expect(callbackURL).toContain("/dashboard");
}); });
it("should signin with SSO provider with domain", async () => { it("should sign in with SSO provider with domain", async () => {
const res = await auth.api.signInSSO({ const res = await auth.api.signInSSO({
body: { body: {
email: "my-email@test.com", email: "my-email@test.com",
@@ -173,7 +173,7 @@ describe("SSO", async () => {
expect(callbackURL).toContain("/dashboard"); expect(callbackURL).toContain("/dashboard");
}); });
it("should signin with SSO provider with providerId", async () => { it("should sign in with SSO provider with providerId", async () => {
const res = await auth.api.signInSSO({ const res = await auth.api.signInSSO({
body: { body: {
providerId: "test", providerId: "test",
@@ -463,7 +463,7 @@ describe("provisioning", async (ctx) => {
}); });
}); });
it("should signin with SSO provide with org slug", async () => { it("should sign in with SSO provide with org slug", async () => {
const res = await auth.api.signInSSO({ const res = await auth.api.signInSSO({
body: { body: {
organizationSlug: "localhost", organizationSlug: "localhost",

View File

@@ -424,7 +424,7 @@ describe("two factor", async () => {
}); });
}); });
describe("two factor auth api", async () => { describe("two factor auth API", async () => {
let OTP = ""; let OTP = "";
const sendOTP = vi.fn(); const sendOTP = vi.fn();
const { auth, signInWithTestUser, testUser } = await getTestInstance({ const { auth, signInWithTestUser, testUser } = await getTestInstance({

View File

@@ -19,7 +19,7 @@ describe("username", async (it) => {
}, },
); );
it("should signup with username", async () => { it("should sign up with username", async () => {
const headers = new Headers(); const headers = new Headers();
await client.signUp.email( await client.signUp.email(
{ {

View File

@@ -13,9 +13,9 @@ export interface RobloxProfile extends Record<string, any> {
name: string; name: string;
/** the account creation date as a unix timestamp in seconds */ /** the account creation date as a unix timestamp in seconds */
created_at: number; created_at: number;
/** the user's profile url */ /** the user's profile URL */
profile: string; profile: string;
/** the user's avatar url */ /** the user's avatar URL */
picture: string; picture: string;
} }

View File

@@ -215,7 +215,7 @@ describe("Social Providers", async (c) => {
}); });
}); });
it("should use callback url if the user is already registered", async () => { it("Should use callback URL if the user is already registered", async () => {
const signInRes = await client.signIn.social({ const signInRes = await client.signIn.social({
provider: "google", provider: "google",
callbackURL: "/callback", callbackURL: "/callback",

View File

@@ -29,7 +29,7 @@ export type BetterAuthOptions = {
*/ */
appName?: string; appName?: string;
/** /**
* Base URL for the better auth. This is typically the * Base URL for the Better Auth. This is typically the
* root URL where your application server is hosted. * root URL where your application server is hosted.
* If not explicitly set, * If not explicitly set,
* the system will check the following environment variable: * the system will check the following environment variable:
@@ -40,9 +40,9 @@ export type BetterAuthOptions = {
*/ */
baseURL?: string; baseURL?: string;
/** /**
* Base path for the better auth. This is typically * Base path for the Better Auth. This is typically
* the path where the * the path where the
* better auth routes are mounted. * Better Auth routes are mounted.
* *
* @default "/api/auth" * @default "/api/auth"
*/ */
@@ -51,7 +51,7 @@ export type BetterAuthOptions = {
* The secret to use for encryption, * The secret to use for encryption,
* signing and hashing. * signing and hashing.
* *
* By default better auth will look for * By default Better Auth will look for
* the following environment variables: * the following environment variables:
* process.env.BETTER_AUTH_SECRET, * process.env.BETTER_AUTH_SECRET,
* process.env.AUTH_SECRET * process.env.AUTH_SECRET
@@ -125,7 +125,7 @@ export type BetterAuthOptions = {
/** /**
* @param user the user to send the * @param user the user to send the
* verification email to * verification email to
* @param url the url to send the verification email to * @param url the URL to send the verification email to
* it contains the token as well * it contains the token as well
* @param token the token to send the verification email to * @param token the token to send the verification email to
*/ */
@@ -207,7 +207,7 @@ export type BetterAuthOptions = {
/** /**
* @param user the user to send the * @param user the user to send the
* reset password email to * reset password email to
* @param url the url to send the reset password email to * @param url the URL to send the reset password email to
* @param token the token to send to the user (could be used instead of sending the url * @param token the token to send to the user (could be used instead of sending the url
* if you need to redirect the user to custom route) * if you need to redirect the user to custom route)
*/ */
@@ -938,9 +938,9 @@ export type BetterAuthOptions = {
*/ */
onError?: (error: unknown, ctx: AuthContext) => void | Promise<void>; onError?: (error: unknown, ctx: AuthContext) => void | Promise<void>;
/** /**
* The url to redirect to on error * The URL to redirect to on error
* *
* When errorURL is provided, the error will be added to the url as a query parameter * When errorURL is provided, the error will be added to the URL as a query parameter
* and the user will be redirected to the errorURL. * and the user will be redirected to the errorURL.
* *
* @default - "/api/auth/error" * @default - "/api/auth/error"

View File

@@ -28,7 +28,7 @@ import { generateAuthConfig } from "../generators/auth-config";
import { getTsconfigInfo } from "../utils/get-tsconfig-info"; import { getTsconfigInfo } from "../utils/get-tsconfig-info";
/** /**
* Should only use any database that is core DBs, and supports the BetterAuth CLI generate functionality. * Should only use any database that is core DBs, and supports the Better Auth CLI generate functionality.
*/ */
const supportedDatabases = [ const supportedDatabases = [
// Built-in kysely // Built-in kysely
@@ -549,7 +549,7 @@ export async function initAction(opts: any) {
} }
} }
} else { } else {
s.stop(`Better Auth dependencies are ${chalk.greenBright(`up-to-date`)}!`); s.stop(`Better Auth dependencies are ${chalk.greenBright(`up to date`)}!`);
} }
// ===== appName ===== // ===== appName =====

View File

@@ -3,7 +3,7 @@ import type { BetterAuthOptions } from "better-auth";
import { logger } from "better-auth"; import { logger } from "better-auth";
import path from "path"; import path from "path";
// @ts-ignore // @ts-ignore
import babelPresetTypescript from "@babel/preset-typescript"; import babelPresetTypeScript from "@babel/preset-typescript";
// @ts-ignore // @ts-ignore
import babelPresetReact from "@babel/preset-react"; import babelPresetReact from "@babel/preset-react";
import fs, { existsSync } from "fs"; import fs, { existsSync } from "fs";
@@ -72,7 +72,7 @@ const jitiOptions = (cwd: string) => {
babel: { babel: {
presets: [ presets: [
[ [
babelPresetTypescript, babelPresetTypeScript,
{ {
isTSX: true, isTSX: true,
allExtensions: true, allExtensions: true,

View File

@@ -3,7 +3,7 @@ import { createAuthMiddleware } from "better-auth/api";
export interface ExpoOptions { export interface ExpoOptions {
/** /**
* Override origin header for expo api routes * Override origin header for expo API routes
*/ */
overrideOrigin?: boolean; overrideOrigin?: boolean;
} }

View File

@@ -145,12 +145,12 @@ export const stripe = <O extends StripeOptions>(options: O) => {
}) })
.optional(), .optional(),
/** /**
* Success url to redirect back after successful subscription * Success URL to redirect back after successful subscription
*/ */
successUrl: z successUrl: z
.string({ .string({
description: description:
"callback url to redirect back after successful subscription", "Callback URL to redirect back after successful subscription",
}) })
.default("/"), .default("/"),
/** /**
@@ -159,7 +159,7 @@ export const stripe = <O extends StripeOptions>(options: O) => {
cancelUrl: z cancelUrl: z
.string({ .string({
description: description:
"callback url to redirect back after successful subscription", "Callback URL to redirect back after successful subscription",
}) })
.default("/"), .default("/"),
/** /**