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/...`: