From 6bae4383bbba4e7cbd94d9d6050f8b18f520c704 Mon Sep 17 00:00:00 2001 From: Evelina Berg Date: Wed, 25 Oct 2023 23:10:05 +0200 Subject: [PATCH 1/4] Add nuxt tutorial --- src/routes/docs/tutorials/nuxt/+layout.svelte | 10 + src/routes/docs/tutorials/nuxt/+layout.ts | 11 + src/routes/docs/tutorials/nuxt/+page.ts | 6 + .../docs/tutorials/nuxt/step-1/+page.markdoc | 35 +++ .../docs/tutorials/nuxt/step-2/+page.markdoc | 98 +++++++++ .../docs/tutorials/nuxt/step-3/+page.markdoc | 59 +++++ .../docs/tutorials/nuxt/step-4/+page.markdoc | 196 +++++++++++++++++ .../docs/tutorials/nuxt/step-5/+page.markdoc | 58 +++++ .../docs/tutorials/nuxt/step-6/+page.markdoc | 79 +++++++ .../docs/tutorials/nuxt/step-7/+page.markdoc | 203 ++++++++++++++++++ .../docs/tutorials/nuxt/step-8/+page.markdoc | 10 + 11 files changed, 765 insertions(+) create mode 100644 src/routes/docs/tutorials/nuxt/+layout.svelte create mode 100644 src/routes/docs/tutorials/nuxt/+layout.ts create mode 100644 src/routes/docs/tutorials/nuxt/+page.ts create mode 100644 src/routes/docs/tutorials/nuxt/step-1/+page.markdoc create mode 100644 src/routes/docs/tutorials/nuxt/step-2/+page.markdoc create mode 100644 src/routes/docs/tutorials/nuxt/step-3/+page.markdoc create mode 100644 src/routes/docs/tutorials/nuxt/step-4/+page.markdoc create mode 100644 src/routes/docs/tutorials/nuxt/step-5/+page.markdoc create mode 100644 src/routes/docs/tutorials/nuxt/step-6/+page.markdoc create mode 100644 src/routes/docs/tutorials/nuxt/step-7/+page.markdoc create mode 100644 src/routes/docs/tutorials/nuxt/step-8/+page.markdoc diff --git a/src/routes/docs/tutorials/nuxt/+layout.svelte b/src/routes/docs/tutorials/nuxt/+layout.svelte new file mode 100644 index 0000000000..fb9fb3980f --- /dev/null +++ b/src/routes/docs/tutorials/nuxt/+layout.svelte @@ -0,0 +1,10 @@ + + + diff --git a/src/routes/docs/tutorials/nuxt/+layout.ts b/src/routes/docs/tutorials/nuxt/+layout.ts new file mode 100644 index 0000000000..c8884f46b8 --- /dev/null +++ b/src/routes/docs/tutorials/nuxt/+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/nuxt/+page.ts b/src/routes/docs/tutorials/nuxt/+page.ts new file mode 100644 index 0000000000..fa071eee0a --- /dev/null +++ b/src/routes/docs/tutorials/nuxt/+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/nuxt/step-1'); +}; diff --git a/src/routes/docs/tutorials/nuxt/step-1/+page.markdoc b/src/routes/docs/tutorials/nuxt/step-1/+page.markdoc new file mode 100644 index 0000000000..b709a1a77e --- /dev/null +++ b/src/routes/docs/tutorials/nuxt/step-1/+page.markdoc @@ -0,0 +1,35 @@ +--- +layout: tutorial +title: Build an ideas tracker with Nuxt +description: Learn to build an idea tracker app with Appwrite and Nuxt with authentication, databases and collections, queries, pagination, and file storage. +step: 1 +difficulty: beginner +readtime: 12 +back: /docs +--- + +**Idea tracker**: an app to track all the side project ideas that you'll start, but probably never finish. +In this tutorial, you will build Idea tracker with Appwrite and Nuxt. + +{% only_dark %} +![Create project screen](/images/docs/tutorials/dark/idea-tracker.png) +{% /only_dark %} +{% only_light %} +![Create project screen](/images/docs/tutorials/idea-tracker.png) +{% /only_light %} + +# Concepts {% #concepts %} + +This tutorial will introduce the following concepts: + +1. Setting up your first project +2. Authentication +3. Navigation +4. Databases and collections +5. Queries + + +# Prerequisites {% #prerequisites %} + +1. Basic knowledge of JavaScript. +2. Have [Node.js](https://nodejs.org/en) and [NPM](https://www.npmjs.com/) installed on your computer. diff --git a/src/routes/docs/tutorials/nuxt/step-2/+page.markdoc b/src/routes/docs/tutorials/nuxt/step-2/+page.markdoc new file mode 100644 index 0000000000..74b0a9c9f5 --- /dev/null +++ b/src/routes/docs/tutorials/nuxt/step-2/+page.markdoc @@ -0,0 +1,98 @@ +--- +layout: tutorial +title: Create app +description: Create a Nuxt app project and integrate with Appwrite +step: 2 +--- + +# Create Nuxt project {% #create-nuxt-project %} + +Create a Nuxt app with the `npx init` command. + +```sh +npx nuxi@latest init ideas-tracker +``` + +# Add dependencies {% #add-dependencies %} + +Install the JavaScript Appwrite SDK. + +```sh +npm install appwrite +``` + +You can start the development server to watch your app update in the browser as you make changes. + +```sh +npm run dev +``` + +# Set up files {% #set up-files %} + +In Nuxt, directories help organize the codebase and minimize boilerplate. +The purpose is making it easy to find and manage different aspect of your application. + +The files added to the `pages` directory will automatically become a route. +Nuxt will look for a layout in the `layouts` directory to render a page layout. +Without a layout file in this directory, the routing won't work +When these files have been created the `app.vue` file needs to edited to render these pages instead of the standard welcome page. +Then, we will have a working app where we can verify our changes in the browser throughout the tutorial. +As an additional step, we will be adding [Appwrite's Pink Design system]('https://pink.appwrite.io/') to have a global design system to help with the layout. + +First, add a page by creating the file `src/pages/index.vue` and add the following code. + +```vue + +``` + +Create the file `src/layouts/default.vue` to add the default layout. + +```vue + + + +``` + +Go to `app.vue`, remove `NuxtWelcome`and insert `` wrapped inside ``. + +```vue + +``` + +To import Appwrite's design system to all pages and components, edit the file `nuxt.config.ts`. +The layouts is then ready to be used in the templates with auto-import. + +```ts +export default defineNuxtConfig({ + app: { + head: { + link: [ + { rel: "stylesheet", href: "https://unpkg.com/@appwrite.io/pink" }, + { + rel: "stylesheet", + href: "https://unpkg.com/@appwrite.io/pink-icons", + }, + ], + }, + }, + devtools: { enabled: true }, +}); +``` diff --git a/src/routes/docs/tutorials/nuxt/step-3/+page.markdoc b/src/routes/docs/tutorials/nuxt/step-3/+page.markdoc new file mode 100644 index 0000000000..8d8546c8b9 --- /dev/null +++ b/src/routes/docs/tutorials/nuxt/step-3/+page.markdoc @@ -0,0 +1,59 @@ +--- +layout: tutorial +title: Set up Appwrite +description: Import and configure a project with Appwrite Cloud. +step: 3 +--- + +# Create project {% #create-project %} + +Head to the [Appwrite Console](https://cloud.appwrite.io/console). + +{% only_dark %} +![Create project screen](/images/docs/quick-starts/dark/create-project.png) +{% /only_dark %} +{% only_light %} +![Create project screen](/images/docs/quick-starts/create-project.png) +{% /only_light %} + +If this is your first time using Appwrite, create an account and create your first project. + +Then, under **Add a platform**, add a **Web app**. +The **Hostname** should be localhost. + +{% only_dark %} +![Add a platform](/images/docs/quick-starts/dark/add-platform.png) +{% /only_dark %} +{% only_light %} +![Add a platform](/images/docs/quick-starts/add-platform.png) +{% /only_light %} + +You can skip the optional steps. + +# Initialize Appwrite SDK {% #init-sdk %} + +To use Appwrite in our app, we'll need to find our project ID. +It is located in the **Settings** page. + +{% only_dark %} +![Project settings screen](/images/docs/quick-starts/dark/project-id.png) +{% /only_dark %} +{% only_light %} +![Project settings screen](/images/docs/quick-starts/project-id.png) +{% /only_light %} + +Create a new file `src/appwrite.js` for the Appwrite related code. +Only one instance of the `Client()` class should be created per app. +Add the following code to it, replacing `` with your project ID. + +```js +import { Client, Databases, Account } from "appwrite"; + +const client = new Client(); +client + .setEndpoint("https://cloud.appwrite.io/v1") + .setProject(""); // Replace with your project ID + +export const account = new Account(client); +export const database = new Databases(client); +``` diff --git a/src/routes/docs/tutorials/nuxt/step-4/+page.markdoc b/src/routes/docs/tutorials/nuxt/step-4/+page.markdoc new file mode 100644 index 0000000000..5522ddcc2d --- /dev/null +++ b/src/routes/docs/tutorials/nuxt/step-4/+page.markdoc @@ -0,0 +1,196 @@ +--- +layout: tutorial +title: Add authentication +description: Add authentication to your Nuxt application using Appwrite Web SDK +step: 4 +--- + +# Composables {% #composables %} + +Composables is a design pattern in Vue and Nuxt to manage logic related to data fetching and global state management. +You can think of a composable as a way to put pieces of code that do specific tasks into neat little boxes that you can use over and over again in you app. + +In the user session composable will put all the logic related to user authentication, such as login, logout and authentication status. +It will be available for access in all pages and components. + +Create your composable for the user session logic by adding the file `src/composables/useUserSession.js`. +Add the following code. + +```js +import { ID } from 'appwrite' +import { ref } from 'vue' +import { account } from '/appwrite' + +const current = ref(null) //Reference to the current user object +const isLoggedIn = ref(null) //Reference to check user status + +export const useUserSession = () => { + const register = async (email, password) => { + await account.create(ID.unique(), email, password) //Interaction with the Appwrite backend + await this.login(email, password) //Login the newly created user + } + + const login = async (email, password) => { + const authUser = await account.createEmailSession(email, password) //Interaction with the Appwrite backend + current.value = authUser //Passing user data to the current user reference + isLoggedIn.value = true //Setting user status to true + } + + const logout = async () => { + await account.deleteSession('current') //Interaction with the Appwrite backend + current.value = null //Clearing the current user data object + isLoggedIn.value = false //Setting user status to false + } + return { + current, + isLoggedIn, + login, + logout, + register, + } +``` + +The `useUserSession()` function is neatly packed and ready to be reused in our pages and components. + +# Login page {% #login-page %} + +With the authentication functions handled, we can go on to build a simple login page. +The user interactions will be handled in a form with two input fields for email and password. +Underneath will be a button to login and a button to register a new user. + +The values from the inputs will be bound to a `v-model`. +The `v-model`acts like a bridge between your input fields and your Javascript code. +If you change the information with yout code, the input field also changes. +Similarily, if you type something in the input field, the information in your code also updates. +It is a two-way-cnnection that are magically links them together. + +Create the form by adding a new file `src/pages/index.vue` and put in the following code. + +```vue + + + +``` + +# Home page {% #home-page %} + +Now that users can register and login to the app, let's modify the home page in `src/pages/index.vue` to give the logged in users a secret message. + +```vue + + + +``` diff --git a/src/routes/docs/tutorials/nuxt/step-5/+page.markdoc b/src/routes/docs/tutorials/nuxt/step-5/+page.markdoc new file mode 100644 index 0000000000..c6b6c3c284 --- /dev/null +++ b/src/routes/docs/tutorials/nuxt/step-5/+page.markdoc @@ -0,0 +1,58 @@ +--- +layout: tutorial +title: Add navigation +description: Add navigation to your app. +step: 5 +--- + +To help our users navigate the app we want it to have a navigation bar that's visible on all pages. +We will use the `useUserSession` composable to show a login button when no user is logged in and a logout button when logged in. +Open the `app.vue` file and add the navbar in the `template`, just above the `` tag. + +```vue +... + + + + + + +... +``` + +Add a new script below the template to get information about the user session from the `useUserSession`composable. + +```vue + +``` + +You might wonder about the v- diff --git a/src/routes/docs/tutorials/nuxt/step-6/+page.markdoc b/src/routes/docs/tutorials/nuxt/step-6/+page.markdoc new file mode 100644 index 0000000000..b002524b98 --- /dev/null +++ b/src/routes/docs/tutorials/nuxt/step-6/+page.markdoc @@ -0,0 +1,79 @@ +--- +layout: tutorial +title: Add database +description: Add databases and queries for ideas in your Nuxt project. +step: 6 +--- + +In Appwrite, data is stored as a collection of documents. Create a collection in the [Appwrite Console](https://cloud.appwrite.io/) to store our ideas. + +{% only_dark %} +![Create project screen](/images/docs/tutorials/dark/idea-tracker-collection.png) +{% /only_dark %} +{% only_light %} +![Create project screen](/images/docs/tutorials/idea-tracker-collection.png) +{% /only_light %} + +Create a new collection with the following attributes: +| Field | Type | Required | +|-------------|--------|----------| +| userId | String | Yes | +| title | String | Yes | +| description | String | No | + +Change the collection's permissions in the settings to give access. +First, add an "Any" role and check the `READ` box. +Next, add a "Users" role and give them access to create, update and delete. + +# Query methods {% #query-methods %} +Now that you have a collection to hold ideas, we can use it to get, add and remove data from our app. +We will create a new composable to manage the data fetching and their global state. +Create a new file in the composables directory, `src/composables/useIdeas.js` and add the following code. + +```js +import { ID, Query } from "appwrite"; +import { database } from "~/appwrite"; +import { ref } from "vue"; + +const IDEAS_DATABASE_ID = "YOUR_DATABASE_ID"; +const IDEAS_COLLECTION_ID = "YOUR_COLLECTION_ID"; + +const current = ref(null); //Reference for the fetched data + +export const useIdeas = () => { + + /* Fetch the 10 most recent ideas from the database + and passes the list to the current reference object */ + const init = async () => { + const response = await database.listDocuments( + IDEAS_DATABASE_ID, + IDEAS_COLLECTION_ID, + [Query.orderDesc("$createdAt"), Query.limit(10)] + ); + current.value = response.documents; + }; + + /* Add new idea to the database, add it to the current + object and remove the last to still have 10 ideas */ + const add = async (idea) => { + const response = await database.createDocument( + IDEAS_DATABASE_ID, + IDEAS_COLLECTION_ID, + ID.unique(), + idea + ); + current.value = [response, ...current.value].slice(0, 10); + + const remove = async (id) => { + await database.deleteDocument(IDEAS_DATABASE_ID, IDEAS_COLLECTION_ID, id); + await init(); //Refetch ideas to ensure we have 10 items + }; + + return { + add, + current, + init, + remove, + }; +}; +``` diff --git a/src/routes/docs/tutorials/nuxt/step-7/+page.markdoc b/src/routes/docs/tutorials/nuxt/step-7/+page.markdoc new file mode 100644 index 0000000000..fa619f51f0 --- /dev/null +++ b/src/routes/docs/tutorials/nuxt/step-7/+page.markdoc @@ -0,0 +1,203 @@ +--- +layout: tutorial +title: Create ideas page +description: Add database queries using Appwrite in your Nuxt app. +step: 7 +--- + +# Create ideas page {% #create-ideas-page %} + +Using the `useIdeas` composable, we can now get some ideas on the page to read and interact with. +We don't have any to show just yet, so we are going to start with adding a form to create new ones. +The form will only be visible for logged in users. + +We begin with adding the `v-model` object in the ` +``` + +Let's remove the header with the secret message we added in step 4 and replace it with a form. +Since the properties for the `v-model` variables are references, we use the `.value` property to get the correct information to show. + +```vue +... + +
+
+

Submit Idea

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