From 300b390b8285462716e743d4389f225db9151845 Mon Sep 17 00:00:00 2001
From: Micha Mailaender <87228994+mmailaender@users.noreply.github.com>
Date: Mon, 12 Oct 2026 09:00:37 +0200
Subject: [PATCH 1/5] docs(sveltekit): update guide for SvelteKit 3 and
convex-better-auth-svelte 0.10
- Target SvelteKit 3: src/env.ts, $app/env/public, #lib/#convex subpath
imports, config in vite.config.ts.
- Register the Convex URL once with initConvex() in src/hooks.ts; the
.convex.site URL is derived on Convex Cloud.
- Use convex-svelte instead of the legacy @mmailaender/convex-svelte fork.
- Add the convexLoad transport setup and a cookiePrefix note for getToken.
- Add a SvelteKit 2 section with the differences.
---
.../docs/framework-guides/sveltekit.mdx | 184 +++++++++++++-----
1 file changed, 136 insertions(+), 48 deletions(-)
diff --git a/docs/content/docs/framework-guides/sveltekit.mdx b/docs/content/docs/framework-guides/sveltekit.mdx
index 2702fec0..fdfd13c4 100644
--- a/docs/content/docs/framework-guides/sveltekit.mdx
+++ b/docs/content/docs/framework-guides/sveltekit.mdx
@@ -10,6 +10,9 @@ description: Install and configure Convex + Better Auth for SvelteKit.
can be reported there as well.
+This guide targets SvelteKit 3. Still on SvelteKit 2? Follow along and apply the
+differences listed in [SvelteKit 2](#sveltekit-2).
+
## Prerequisites
You'll first need a project where Convex is already set-up. Ensure that all
@@ -22,7 +25,7 @@ steps in prerequisites are completed.
### Install convex
```npm
-npm install convex @mmailaender/convex-svelte
+npm install convex convex-svelte
```
@@ -54,32 +57,18 @@ npm install convex @mmailaender/convex-svelte
- ### Add $convex alias
-
- Add the following to your `svelte.config.js` file:
-
- ```ts title="svelte.config.js"
- import adapter from '@sveltejs/adapter-auto';
- import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
-
- /** @type {import('@sveltejs/kit').Config} */
- const config = {
- // Consult https://svelte.dev/docs/kit/integrations
- // for more information about preprocessors
- preprocess: vitePreprocess(),
-
- kit: {
- // adapter-auto only supports some environments, see https://svelte.dev/docs/kit/adapter-auto for a list.
- // If your environment is not supported, or you settled on a specific environment, switch out the adapter.
- // See https://svelte.dev/docs/kit/adapters for more information about adapters.
- adapter: adapter(),
- alias: {
- $convex: './src/convex'
- }
- }
- };
+ ### Add a `#convex` import alias
- export default config;
+ Add a [subpath import](https://svelte.dev/docs/kit/$lib) to your `package.json`, so you can import from `src/convex/` as `#convex/...`:
+
+ ```json title="package.json"
+ {
+ "imports": {
+ "#lib": "./src/lib/index.js",
+ "#lib/*": "./src/lib/*",
+ "#convex/*": "./src/convex/*" // [!code ++]
+ }
+ }
```
@@ -160,9 +149,6 @@ npm install convex @mmailaender/convex-svelte
PUBLIC_CONVEX_URL=https://adjective-animal-123.convex.cloud
- # Same as PUBLIC_CONVEX_URL but ends in .site // [!code ++]
- PUBLIC_CONVEX_SITE_URL=https://adjective-animal-123.convex.site # [!code ++]
-
# Your local site URL // [!code ++]
PUBLIC_SITE_URL=http://localhost:5173 # [!code ++]
```
@@ -181,6 +167,31 @@ npm install convex @mmailaender/convex-svelte
PUBLIC_SITE_URL=http://localhost:5173 # [!code ++]
```
+ On Convex Cloud, the Convex site URL (`.convex.site`) is derived from `PUBLIC_CONVEX_URL`.
+ Self-hosted, local, and custom-domain deployments need `PUBLIC_CONVEX_SITE_URL`.
+
+ Declare the variables in `src/env.ts`. SvelteKit 3 only exposes declared variables.
+
+ ```ts title="src/env.ts" tab="Cloud"
+ import { defineEnvVars } from '@sveltejs/kit/env';
+
+ export const variables = defineEnvVars({
+ PUBLIC_CONVEX_URL: { public: true, static: true }
+ });
+ ```
+
+ ```ts title="src/env.ts" tab="Self hosted"
+ import { defineEnvVars } from '@sveltejs/kit/env';
+
+ export const variables = defineEnvVars({
+ PUBLIC_CONVEX_URL: { public: true, static: true },
+ PUBLIC_CONVEX_SITE_URL: { public: true, static: true }
+ });
+ ```
+
+ `static: true` inlines the values at build time. Keep it if the values only
+ exist while building, for example with `npx convex deploy --cmd 'npm run build'`.
+
@@ -267,26 +278,48 @@ npm install convex @mmailaender/convex-svelte
Set up route handlers to proxy auth requests from your framework server to your Convex deployment.
- ```ts title="src/routes/api/auth/[...all]/+server.ts"
+ ```ts title="src/routes/api/auth/[...all]/+server.ts" tab="Cloud"
import { createSvelteKitHandler } from '@mmailaender/convex-better-auth-svelte/sveltekit';
export const { GET, POST } = createSvelteKitHandler();
```
+ ```ts title="src/routes/api/auth/[...all]/+server.ts" tab="Self hosted"
+ import { createSvelteKitHandler } from '@mmailaender/convex-better-auth-svelte/sveltekit';
+ import { PUBLIC_CONVEX_SITE_URL } from '$app/env/public';
+
+ export const { GET, POST } = createSvelteKitHandler({ convexSiteUrl: PUBLIC_CONVEX_SITE_URL });
+ ```
+
+
+
+
+ ### Initialize the Convex client
+
+ Register your deployment URL once in the universal hooks file, which runs on the server and in the browser.
+ `createSvelteAuthClient`, `createConvexHttpClient`, and `createSvelteKitHandler` all read it from there.
+
+ ```ts title="src/hooks.ts"
+ import { initConvex } from 'convex-svelte/sveltekit';
+ import { PUBLIC_CONVEX_URL } from '$app/env/public';
+
+ initConvex(PUBLIC_CONVEX_URL);
+ ```
+
### Set up Convex client provider
Initialize the Convex client with auth in your app.
- Note: `createSvelteAuthClient` includes already `setupConvex()` from `@mmailaender/convex-svelte`.
+ Note: `createSvelteAuthClient` already calls `setupConvex()` from `convex-svelte`, reusing the client from `initConvex()`.
```ts title="src/routes/+layout.svelte"
+
+ {#if auth.isAuthenticated}
+ {@render children()}
+ {:else if auth.isLoading}
+
Loading…
+ {:else}
+
Please sign in.
+ {/if}
+ ```
+
+3. **Pass the server's auth state** (see [SSR](#ssr-optional)). Signed-in
+ users then render the area on the first paint, and their first queries are
+ already authenticated.
-Use this when your app is essentially “members-only” and almost all data
-requires authentication.
-
-By enabling `expectAuth`, all Convex queries and mutations created through
-`createSvelteAuthClient` will:
-
-- automatically include the auth token, and
-- not run until the user is authenticated.
-
-Unauthenticated users won’t trigger any Convex requests until they sign in.
-
-```ts title="src/routes/+layout.svelte"
-import { createSvelteAuthClient } from "@mmailaender/convex-better-auth-svelte/svelte";
-import { authClient } from "#lib/auth-client.js";
+
+ These steps shape what users see. They don't protect your data: every Convex
+ function that returns private data must check the user itself, e.g. with
+ `authComponent.getAuthUser(ctx)`.
+
-createSvelteAuthClient({
- authClient,
- options: {
- expectAuth: true,
- },
-});
-```
+
+ Other guides use Convex's `expectAuth` client option for this. It only holds
+ requests until the first sign-in, and leaves signed-out users with a client
+ that never sends anything, so this guide doesn't use it.
+
### SSR (Optional)
From 9ca52b366ac2ada0b894c5dda5688faf8e7e4350 Mon Sep 17 00:00:00 2001
From: Micha Mailaender <87228994+mmailaender@users.noreply.github.com>
Date: Tue, 13 Oct 2026 07:57:59 +0200
Subject: [PATCH 3/5] docs(sveltekit): load auth data with convexLoad in
+page.server.ts
A universal +page.ts load runs again in the browser during hydration,
before auth is set up, so auth-dependent queries briefly return their
signed-out result. convex-svelte's convexLoadHydration handle avoids that
on SvelteKit 2.56+, but doesn't support SvelteKit 3 yet. Show the
getCurrentUser example as a server load, and mention the handle in the
SvelteKit 2 section.
---
docs/content/docs/framework-guides/sveltekit.mdx | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/docs/content/docs/framework-guides/sveltekit.mdx b/docs/content/docs/framework-guides/sveltekit.mdx
index b8e6d842..2f832a5c 100644
--- a/docs/content/docs/framework-guides/sveltekit.mdx
+++ b/docs/content/docs/framework-guides/sveltekit.mdx
@@ -590,7 +590,7 @@ export const load: PageServerLoad = async () => {
};
```
-You can also use `convexLoad` for SSR with automatic live subscription upgrade — this works in both `+page.ts` and `+page.server.ts`.
+You can also use `convexLoad` for SSR with automatic live subscription upgrade.
It needs the `ConvexLoadResult` transport in your universal hooks:
```ts title="src/hooks.ts"
@@ -604,7 +604,7 @@ export const transport = { // [!code ++]
}; // [!code ++]
```
-```ts title="src/routes/+page.ts"
+```ts title="src/routes/+page.server.ts"
import { convexLoad } from "convex-svelte/sveltekit";
import { api } from "#convex/_generated/api.js";
@@ -613,6 +613,12 @@ export const load = async () => ({
});
```
+Load data that needs auth in `+page.server.ts`, as above: its result reaches the
+browser through the transport, and the live subscription starts once the user
+is authenticated. A universal `+page.ts` load runs again in the browser during
+hydration, before auth is set up, so an auth-dependent query briefly returns its
+signed-out result there. Use `+page.ts` for public data.
+
### Authenticated requests
There are two common ways to make authenticated Convex requests from Svelte
@@ -849,6 +855,11 @@ guide above with these differences:
export default config;
```
+- **`convexLoad` in `+page.ts`:** on SvelteKit 2.56 or later, convex-svelte's
+ [`convexLoadHydration`](https://docs.convex.dev/client/svelte/sveltekit-server-rendering#convexloadhydration)
+ handle lets universal loads reuse the server's result during hydration, so
+ they work for auth-dependent data too. It doesn't support SvelteKit 3 yet.
+
To upgrade an existing app to SvelteKit 3, run `npx sv migrate sveltekit-3`, then
declare your Convex variables in `src/env.ts` as shown in
[Set environment variables](#set-environment-variables).
From 9075cccaaf94f874813eecd45ed74424639a0633 Mon Sep 17 00:00:00 2001
From: Micha Mailaender <87228994+mmailaender@users.noreply.github.com>
Date: Tue, 13 Oct 2026 12:22:05 +0200
Subject: [PATCH 4/5] docs(sveltekit): convexLoadHydration works on SvelteKit 2
and 3 with fetch
---
docs/content/docs/framework-guides/sveltekit.mdx | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/docs/content/docs/framework-guides/sveltekit.mdx b/docs/content/docs/framework-guides/sveltekit.mdx
index 2f832a5c..069dfd94 100644
--- a/docs/content/docs/framework-guides/sveltekit.mdx
+++ b/docs/content/docs/framework-guides/sveltekit.mdx
@@ -617,7 +617,11 @@ Load data that needs auth in `+page.server.ts`, as above: its result reaches the
browser through the transport, and the live subscription starts once the user
is authenticated. A universal `+page.ts` load runs again in the browser during
hydration, before auth is set up, so an auth-dependent query briefly returns its
-signed-out result there. Use `+page.ts` for public data.
+signed-out result there. To use `+page.ts` anyway, pass the load's `fetch` to
+`convexLoad()` and add convex-svelte's
+[`convexLoadHydration`](https://docs.convex.dev/client/svelte/sveltekit-server-rendering#convexloadhydration)
+handle after your auth handle: the load then reuses the server's result during
+hydration.
### Authenticated requests
@@ -855,11 +859,6 @@ guide above with these differences:
export default config;
```
-- **`convexLoad` in `+page.ts`:** on SvelteKit 2.56 or later, convex-svelte's
- [`convexLoadHydration`](https://docs.convex.dev/client/svelte/sveltekit-server-rendering#convexloadhydration)
- handle lets universal loads reuse the server's result during hydration, so
- they work for auth-dependent data too. It doesn't support SvelteKit 3 yet.
-
To upgrade an existing app to SvelteKit 3, run `npx sv migrate sveltekit-3`, then
declare your Convex variables in `src/env.ts` as shown in
[Set environment variables](#set-environment-variables).
From 03ec884b1b8aa090d3212f310e03404fb937e392 Mon Sep 17 00:00:00 2001
From: Micha Mailaender <87228994+mmailaender@users.noreply.github.com>
Date: Thu, 15 Oct 2026 12:29:30 +0200
Subject: [PATCH 5/5] docs(sveltekit): Handle from @sveltejs/kit/hooks on
SvelteKit 3, link convexLoadHydration setup
---
docs/content/docs/framework-guides/sveltekit.mdx | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/docs/content/docs/framework-guides/sveltekit.mdx b/docs/content/docs/framework-guides/sveltekit.mdx
index 069dfd94..2470fe2f 100644
--- a/docs/content/docs/framework-guides/sveltekit.mdx
+++ b/docs/content/docs/framework-guides/sveltekit.mdx
@@ -343,7 +343,7 @@ npm install convex convex-svelte
Set up a SvelteKit hook to automatically extract the auth token on every request. `withServerConvexToken` stores the token per-request via `AsyncLocalStorage`, so `convexLoad` and `createConvexHttpClient` automatically pick it up during SSR — no need to pass `{ token }` in every load function.
```ts title="src/hooks.server.ts"
- import type { Handle } from "@sveltejs/kit";
+ import type { Handle } from "@sveltejs/kit/hooks";
import { getToken } from '@mmailaender/convex-better-auth-svelte/sveltekit';
import { withServerConvexToken } from 'convex-svelte/sveltekit/server'; // [!code ++]
@@ -619,7 +619,7 @@ is authenticated. A universal `+page.ts` load runs again in the browser during
hydration, before auth is set up, so an auth-dependent query briefly returns its
signed-out result there. To use `+page.ts` anyway, pass the load's `fetch` to
`convexLoad()` and add convex-svelte's
-[`convexLoadHydration`](https://docs.convex.dev/client/svelte/sveltekit-server-rendering#convexloadhydration)
+[`convexLoadHydration`](https://docs.convex.dev/client/svelte/sveltekit-server-rendering#server-hooks)
handle after your auth handle: the load then reuses the server's result during
hydration.
@@ -662,7 +662,8 @@ of gating every query, gate the area once:
[implications for authentication](https://svelte.dev/docs/kit/load#Implications-for-authentication)).
```ts title="src/hooks.server.ts"
- import { redirect, type Handle } from "@sveltejs/kit"; // [!code ++]
+ import { redirect } from "@sveltejs/kit"; // [!code ++]
+ import type { Handle } from "@sveltejs/kit/hooks";
import { getToken } from "@mmailaender/convex-better-auth-svelte/sveltekit";
import { withServerConvexToken } from "convex-svelte/sveltekit/server";
@@ -838,6 +839,9 @@ guide above with these differences:
initConvex(PUBLIC_CONVEX_URL);
```
+- **`Handle` type:** import it from `@sveltejs/kit` instead of
+ `@sveltejs/kit/hooks`.
+
- **Import aliases:** instead of the `#convex` subpath import, add a `$convex`
alias to `svelte.config.js`, and import with `$convex/...` and `$lib/...`: