diff --git a/src/lib/utils/code.ts b/src/lib/utils/code.ts index 4dd877f87e..fd2659318f 100644 --- a/src/lib/utils/code.ts +++ b/src/lib/utils/code.ts @@ -28,6 +28,7 @@ import { Platform } from './references'; const languages = { js: javascript, + javascript: javascript, dart: dart, ts: typescript, typescript: typescript, @@ -56,7 +57,8 @@ const languages = { py: python, rb: ruby, cs: csharp, - css: css + css: css, + svelte: xml } as const satisfies Record; const platformAliases: Record = { diff --git a/src/routes/docs/tutorials/sveltekit-auth/+layout.svelte b/src/routes/docs/tutorials/sveltekit-auth/+layout.svelte new file mode 100644 index 0000000000..fb9fb3980f --- /dev/null +++ b/src/routes/docs/tutorials/sveltekit-auth/+layout.svelte @@ -0,0 +1,10 @@ + + + diff --git a/src/routes/docs/tutorials/sveltekit-auth/+layout.ts b/src/routes/docs/tutorials/sveltekit-auth/+layout.ts new file mode 100644 index 0000000000..562b11506f --- /dev/null +++ b/src/routes/docs/tutorials/sveltekit-auth/+layout.ts @@ -0,0 +1,11 @@ +import type { LayoutLoad } from './$types'; + +export const load: LayoutLoad = ({ url }) => { + const tutorials = import.meta.glob('./**/*.markdoc', { + eager: true + }); + return { + tutorials, + pathname: url.pathname + }; +}; diff --git a/src/routes/docs/tutorials/sveltekit-auth/+page.ts b/src/routes/docs/tutorials/sveltekit-auth/+page.ts new file mode 100644 index 0000000000..1ad2b05f29 --- /dev/null +++ b/src/routes/docs/tutorials/sveltekit-auth/+page.ts @@ -0,0 +1,6 @@ +import { redirect } from '@sveltejs/kit'; +import type { PageLoad } from './$types'; + +export const load: PageLoad = async () => { + throw redirect(303, '/docs/tutorials/sveltekit-auth/step-1'); +}; diff --git a/src/routes/docs/tutorials/sveltekit-auth/step-1/+page.markdoc b/src/routes/docs/tutorials/sveltekit-auth/step-1/+page.markdoc new file mode 100644 index 0000000000..2f0445231a --- /dev/null +++ b/src/routes/docs/tutorials/sveltekit-auth/step-1/+page.markdoc @@ -0,0 +1,18 @@ +--- +layout: tutorial +title: Authentication with SvelteKit +description: Add Authentication to a SvelteKit project using Appwrite. +step: 1 +difficulty: beginner +readtime: 20 +--- + +Appwrite takes away your stress of building and maintaining a backend. Appwrite helps you implement authentication, databases, file storage, and respond to real-time events with **secure** APIs out of the box. +If you're a Svelte developer, examples in this guide shows you how Appwrite can help you add authentication to Svelte apps faster. + +## Before you start + +Even if you've never tried Appwrite, you will get an idea of what it'll feel like to build with Svelte and Appwrite. + +If you're inspired and wish to follow along, make sure you've followed [Start with Svelte](https://appwrite.io/docs/quick-starts/sveltekit) first. +You can also choose to clone our [Getting started](https://github.com/appwrite/getting-started-projects/tree/main/svelte) examples and follow along by looking at our example code. \ No newline at end of file diff --git a/src/routes/docs/tutorials/sveltekit-auth/step-2/+page.markdoc b/src/routes/docs/tutorials/sveltekit-auth/step-2/+page.markdoc new file mode 100644 index 0000000000..8dad1a7364 --- /dev/null +++ b/src/routes/docs/tutorials/sveltekit-auth/step-2/+page.markdoc @@ -0,0 +1,52 @@ +--- +layout: tutorial +title: Create project +description: Add Authentication to a SvelteKit project using Appwrite. +step: 2 +--- + + +You can create a Svelte project using [SvelteKit](https://kit.svelte.dev/docs/creating-a-project). + +```sh +npm create svelte@latest +``` + +The command will give you a prompt with several project types. We'll be starting with a skeleton project. + +The prompt will be something similar to this. + +```sh +create-svelte version 3.2.0 + +┌ Welcome to SvelteKit! +│ +◇ Where should we create your project? +│ my-svelte-project +│ +◇ Which Svelte app template? +│ Skeleton project +│ +◇ Add type checking with TypeScript? +│ Yes, using JavaScript with JSDoc comments +│ +◇ Select additional options (use arrow keys/space bar) +│ Add ESLint for code linting +│ +└ Your project is ready! +``` + +After the prompt is finished, you can head over to the newly create project. + +```sh +cd my-svelte-project +npm install +``` + +## Adding Appwrite to Your Svelte App + +Appwrite provides a Web SDK that can be used in your Svelte apps. You can use Appwrite by installing the Web SDK as an NPM package. + +```sh +npm install appwrite +``` \ No newline at end of file diff --git a/src/routes/docs/tutorials/sveltekit-auth/step-3/+page.markdoc b/src/routes/docs/tutorials/sveltekit-auth/step-3/+page.markdoc new file mode 100644 index 0000000000..8b3eb0e4be --- /dev/null +++ b/src/routes/docs/tutorials/sveltekit-auth/step-3/+page.markdoc @@ -0,0 +1,46 @@ +--- +layout: tutorial +title: Initialize SDK +description: Add Authentication to a SvelteKit project using Appwrite. +step: 3 +--- +Before you can use Appwrite, you need to instanciate the Appwrite `Client` class with the project ID and endpoint. +This tells the SDK where your Appwrite project is hosted and which one to connect to. + +The client is then used to initialize services like `Databases` and `Account`, so they all point to the same Appwrite project. + +You can do this by instantiating the services you need in a file like `src/lib/appwrite.js` and **exporting the instances**. + +```js +// src/lib/appwrite.js +import { + PUBLIC_APPWRITE_ENDPOINT, + PUBLIC_APPWRITE_PROJECT, +} from "$env/static/public"; +import { Databases, Account, Client } from "appwrite"; + +const client = new Client(); +client + .setEndpoint(PUBLIC_APPWRITE_ENDPOINT) + .setProject(PUBLIC_APPWRITE_PROJECT); + +const account = new Account(client); +const databases = new Databases(client); + +export const appwrite = { + client, + account, + databases, +}; +``` + +`PUBLIC_APPWRITE_ENDPOINT` and `PUBLIC_APPWRITE_PROJECT` are environment variables that are exported in your project's [.env file](https://kit.svelte.dev/docs/modules#$env-dynamic-public). + +For example, your `.env` might look something similar to this. + +```text +PUBLIC_APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1 +PUBLIC_APPWRITE_PROJECT=642sdddf85b440dc7e5bf +``` + +You can get the values for these variables from the Appwrite console's **Settings** page. \ No newline at end of file diff --git a/src/routes/docs/tutorials/sveltekit-auth/step-4/+page.markdoc b/src/routes/docs/tutorials/sveltekit-auth/step-4/+page.markdoc new file mode 100644 index 0000000000..6ffb6545f9 --- /dev/null +++ b/src/routes/docs/tutorials/sveltekit-auth/step-4/+page.markdoc @@ -0,0 +1,64 @@ +--- +layout: tutorial +title: Check if logged in +description: Add Authentication to a SvelteKit project using Appwrite. +step: 4 +--- + +Before taking a user to the login screen, we should check if they're already logged in. +With SvelteKit, you can use the `load` function to check if you're logged in before your app renders. + +```js +// src/routes/+layout.js +import { appwrite } from "$lib/appwrite"; + +// Turn off SSR globally, turning the project into a static site +export const ssr = false; + +export const load = async () => { + try { + return { + account: await appwrite.account.get(), + }; + } catch { + return { + account: null, + }; + } +}; +``` + +By returning the account data in the root layout, it is globally available to all pages, **before any page is displayed** to the user. +If we find the user is not logged in, we can redirect them to log in first. + +We can get the returned data in the root page by using the `data` prop: + +```svelte + + + +{#if loggedIn} +

Hello {data.account?.name}!

+ +{:else} + Login + Signup +{/if} +``` + +Normally, you'll want to use the `invalidate` method instead of `invalidateAll`, to avoid fetching data that you don't need to. +You can refer to the [SvelteKit docs](https://kit.svelte.dev/docs/modules#$app-navigation-invalidate) for more information on invalidation. \ No newline at end of file diff --git a/src/routes/docs/tutorials/sveltekit-auth/step-5/+page.markdoc b/src/routes/docs/tutorials/sveltekit-auth/step-5/+page.markdoc new file mode 100644 index 0000000000..289773dabd --- /dev/null +++ b/src/routes/docs/tutorials/sveltekit-auth/step-5/+page.markdoc @@ -0,0 +1,83 @@ +--- +layout: tutorial +title: Create login page +description: Add Authentication to a SvelteKit project using Appwrite. +step: 5 +--- + +We can now implement our login page. Create a `+page.js` file in the `src/routes/login` directory: + +```js +// src/routes/login/+page.js +import { redirect } from "@sveltejs/kit"; + +export const load = async ({ parent }) => { + // Gets the data returned from the root layout + const { account } = await parent(); + if (account) { + throw redirect(303, "/"); + } +}; +``` + +You can see that we added a redirect in the login page to check if the user's already logged in, in which case we redirect them to the homepage. + +Now we just need to create a form to let the user input sign in data. + +```svelte + + + +
+ + + + + + {#if formError} +

{formError}

+ {/if} +
+``` + +And that's it. When the user successfully logs in, we use `invalidateAll` to re-run the relevant `load` functions. In this case, the functions inside `src/routes/login/+page.js` and `src/routes/+layout.js`. +This means that the `account` data will be updated, no longer being `null`, and so the login `load` function will redirect the user to the home page. diff --git a/src/routes/docs/tutorials/sveltekit-auth/step-6/+page.markdoc b/src/routes/docs/tutorials/sveltekit-auth/step-6/+page.markdoc new file mode 100644 index 0000000000..185b25174b --- /dev/null +++ b/src/routes/docs/tutorials/sveltekit-auth/step-6/+page.markdoc @@ -0,0 +1,69 @@ +--- +layout: tutorial +title: Create signup page +description: Add Authentication to a SvelteKit project using Appwrite. +step: 6 +--- + +For signup, you can copy the login `+page.js` and `+page.svelte` files into `src/routes/signup`, with some small changes to the `+page.svelte` file: + +```svelte + + + +
+ + + + + + + + {#if formError} +

{formError}

+ {/if} +
+``` +With this, you have a simple authentication system. + diff --git a/src/routes/docs/tutorials/sveltekit-auth/step-7/+page.markdoc b/src/routes/docs/tutorials/sveltekit-auth/step-7/+page.markdoc new file mode 100644 index 0000000000..2b3ac61f5c --- /dev/null +++ b/src/routes/docs/tutorials/sveltekit-auth/step-7/+page.markdoc @@ -0,0 +1,11 @@ +--- +layout: tutorial +title: All set +description: Add Authentication to a SvelteKit project using Appwrite. +step: 7 +--- +If you want to see these authentication concepts applied in a more robust manner, you can see them in action in this [demo app](https://github.com/appwrite/getting-started-projects/tree/main/svelte/auth). + +## Other authentication methods +Appwrite also supports OAuth, passwordless login, anonymous login, and phone login. +Learn more about them in the [authentication guide](https://appwrite.io/docs/products/auth). diff --git a/src/scss/hljs.css b/src/scss/hljs.css index d9605d03d3..cf7f2d67e7 100644 --- a/src/scss/hljs.css +++ b/src/scss/hljs.css @@ -1,5 +1,105 @@ +/*! + Theme: a11y-dark + Author: @ericwbailey + Maintainer: @ericwbailey + + Based on the Tomorrow Night Eighties theme: https://github.com/isagalaev/highlight.js/blob/master/src/styles/tomorrow-night-eighties.css +*/ + +.hljs { + background: #2b2b2b; + color: #f8f8f2; +} + +/* Comment */ +.hljs-comment, +.hljs-quote { + color: #d4d0ab; +} + +/* Red */ +.hljs-variable, +.hljs-template-variable, +.hljs-tag, +.hljs-name, +.hljs-selector-id, +.hljs-selector-class, +.hljs-regexp, +.hljs-deletion { + color: #ffa07a; +} + +/* Orange */ +.hljs-number, +.hljs-built_in, +.hljs-literal, +.hljs-type, +.hljs-params, +.hljs-meta, +.hljs-link { + color: #f5ab35; +} + +/* Yellow */ +.hljs-attribute { + color: #ffd700; +} + +/* Green */ +.hljs-string, +.hljs-symbol, +.hljs-bullet, +.hljs-addition { + color: #abe338; +} + +/* Blue */ +.hljs-title, +.hljs-section { + color: #00e0e0; +} + +/* Purple */ +.hljs-keyword, +.hljs-selector-tag { + color: #dcc6e0; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} + +@media screen and (-ms-high-contrast: active) { + .hljs-addition, + .hljs-attribute, + .hljs-built_in, + .hljs-bullet, + .hljs-comment, + .hljs-link, + .hljs-literal, + .hljs-meta, + .hljs-number, + .hljs-params, + .hljs-string, + .hljs-symbol, + .hljs-type, + .hljs-quote { + color: highlight; + } + + .hljs-keyword, + .hljs-selector-tag { + font-weight: bold; + } +} + +/* Our Overrides */ pre { - color: #e4e4e7; + color: #e4e4e7; } code.line-numbers .line { @@ -11,7 +111,7 @@ code.line-numbers .line:before { display: inline-block; text-align: right; padding-right: 1rem; - color: #6C6C71; + color: #6c6c71; width: 2.5rem; } @@ -22,7 +122,7 @@ code.line-numbers .line:before { .hljs-template-variable, .hljs-type, .hljs-variable.language_ { - color: #fe86a8; + color: #fe86a8; } .hljs-title, @@ -30,7 +130,7 @@ code.line-numbers .line:before { .hljs-title.class_.inherited__, .hljs-title.function_, .hljs-symbol { - color: #68a3fe; + color: #68a3fe; } .hljs-attr, @@ -44,25 +144,25 @@ code.line-numbers .line:before { .hljs-selector-attr, .hljs-selector-class, .hljs-selector-id { - color: #fe9567; + color: #fe9567; } .hljs-regexp, .hljs-string, .hljs-meta .hljs-string { - color: #85dbd8; + color: #85dbd8; } .hljs-comment, .hljs-code, .hljs-formula { - color: #adadb0; + color: #adadb0; } .hljs-emphasis { - font-style: italic; + font-style: italic; } .hljs-strong { - font-weight: bold; + font-weight: bold; }