diff --git a/.gitignore b/.gitignore index 5cc0dd05ee..d7683a2b02 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,6 @@ node_modules/ .temp/ *.tgz .vscode/launch.json + +# environment variables +**.env diff --git a/package.json b/package.json index 04257119bd..270caadfb4 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "scripts": { "doc": "pnpm --filter @skeletonlabs/skeleton.dev", "themes": "pnpm --filter @skeletonlabs/themes.skeleton.dev", + "plus": "pnpm --filter @skeletonlabs/plus.skeleton.dev", "svelte": "pnpm --filter @skeletonlabs/playground-skeleton-svelte", "react": "pnpm --filter @skeletonlabs/playground-skeleton-react", "test": "vitest run", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5cbfa46b95..1ad683d3c2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -75,6 +75,12 @@ catalogs: '@stackblitz/sdk': specifier: 1.11.0 version: 1.11.0 + '@supabase/ssr': + specifier: 0.10.0 + version: 0.10.0 + '@supabase/supabase-js': + specifier: 2.101.1 + version: 2.101.1 '@sveltejs/adapter-auto': specifier: 7.0.1 version: 7.0.1 @@ -863,6 +869,54 @@ importers: specifier: 'catalog:' version: 0.3.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3)) + sites/plus.skeleton.dev: + devDependencies: + '@skeletonlabs/skeleton': + specifier: workspace:* + version: link:../../packages/skeleton + '@skeletonlabs/skeleton-svelte': + specifier: workspace:* + version: link:../../packages/skeleton-svelte + '@supabase/ssr': + specifier: 'catalog:' + version: 0.10.0(@supabase/supabase-js@2.101.1) + '@supabase/supabase-js': + specifier: 'catalog:' + version: 2.101.1 + '@sveltejs/adapter-auto': + specifier: ^7.0.0 + version: 7.0.1(@sveltejs/kit@2.55.0(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.1)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3)))(svelte@5.55.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3))) + '@sveltejs/kit': + specifier: ^2.50.2 + version: 2.55.0(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.1)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3)))(svelte@5.55.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3)) + '@sveltejs/vite-plugin-svelte': + specifier: ^6.2.4 + version: 6.2.4(svelte@5.55.1)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3)) + '@tailwindcss/forms': + specifier: ^0.5.11 + version: 0.5.11(tailwindcss@4.2.2) + '@tailwindcss/vite': + specifier: ^4.1.18 + version: 4.2.2(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3)) + svelte: + specifier: ^5.54.0 + version: 5.55.1 + svelte-check: + specifier: ^4.4.2 + version: 4.4.6(picomatch@4.0.4)(svelte@5.55.1)(typescript@5.9.3) + tailwindcss: + specifier: ^4.1.18 + version: 4.2.2 + typescript: + specifier: ^5.9.3 + version: 5.9.3 + vite: + specifier: ^7.3.1 + version: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3) + vite-plugin-transform-lucide-imports: + specifier: 'catalog:' + version: 0.3.0(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3)) + sites/skeleton.dev: dependencies: '@astrojs/check': @@ -2966,6 +3020,38 @@ packages: '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@supabase/auth-js@2.101.1': + resolution: {integrity: sha512-Kd0Wey+RkFHgyVep7adS6UOE2pN6MJ3mZ32PAXSvfw6IjUkFRC7IQpdZZjUOcUe5pXr1ejufCRgF6lsGINe4Tw==} + engines: {node: '>=20.0.0'} + + '@supabase/functions-js@2.101.1': + resolution: {integrity: sha512-OZWU7YtaG+NNNFZK8p/FuJ6gpq7pFyrG2fLOopP73HAIDHDGpOttPJapvO8ADu3RkqfQfkwrB354vPkSBbZ20A==} + engines: {node: '>=20.0.0'} + + '@supabase/phoenix@0.4.0': + resolution: {integrity: sha512-RHSx8bHS02xwfHdAbX5Lpbo6PXbgyf7lTaXTlwtFDPwOIw64NnVRwFAXGojHhjtVYI+PEPNSWwkL90f4agN3bw==} + + '@supabase/postgrest-js@2.101.1': + resolution: {integrity: sha512-UW1RajH5jbZoK+ldAJ1I6VZ+HWwZ2oaKjEQ6Gn+AQ67CHQVxGl8wNQoLYyumbyaExm41I+wn7arulcY1eHeZJw==} + engines: {node: '>=20.0.0'} + + '@supabase/realtime-js@2.101.1': + resolution: {integrity: sha512-Oa6dno0OB9I+hv5do5zsZHbFu41ViZnE9IWjmkeeF/8fPmB5fWoHGqeTYEC3/0DAgtpUoFJa4FpvzFH0SBHo1Q==} + engines: {node: '>=20.0.0'} + + '@supabase/ssr@0.10.0': + resolution: {integrity: sha512-36jIu+DuKzg5EgA3fnH+zHvwASvpKcL4zPgmHoZaULroS5Q4mzeHcM69zJ0sXUHddO5IcHjQNZJ9Vyhl/DdbRw==} + peerDependencies: + '@supabase/supabase-js': ^2.100.1 + + '@supabase/storage-js@2.101.1': + resolution: {integrity: sha512-WhTaUOBgeEvnKLy95Cdlp6+D5igSF/65yC727w1olxbet5nzUvMlajKUWyzNtQu2efrz2cQ7FcdVBdQqgT9YKQ==} + engines: {node: '>=20.0.0'} + + '@supabase/supabase-js@2.101.1': + resolution: {integrity: sha512-Jnhm3LfuACwjIzvk2pfUbGQn7pa7hi6MFzfSyPrRYWVCCu69RPLCFyHSBl7HSBwadbQ3UZOznnD3gPca3ePrRA==} + engines: {node: '>=20.0.0'} + '@sveltejs/acorn-typescript@1.0.9': resolution: {integrity: sha512-lVJX6qEgs/4DOcRTpo56tmKzVPtoWAaVbL4hfO7t7NVwl9AAXzQR6cihesW1BmNMPl+bK6dreu2sOKBP2Q9CIA==} peerDependencies: @@ -3376,6 +3462,9 @@ packages: '@types/unist@3.0.3': resolution: {integrity: sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==} + '@types/ws@8.18.1': + resolution: {integrity: sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==} + '@typescript-eslint/types@8.58.0': resolution: {integrity: sha512-O9CjxypDT89fbHxRfETNoAnHj/i6IpRK0CvbVN3qibxlLdo5p5hcLmUuCCrHMpxiWSwKyI8mCP7qRNYuOJ0Uww==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4445,6 +4534,10 @@ packages: resolution: {integrity: sha512-tsYlhAYpjCKa//8rXZ9DqKEawhPoSytweBC2eNvcaDK+57RZLHGqNs3PZTQO6yekLFSuvA6AlnAfrw1uBvtb+Q==} hasBin: true + iceberg-js@0.8.1: + resolution: {integrity: sha512-1dhVQZXhcHje7798IVM+xoo/1ZdVfzOMIc8/rgVSijRK38EDqOJoGula9N/8ZI5RD8QTxNQtK/Gozpr+qUqRRA==} + engines: {node: '>=20.0.0'} + iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} @@ -7996,6 +8089,51 @@ snapshots: '@standard-schema/spec@1.1.0': {} + '@supabase/auth-js@2.101.1': + dependencies: + tslib: 2.8.1 + + '@supabase/functions-js@2.101.1': + dependencies: + tslib: 2.8.1 + + '@supabase/phoenix@0.4.0': {} + + '@supabase/postgrest-js@2.101.1': + dependencies: + tslib: 2.8.1 + + '@supabase/realtime-js@2.101.1': + dependencies: + '@supabase/phoenix': 0.4.0 + '@types/ws': 8.18.1 + tslib: 2.8.1 + ws: 8.20.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@supabase/ssr@0.10.0(@supabase/supabase-js@2.101.1)': + dependencies: + '@supabase/supabase-js': 2.101.1 + cookie: 1.1.1 + + '@supabase/storage-js@2.101.1': + dependencies: + iceberg-js: 0.8.1 + tslib: 2.8.1 + + '@supabase/supabase-js@2.101.1': + dependencies: + '@supabase/auth-js': 2.101.1 + '@supabase/functions-js': 2.101.1 + '@supabase/postgrest-js': 2.101.1 + '@supabase/realtime-js': 2.101.1 + '@supabase/storage-js': 2.101.1 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + '@sveltejs/acorn-typescript@1.0.9(acorn@8.16.0)': dependencies: acorn: 8.16.0 @@ -8004,6 +8142,10 @@ snapshots: dependencies: '@sveltejs/kit': 2.55.0(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3)))(svelte@5.55.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3)) + '@sveltejs/adapter-auto@7.0.1(@sveltejs/kit@2.55.0(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.1)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3)))(svelte@5.55.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3)))': + dependencies: + '@sveltejs/kit': 2.55.0(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.55.1)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3)))(svelte@5.55.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3)) + '@sveltejs/adapter-vercel@6.3.3(@sveltejs/kit@2.55.0(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3)))(svelte@5.55.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3)))(rollup@4.60.1)': dependencies: '@sveltejs/kit': 2.55.0(@sveltejs/vite-plugin-svelte@5.1.1(svelte@5.55.1)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3)))(svelte@5.55.1)(typescript@5.9.3)(vite@7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3)) @@ -8053,7 +8195,6 @@ snapshots: vite: 7.3.1(@types/node@25.5.2)(jiti@2.6.1)(lightningcss@1.32.0)(sass-embedded@1.93.3)(sass@1.93.3)(tsx@4.21.0)(yaml@2.8.3) optionalDependencies: typescript: 5.9.3 - optional: true '@sveltejs/package@2.5.7(svelte@5.55.1)(typescript@5.9.3)': dependencies: @@ -8500,6 +8641,10 @@ snapshots: '@types/unist@3.0.3': {} + '@types/ws@8.18.1': + dependencies: + '@types/node': 25.5.2 + '@typescript-eslint/types@8.58.0': {} '@ungap/structured-clone@1.3.0': {} @@ -9972,6 +10117,8 @@ snapshots: human-id@4.1.3: {} + iceberg-js@0.8.1: {} + iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 2b41acd9b0..aa2a75010b 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -27,6 +27,8 @@ catalog: '@shikijs/transformers': 4.0.2 '@shikijs/types': 4.0.2 '@stackblitz/sdk': 1.11.0 + '@supabase/ssr': 0.10.0 + '@supabase/supabase-js': 2.101.1 '@sveltejs/adapter-auto': 7.0.1 '@sveltejs/adapter-vercel': 6.3.3 '@sveltejs/kit': 2.55.0 diff --git a/sites/plus.skeleton.dev/.env.example b/sites/plus.skeleton.dev/.env.example new file mode 100644 index 0000000000..1e677e4064 --- /dev/null +++ b/sites/plus.skeleton.dev/.env.example @@ -0,0 +1,2 @@ +PUBLIC_SUPABASE_URL= +PUBLIC_SUPABASE_PUBLISHABLE_KEY= \ No newline at end of file diff --git a/sites/plus.skeleton.dev/package.json b/sites/plus.skeleton.dev/package.json new file mode 100644 index 0000000000..6ed27f8acb --- /dev/null +++ b/sites/plus.skeleton.dev/package.json @@ -0,0 +1,29 @@ +{ + "name": "@skeletonlabs/plus.skeleton.dev", + "version": "1.0.0", + "private": true, + "scripts": { + "dev": "vite dev", + "build": "vite build", + "check": "svelte-check --tsconfig ./tsconfig.json", + "postinstall": "svelte-kit sync" + }, + "devDependencies": { + "@skeletonlabs/skeleton": "workspace:*", + "@skeletonlabs/skeleton-svelte": "workspace:*", + "@supabase/ssr": "catalog:", + "@supabase/supabase-js": "catalog:", + "@sveltejs/adapter-auto": "^7.0.0", + "@sveltejs/kit": "^2.50.2", + "@sveltejs/vite-plugin-svelte": "^6.2.4", + "@tailwindcss/forms": "^0.5.11", + "@tailwindcss/vite": "^4.1.18", + "svelte": "^5.54.0", + "svelte-check": "^4.4.2", + "tailwindcss": "^4.1.18", + "typescript": "^5.9.3", + "vite": "^7.3.1", + "vite-plugin-transform-lucide-imports": "catalog:" + }, + "type": "module" +} diff --git a/sites/plus.skeleton.dev/src/app.d.ts b/sites/plus.skeleton.dev/src/app.d.ts new file mode 100644 index 0000000000..054649ebd7 --- /dev/null +++ b/sites/plus.skeleton.dev/src/app.d.ts @@ -0,0 +1,21 @@ +import type { Session, SupabaseClient, User } from '@supabase/supabase-js'; +import type { Database } from './database.types.ts'; + +declare global { + namespace App { + // interface Error {} + interface Locals { + supabase: SupabaseClient; + safeGetSession: () => Promise<{ session: Session | null; user: User | null }>; + session: Session | null; + user: User | null; + } + interface PageData { + session: Session | null; + } + // interface PageState {} + // interface Platform {} + } +} + +export {}; diff --git a/sites/plus.skeleton.dev/src/app.html b/sites/plus.skeleton.dev/src/app.html new file mode 100644 index 0000000000..6a2bb58226 --- /dev/null +++ b/sites/plus.skeleton.dev/src/app.html @@ -0,0 +1,12 @@ + + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/sites/plus.skeleton.dev/src/hooks.server.ts b/sites/plus.skeleton.dev/src/hooks.server.ts new file mode 100644 index 0000000000..79b3297163 --- /dev/null +++ b/sites/plus.skeleton.dev/src/hooks.server.ts @@ -0,0 +1,56 @@ +import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_PUBLISHABLE_KEY } from '$env/static/public'; +import { createServerClient } from '@supabase/ssr'; +import type { Handle } from '@sveltejs/kit'; + +export const handle: Handle = async ({ event, resolve }) => { + event.locals.supabase = createServerClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_PUBLISHABLE_KEY, { + cookies: { + getAll() { + return event.cookies.getAll(); + }, + setAll(cookiesToSet, headers) { + /** + * Note: You have to add the `path` variable to the + * set and remove method due to sveltekit's cookie API + * requiring this to be set, setting the path to an empty string + * will replicate previous/standard behavior (https://kit.svelte.dev/docs/types#public-types-cookies) + */ + cookiesToSet.forEach(({ name, value, options }) => event.cookies.set(name, value, { ...options, path: '/' })); + if (Object.keys(headers).length > 0) { + event.setHeaders(headers); + } + }, + }, + }); + + /** + * Unlike `supabase.auth.getSession()`, which returns the session _without_ + * validating the JWT, this function also calls `getUser()` to validate the + * JWT before returning the session. + */ + event.locals.safeGetSession = async () => { + const { + data: { session }, + } = await event.locals.supabase.auth.getSession(); + if (!session) { + return { session: null, user: null }; + } + + const { + data: { user }, + error, + } = await event.locals.supabase.auth.getUser(); + if (error) { + // JWT validation has failed + return { session: null, user: null }; + } + + return { session, user }; + }; + + return resolve(event, { + filterSerializedResponseHeaders(name) { + return name === 'content-range' || name === 'x-supabase-api-version'; + }, + }); +}; diff --git a/sites/plus.skeleton.dev/src/routes/+layout.server.ts b/sites/plus.skeleton.dev/src/routes/+layout.server.ts new file mode 100644 index 0000000000..f2f7b411bf --- /dev/null +++ b/sites/plus.skeleton.dev/src/routes/+layout.server.ts @@ -0,0 +1,9 @@ +export const load = async (event) => { + const { session, user } = await event.locals.safeGetSession(); + + return { + session, + user, + cookies: event.cookies.getAll(), + }; +}; diff --git a/sites/plus.skeleton.dev/src/routes/+layout.svelte b/sites/plus.skeleton.dev/src/routes/+layout.svelte new file mode 100644 index 0000000000..65e81826a5 --- /dev/null +++ b/sites/plus.skeleton.dev/src/routes/+layout.svelte @@ -0,0 +1,7 @@ + + +{@render children()} diff --git a/sites/plus.skeleton.dev/src/routes/+layout.ts b/sites/plus.skeleton.dev/src/routes/+layout.ts new file mode 100644 index 0000000000..c750f288c8 --- /dev/null +++ b/sites/plus.skeleton.dev/src/routes/+layout.ts @@ -0,0 +1,29 @@ +import { PUBLIC_SUPABASE_PUBLISHABLE_KEY, PUBLIC_SUPABASE_URL } from '$env/static/public'; +import { createBrowserClient, createServerClient, isBrowser } from '@supabase/ssr'; + +export const load = async (event) => { + event.depends('supabase:auth'); + + const supabase = isBrowser() + ? createBrowserClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_PUBLISHABLE_KEY, { + global: { + fetch, + }, + }) + : createServerClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_PUBLISHABLE_KEY, { + global: { + fetch, + }, + cookies: { + getAll() { + return event.data.cookies; + }, + }, + }); + + const { + data: { session }, + } = await supabase.auth.getSession(); + + return { supabase, session }; +}; diff --git a/sites/plus.skeleton.dev/src/routes/+page.svelte b/sites/plus.skeleton.dev/src/routes/+page.svelte new file mode 100644 index 0000000000..cc88df0ea3 --- /dev/null +++ b/sites/plus.skeleton.dev/src/routes/+page.svelte @@ -0,0 +1,2 @@ +

Welcome to SvelteKit

+

Visit svelte.dev/docs/kit to read the documentation

diff --git a/sites/plus.skeleton.dev/src/routes/auth/confirm/+server.ts b/sites/plus.skeleton.dev/src/routes/auth/confirm/+server.ts new file mode 100644 index 0000000000..cd2d01341a --- /dev/null +++ b/sites/plus.skeleton.dev/src/routes/auth/confirm/+server.ts @@ -0,0 +1,31 @@ +import { redirect } from '@sveltejs/kit'; +import { type EmailOtpType } from '@supabase/supabase-js'; + +export const GET = async (event) => { + const token_hash = event.url.searchParams.get('token_hash') as string; + const type = event.url.searchParams.get('type') as EmailOtpType | null; + const next = event.url.searchParams.get('next') ?? '/'; + + /** + * Clean up the redirect URL by deleting the Auth flow parameters. + * + * `next` is preserved for now, because it's needed in the error case. + */ + const redirectTo = new URL(event.url); + redirectTo.pathname = next; + redirectTo.searchParams.delete('token_hash'); + redirectTo.searchParams.delete('type'); + + if (token_hash && type) { + const { error } = await event.locals.supabase.auth.verifyOtp({ token_hash, type }); + if (!error) { + redirectTo.searchParams.delete('next'); + redirect(303, redirectTo); + } + } + + // return the user to an error page with some instructions + // TODO: Create a proper error page and pass the error message along + redirectTo.pathname = '/auth/error'; + redirect(303, redirectTo); +}; diff --git a/sites/plus.skeleton.dev/src/routes/layout.css b/sites/plus.skeleton.dev/src/routes/layout.css new file mode 100644 index 0000000000..ffb96a15fe --- /dev/null +++ b/sites/plus.skeleton.dev/src/routes/layout.css @@ -0,0 +1,2 @@ +@import 'tailwindcss'; +@plugin '@tailwindcss/forms'; diff --git a/sites/plus.skeleton.dev/static/robots.txt b/sites/plus.skeleton.dev/static/robots.txt new file mode 100644 index 0000000000..b6dd6670cb --- /dev/null +++ b/sites/plus.skeleton.dev/static/robots.txt @@ -0,0 +1,3 @@ +# allow crawling everything by default +User-agent: * +Disallow: diff --git a/sites/plus.skeleton.dev/svelte.config.js b/sites/plus.skeleton.dev/svelte.config.js new file mode 100644 index 0000000000..973f554e73 --- /dev/null +++ b/sites/plus.skeleton.dev/svelte.config.js @@ -0,0 +1,13 @@ +import adapter from '@sveltejs/adapter-auto'; + +/** @type {import('@sveltejs/kit').Config} */ +const config = { + compilerOptions: { + runes: ({ filename }) => (filename.split(/[/\\]/).includes('node_modules') ? undefined : true), + }, + kit: { + adapter: adapter(), + }, +}; + +export default config; diff --git a/sites/plus.skeleton.dev/tsconfig.json b/sites/plus.skeleton.dev/tsconfig.json new file mode 100644 index 0000000000..81def1550e --- /dev/null +++ b/sites/plus.skeleton.dev/tsconfig.json @@ -0,0 +1,18 @@ +{ + "extends": "./.svelte-kit/tsconfig.json", + "compilerOptions": { + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "moduleResolution": "bundler" + } + // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias and https://kit.svelte.dev/docs/configuration#files + // + // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes + // from the referenced tsconfig.json - TypeScript does not merge them in +} diff --git a/sites/plus.skeleton.dev/vite.config.ts b/sites/plus.skeleton.dev/vite.config.ts new file mode 100644 index 0000000000..8c26883b20 --- /dev/null +++ b/sites/plus.skeleton.dev/vite.config.ts @@ -0,0 +1,8 @@ +import { sveltekit } from '@sveltejs/kit/vite'; +import tailwind from '@tailwindcss/vite'; +import { defineConfig } from 'vite'; +import transformLucideImports from 'vite-plugin-transform-lucide-imports'; + +export default defineConfig({ + plugins: [sveltekit(), tailwind(), transformLucideImports()], +});