Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/sveltekit-pages/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DATABASE_URL=file:.wrangler/state/v3/d1/miniflare-D1DatabaseObject/your-d1.sqlite
28 changes: 28 additions & 0 deletions examples/sveltekit-pages/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
node_modules

# Output
.output
.vercel
.netlify
.wrangler
/.svelte-kit
/build

# OS
.DS_Store
Thumbs.db

# Env
.env
.env.*
!.env.example
!.env.test

# Vite
vite.config.js.timestamp-*
vite.config.ts.timestamp-*

# SQLite
*.db

.dev.vars*
1 change: 1 addition & 0 deletions examples/sveltekit-pages/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
engine-strict=true
6 changes: 6 additions & 0 deletions examples/sveltekit-pages/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Package Managers
package-lock.json
pnpm-lock.yaml
yarn.lock
bun.lock
bun.lockb
15 changes: 15 additions & 0 deletions examples/sveltekit-pages/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"useTabs": true,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100,
"plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
"overrides": [
{
"files": "*.svelte",
"options": {
"parser": "svelte"
}
}
]
}
5 changes: 5 additions & 0 deletions examples/sveltekit-pages/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"files.associations": {
"wrangler.json": "jsonc"
}
}
106 changes: 106 additions & 0 deletions examples/sveltekit-pages/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Better Auth Cloudflare SvelteKit Example (deploy on Cloudflare Pages)

This example demonstrates how to integrate [Better Auth](https://github.com/better-auth/better-auth) with [SvelteKit](https://svelte.dev/docs/kit/) on Cloudflare Pages using the `better-auth-cloudflare` plugin.

## Features

- **User Authentication**: Secure sign-in options including email/password and passwordless logins.
- **Session Management**: Leverages Cloudflare KV for efficient session storage.
- **File Management**: Upload, download, and manage files securely using Cloudflare R2.
- **Data Persistence**: Utilizes Cloudflare D1 for database storage.
- **Geolocation**: Fetches and displays user's location data via Cloudflare headers.
- **Protected Routes**: Example of a dashboard page accessible only to authenticated users.

## Getting Started

### Prerequisites

- You will need a [Cloudflare account](https://dash.cloudflare.com/sign-up).
- You will need [Node.js](https://nodejs.org/en/) installed, preferably the latest LTS version.
- This project uses `pnpm` as a package manager, but you can use `npm` or `bun`.

### Installation

#### 1. Navigate to this directory

```shell
cd examples/sveltekit-pages && pnpm install
```

This directory initialized with `bun create cloudflare@latest sveltekit-pages --framework=svelte --platform=pages`. You can create with `npm` or `bun`

#### 2. Create Cloudflare Storages (D1, KV and R2)

To run the demo project, create a D1 Database and KV Storage in your Cloudflare account using the following CLI commands. (KV is optional and used for secondary session storage).

```shell
pnpm wrangler d1 create your-sveltekit-pages-d1
pnpm wrangler kv namespace create "SVELTEKIT_PAGES_AUTH_SESSION_KV"
pnpm wrangler kv namespace create "SVELTEKIT_PAGES_AUTH_SESSION_KV" --preview #This is for `wrangler pages dev`
pnpm wrangler r2 bucket create "your-sveltekit-pages-assets"
```

#### 3. Configure your Cloudflare bindings in `wrangler.jsonc`

Update the information in `wrangler.jsonc` based on the resources created in step 2.

```wrangler.jsonc
"d1_databases": [
{
"binding": "DB",
"database_name": "your-sveltekit-pages-d1",
"database_id": "your-sveltekit-pages-d1-id",
"migrations_dir": "drizzle"
}
],
"kv_namespaces": [
{
"binding": "SVELTEKIT_PAGES_AUTH_SESSION_KV",
"id": "your-sveltekit-pages-auth-session-kv-id",
"preview_id": "your-sveltekit-pages-auth-session-kv-preview-id"
}
],
"r2_buckets": [
{
"binding": "SVELTEKIT_PAGES_ASSETS",
"bucket_name": "your-sveltekit-pages-assets",
"preview_bucket_name": "your-sveltekit-pages-assets-preview"
}
]
```

If you used a different name when creating the resources with the Wrangler CLI, you must also change the name in the `binding:` section. Additionally, run `pnpm run cf-typegen` to update the `worker-configuration.d.ts` file.

In the D1 configuration, add `"migrations_dir": "drizzle"`. This is the migration path for the Drizzle ORM.

> Support for `wrangler.jsonc` requires wrangler version v3.91.0 or higher.[^1]

#### 4. Apply Database Migrations

After configuring your bindings, apply the database schema to your D1 database.

```shell
# For production environment
pnpm wrangler d1 migrations apply sveltekit-pages-d1

# For local development
pnpm wrangler d1 migrations apply sveltekit-pages-d1 --local
```

### Local Development

To start the local development server, run the following command:

```shell
pnpm run dev
```

This command starts the SvelteKit development server and uses `wrangler` to simulate the Cloudflare environment locally. This includes access to your local D1 database and KV namespaces.

### Deploy

```shell
pnpm run deploy
```

[^1]: [Configuration - Wrangler · Cloudflare Workers docs](https://developers.cloudflare.com/workers/wrangler/configuration/)
16 changes: 16 additions & 0 deletions examples/sveltekit-pages/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "https://shadcn-svelte.com/schema.json",
"tailwind": {
"css": "src/app.css",
"baseColor": "slate"
},
"aliases": {
"components": "$lib/components",
"utils": "$lib/utils",
"ui": "$lib/components/ui",
"hooks": "$lib/hooks",
"lib": "$lib"
},
"typescript": true,
"registry": "https://shadcn-svelte.com/registry"
}
11 changes: 11 additions & 0 deletions examples/sveltekit-pages/drizzle.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { defineConfig } from 'drizzle-kit';

if (!process.env.DATABASE_URL) throw new Error('DATABASE_URL is not set');

export default defineConfig({
schema: './src/lib/server/db/schema.ts',
dialect: 'sqlite',
dbCredentials: { url: process.env.DATABASE_URL },
verbose: true,
strict: true
});
73 changes: 73 additions & 0 deletions examples/sveltekit-pages/drizzle/0000_parched_glorian.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
CREATE TABLE `accounts` (
`id` text PRIMARY KEY NOT NULL,
`account_id` text NOT NULL,
`provider_id` text NOT NULL,
`user_id` text NOT NULL,
`access_token` text,
`refresh_token` text,
`id_token` text,
`access_token_expires_at` integer,
`refresh_token_expires_at` integer,
`scope` text,
`password` text,
`created_at` integer NOT NULL,
`updated_at` integer NOT NULL,
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE TABLE `sessions` (
`id` text PRIMARY KEY NOT NULL,
`expires_at` integer NOT NULL,
`token` text NOT NULL,
`created_at` integer NOT NULL,
`updated_at` integer NOT NULL,
`ip_address` text,
`user_agent` text,
`user_id` text NOT NULL,
`timezone` text,
`city` text,
`country` text,
`region` text,
`region_code` text,
`colo` text,
`latitude` text,
`longitude` text,
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE UNIQUE INDEX `sessions_token_unique` ON `sessions` (`token`);--> statement-breakpoint
CREATE TABLE `user_files` (
`id` text PRIMARY KEY NOT NULL,
`user_id` text NOT NULL,
`filename` text NOT NULL,
`original_name` text NOT NULL,
`content_type` text NOT NULL,
`size` integer NOT NULL,
`r2_key` text NOT NULL,
`uploaded_at` integer NOT NULL,
`category` text,
`is_public` integer,
`description` text,
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE TABLE `users` (
`id` text PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`email` text NOT NULL,
`email_verified` integer NOT NULL,
`image` text,
`created_at` integer NOT NULL,
`updated_at` integer NOT NULL,
`is_anonymous` integer
);
--> statement-breakpoint
CREATE UNIQUE INDEX `users_email_unique` ON `users` (`email`);--> statement-breakpoint
CREATE TABLE `verifications` (
`id` text PRIMARY KEY NOT NULL,
`identifier` text NOT NULL,
`value` text NOT NULL,
`expires_at` integer NOT NULL,
`created_at` integer,
`updated_at` integer
);
Loading