diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..815d6d0 --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +PUBLIC_SUPABASE_URL="" +PUBLIC_SUPABASE_ANON_KEY="" \ No newline at end of file diff --git a/src/lib/components/SignIn.svelte b/src/lib/components/SignIn.svelte new file mode 100644 index 0000000..9eb7017 --- /dev/null +++ b/src/lib/components/SignIn.svelte @@ -0,0 +1,71 @@ + + +
+
+
+ +
+
+ +
+ +
+ +
+
+
diff --git a/src/lib/components/SignOut.svelte b/src/lib/components/SignOut.svelte new file mode 100644 index 0000000..a4cc2bf --- /dev/null +++ b/src/lib/components/SignOut.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/lib/components/SignUp.svelte b/src/lib/components/SignUp.svelte new file mode 100644 index 0000000..bc2053a --- /dev/null +++ b/src/lib/components/SignUp.svelte @@ -0,0 +1,67 @@ + + +
+
+ +
+
+ +
+
+ +
+
diff --git a/src/lib/index.ts b/src/lib/index.ts new file mode 100644 index 0000000..856f2b6 --- /dev/null +++ b/src/lib/index.ts @@ -0,0 +1 @@ +// place files you want to import through the `$lib` alias in this folder. diff --git a/src/lib/stores/user.ts b/src/lib/stores/user.ts new file mode 100644 index 0000000..fc3cad2 --- /dev/null +++ b/src/lib/stores/user.ts @@ -0,0 +1,5 @@ +import { writable } from 'svelte/store'; +import { type User } from '@supabase/auth-js'; + +// Create a user store with null as the initial value +export const user = writable(null); diff --git a/src/routes/+layout.server.ts b/src/routes/+layout.server.ts new file mode 100644 index 0000000..1d33583 --- /dev/null +++ b/src/routes/+layout.server.ts @@ -0,0 +1,10 @@ +import type { LayoutServerLoad } from './$types'; + +export const load: LayoutServerLoad = async ({ locals: { safeGetSession } }) => { + const { session, user } = await safeGetSession(); + + return { + session, + user + }; +}; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte new file mode 100644 index 0000000..0ea8eca --- /dev/null +++ b/src/routes/+layout.svelte @@ -0,0 +1,230 @@ + + + + + + + + + + + +
+ +
+ +
+ +
+ + + + diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts new file mode 100644 index 0000000..80875ca --- /dev/null +++ b/src/routes/+layout.ts @@ -0,0 +1,34 @@ +import { PUBLIC_SUPABASE_ANON_KEY, PUBLIC_SUPABASE_URL } from '$env/static/public'; +import type { LayoutLoad } from './$types'; +import { createBrowserClient, isBrowser, parse } from '@supabase/ssr'; + +export const load: LayoutLoad = async ({ fetch, data, depends }) => { + depends('supabase:auth'); + + const supabase = createBrowserClient(PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY, { + global: { + fetch + }, + cookies: { + get(key) { + if (!isBrowser()) { + return JSON.stringify(data.session); + } + + const cookie = parse(document.cookie); + return cookie[key]; + } + } + }); + + /** + * It's fine to use `getSession` here, because on the client, `getSession` is + * safe, and on the server, it reads `session` from the `LayoutData`, which + * safely checked the session using `safeGetSession`. + */ + const { + data: { session } + } = await supabase.auth.getSession(); + + return { supabase, session }; +}; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte new file mode 100644 index 0000000..c354b89 --- /dev/null +++ b/src/routes/+page.svelte @@ -0,0 +1,150 @@ + + +
+
+
+

Sign up for this amazing SaaS right now - don't miss out!

+
+
+ +
+
+
+ +
+
+
+
Conversions
+
310K
+
Since January 2024
+
+ +
+
New Users
+
4,200
+
↗︎ 400 (22%)
+
+ +
+
Contracts Completed
+
1,200
+
↘︎ 90 (14%)
+
+
+ +
+

Features

+ +
    +
  • +
    + + + +
    +

    Blah

    +

    + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ut ex blandit, hendrerit + dolor in, egestas erat. In hac habitasse platea dictumst. Vestibulum consequat arcu + ultrices, dignissim quam consectetur, mattis turpis. Quisque ligula est, consectetur a + nunc eget, efficitur euismod sapien. +

    +
    +
    +
  • +
  • +
    + + + +
    +

    Blah

    +

    + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ut ex blandit, hendrerit + dolor in, egestas erat. In hac habitasse platea dictumst. Vestibulum consequat arcu + ultrices, dignissim quam consectetur, mattis turpis. Quisque ligula est, consectetur a + nunc eget, efficitur euismod sapien. +

    +
    +
    +
  • +
  • +
    + + + +
    +

    Blah

    +

    + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ut ex blandit, hendrerit + dolor in, egestas erat. In hac habitasse platea dictumst. Vestibulum consequat arcu + ultrices, dignissim quam consectetur, mattis turpis. Quisque ligula est, consectetur a + nunc eget, efficitur euismod sapien. +

    +
    +
    +
  • +
  • +
    + + + +
    +

    Blah

    +

    + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ut ex blandit, hendrerit + dolor in, egestas erat. In hac habitasse platea dictumst. Vestibulum consequat arcu + ultrices, dignissim quam consectetur, mattis turpis. Quisque ligula est, consectetur a + nunc eget, efficitur euismod sapien. +

    +
    +
    +
  • +
+
+
diff --git a/src/routes/about/+page.ts b/src/routes/about/+page.ts new file mode 100644 index 0000000..3e13462 --- /dev/null +++ b/src/routes/about/+page.ts @@ -0,0 +1,9 @@ +import { dev } from '$app/environment'; + +// we don't need any JS on this page, though we'll load +// it in dev so that we get hot module replacement... +export const csr = dev; + +// since there's no dynamic data here, we can prerender +// it so that it gets served as a static asset in prod +export const prerender = true; diff --git a/src/routes/auth/confirm/+server.ts b/src/routes/auth/confirm/+server.ts new file mode 100644 index 0000000..bd03c7a --- /dev/null +++ b/src/routes/auth/confirm/+server.ts @@ -0,0 +1,22 @@ +import { redirect } from '@sveltejs/kit'; +import { type EmailOtpType } from '@supabase/supabase-js'; + +export const GET = async (event) => { + const { + url, + locals: { supabase } + } = event; + const token_hash = url.searchParams.get('token_hash') as string; + const type = url.searchParams.get('type') as EmailOtpType | null; + const next = url.searchParams.get('next') ?? '/'; + + if (token_hash && type) { + const { error } = await supabase.auth.verifyOtp({ token_hash, type }); + if (!error) { + throw redirect(303, `/${next.slice(1)}`); + } + } + + // return the user to an error page with some instructions + throw redirect(303, '/auth/auth-code-error'); +}; diff --git a/src/routes/profile/+page.svelte b/src/routes/profile/+page.svelte new file mode 100644 index 0000000..b989b50 --- /dev/null +++ b/src/routes/profile/+page.svelte @@ -0,0 +1,23 @@ + + +
+ {#if localUser} + {localUser?.email} + {:else} +

Please log in to view this page

+ {/if} +