diff --git a/src/routes/docs/tutorials/vue-auth/+layout.svelte b/src/routes/docs/tutorials/vue-auth/+layout.svelte new file mode 100644 index 0000000000..fb9fb3980f --- /dev/null +++ b/src/routes/docs/tutorials/vue-auth/+layout.svelte @@ -0,0 +1,10 @@ + + + diff --git a/src/routes/docs/tutorials/vue-auth/+layout.ts b/src/routes/docs/tutorials/vue-auth/+layout.ts new file mode 100644 index 0000000000..562b11506f --- /dev/null +++ b/src/routes/docs/tutorials/vue-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/vue-auth/+page.ts b/src/routes/docs/tutorials/vue-auth/+page.ts new file mode 100644 index 0000000000..027e659825 --- /dev/null +++ b/src/routes/docs/tutorials/vue-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/vue-auth/step-1'); +}; diff --git a/src/routes/docs/tutorials/vue-auth/step-1/+page.markdoc b/src/routes/docs/tutorials/vue-auth/step-1/+page.markdoc new file mode 100644 index 0000000000..33a22a8cc6 --- /dev/null +++ b/src/routes/docs/tutorials/vue-auth/step-1/+page.markdoc @@ -0,0 +1,20 @@ +--- +layout: tutorial +title: Authentication with Vue +description: Add Authentication to a Vue project using Appwrite. +step: 1 +difficulty: intermediate +readtime: 40 +--- +## Appwrite: The backend you'll never have to build or maintain. + +Appwrite is a self-hosted backend platform that takes away the stress of building and maintaining a backend. With Appwrite, you can implement authentication, databases, file storage, and real-time events with secure APIs out of the box. + +This means that you can focus on what you do best: building great Vue apps. You don't have to worry about managing servers, databases, or security. Appwrite takes care of all that for you. Even if you're a beginner, you can get started with Appwrite and Vue in no time. + + +## Before you start + +Even if you've never tried Appwrite, you will get an idea of what it'll feel like to build with Vue and Appwrite. + +If you're inspired and wish to follow along, make sure you've followed [Start with Vue](https://appwrite.io/docs/quick-starts/vue) first and can later jump onto this tutorial. diff --git a/src/routes/docs/tutorials/vue-auth/step-10/+page.markdoc b/src/routes/docs/tutorials/vue-auth/step-10/+page.markdoc new file mode 100644 index 0000000000..6c28a8e82c --- /dev/null +++ b/src/routes/docs/tutorials/vue-auth/step-10/+page.markdoc @@ -0,0 +1,22 @@ +--- +layout: tutorial +title: Next steps +description: View your Vue.js app build on Appwrite Cloud. +step: 10 +--- + +# Test your project {% #test-project %} +Run your project with `npm run dev` and open the URL that comes up on the terminal. + + +# Play with your project {% #play-project %} + +Try to implement `validations` to input, make use of `phone verification`. + +# Use Appwrite{% #make-project %} + +Use appwrite in your projects and explore other amazing features that appwrite provides such as + +- Databases +- Functions +- Storage \ No newline at end of file diff --git a/src/routes/docs/tutorials/vue-auth/step-2/+page.markdoc b/src/routes/docs/tutorials/vue-auth/step-2/+page.markdoc new file mode 100644 index 0000000000..918825d0df --- /dev/null +++ b/src/routes/docs/tutorials/vue-auth/step-2/+page.markdoc @@ -0,0 +1,52 @@ +--- +layout: tutorial +title: Create project +description: Add Authentication to a Vue project using Appwrite. +step: 2 +--- + +# Create Vue Project + +You can create a Vue project using [Vue](https://vuejs.org/guide/quick-start.html). + +```sh +npm create vue@latest +``` + +This command will install and execute [create-vue](https://github.com/vuejs/create-vue), the official Vue project scaffolding tool. You will be presented with prompts for several optional features such as TypeScript and testing support: + +The prompt will be something similar to this. + +```sh +✔ Project name: … +✔ Add TypeScript? … No / Yes +✔ Add JSX Support? … No / Yes +✔ Add Vue Router for Single Page Application development? … No / Yes +✔ Add Pinia for state management? … No / Yes +✔ Add Vitest for Unit testing? … No / Yes +✔ Add an End-to-End Testing Solution? … No / Cypress / Playwright +✔ Add ESLint for code quality? … No / Yes +✔ Add Prettier for code formatting? … No / Yes + +Scaffolding project in ./... +Done. +``` +For this project we will be using Vue router and Pinia. So, make sure to check **yes** for these. + +After the prompt is finished, you can head over to the newly create project. + +```sh + cd vue_appwrite + npm install + npm run dev +``` + +After running all these commands, you will be able to access you Vue app. + +## Adding Appwrite to Your Vue App + +Appwrite provides a Web SDK that can be used in your Vue 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/vue-auth/step-3/+page.markdoc b/src/routes/docs/tutorials/vue-auth/step-3/+page.markdoc new file mode 100644 index 0000000000..08f32505f1 --- /dev/null +++ b/src/routes/docs/tutorials/vue-auth/step-3/+page.markdoc @@ -0,0 +1,64 @@ +--- +layout: tutorial +title: Initialize SDK +description: Import and configure a project with Appwrite Cloud and Vue.js. +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 optional steps. + +# Initialize Appwrite SDK {% #init-sdk %} + +To use Appwrite in our Vue app, we'll need to find our project ID. Find your project's ID 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/lib/appwrite.js` to hold our 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. + +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 +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 databases = new Databases(client); +``` +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/vue-auth/step-4/+page.markdoc b/src/routes/docs/tutorials/vue-auth/step-4/+page.markdoc new file mode 100644 index 0000000000..44da4f9017 --- /dev/null +++ b/src/routes/docs/tutorials/vue-auth/step-4/+page.markdoc @@ -0,0 +1,182 @@ +--- +layout: tutorial +title: Check if logged in +description: Setting up a pinia store, a navigation bar for ease of navigation and routes using vue-router +step: 4 +--- + +# Auth store {% #auth-store %} + +Since, we chose pinia for state management during the installatin process. So, we have already setuped our store. +Now, We just need to declare state(data that user will have), actions (fetching of information for appwrite). We will discuss about these as we go. + +```js +import { defineStore } from 'pinia'; +import { ID } from 'appwrite'; +import { account } from '../lib/appwrite.js'; + +export const useAuthenticationStore = defineStore('auth', { + state: () => ({ + email: '', + password: '', + name: '', + user: {}, + isAuthenticated: false, + isVerified: false, + }), + actions: { + async login() { + const loginResponse = await account.createEmailSession(this.email, this.password); + this.isAuthenticated = true; + }, + async logout() { + await account.deleteSession("current"); + this.user = null; + this.isAuthenticated = false; + }, + async register() { + const registerResponse = await account.create(ID.unique(), this.email, this.password, this.name); + alert("Account Created and verification send") + this.user = registerResponse; + }, + async getUser() { + this.user = await account.get(); + this.isVerified = this.user.emailVerification; + }, + async verifyUser(){ + const verfication = await account.createVerification('http://localhost:5174/verify') + }, + async confirmVerification(id, secret){ + const confirResponse = await account.updateVerification(id, secret) + }, + async UpdatePassword(email){ + const update = await account.createRecovery(email, 'http://localhost:5174/forgot') + }, + async UpdatePasswordConfirm(id,secret, password, passwordAgain){ + const confirResponse = await account.updateRecovery(id, secret, password, passwordAgain) + } + }, +}); +``` +Now, we can import the `auth` store in any component and use it to login, logout, verify user, recover password or register a user. + +Here, we have declared all the actions that we will require in order to achieve the following things: +- `Log in` +- `Register up` +- `Logout` +- `Get user data` +- `Verify user` +- `Password Recovery` + +We will be going through each of them as we move forward in the tutorial. + +# Basic Navigation {% #basic-navigation %} + +In `src/components` create a file called `Navbar.vue`, we will be using this in `src/App.vue` for ease of navigation. + +```html + +``` +Above we are using Use the `isAuthenticated` computed property to conditionally render the Dashboard and Login/Register route links. We also have a `logout` button which utilizes the `logout action` in the auth store. + +We maintain the `isAuthenticated` state in our store to enable navigation guards. + +```js + +``` +In the script we are using `authenticationStore` and using `isAuthenticated` state. + +Also, we have a logout function that will be visible only if user is logged in. This logout function is calling the `logout action` declared in our store, which will logout our user from the app. + +Below is how our `src/App.vue` will look. We have a navbar and `RouterView` which renders our views/pages. + +```js + +``` +```html + +``` + +# Home page {% #home-page %} + +`src/views` folder will contain all the pages that we will have in our app. + +Create a new file `src/views/Home.vue` and add the following code to it. + +```html + +``` + +In the above code we have some introduction and a link to `/login` route where our login form is present. + +# Routes {% #Routes %} + +Last setup, we require is to setup the routes using the `vue-router`. The routes `index.js` file is present in `src/router` folder. + +Now, add the code from this [index.js](https://gist.github.com/Vaibhav91one/02a2bc139625b985cc597c9fb0e7156e) file. + +The code above is a `Vue Router` configuration that defines the routes for your application and a navigation guard that prevents users from accessing protected routes if they are not authenticated. + +We will be having the following routes: + +- `home`: This is the home page of your application. It is accessible to all users. +- `dashboard`: This is a protected route that is only accessible to authenticated users. +- `verify`: This route is used to verify the user's email address. +- `login`: This route is used to log the user in, registering and password recovery. +- `forgot`: This route is used to reset the user's password. +- `/:pathMatch(.*)*`: This is a catch-all route that matches any URL that does not match another route. It redirects the user to the home page. + diff --git a/src/routes/docs/tutorials/vue-auth/step-5/+page.markdoc b/src/routes/docs/tutorials/vue-auth/step-5/+page.markdoc new file mode 100644 index 0000000000..0c3c832d8b --- /dev/null +++ b/src/routes/docs/tutorials/vue-auth/step-5/+page.markdoc @@ -0,0 +1,236 @@ +--- +layout: tutorial +title: Create login page +description: Everything about the login functionality and dashboard page. +step: 5 +--- + +# Login page {% #login-page %} + +Finally, we are going to create our login page. Users will be able to login, register or recover their password from this page. + +Create a new file `src/views/LoginRegister.vue` and add the following code to it. + +```html + +``` + +```js + +``` + +The above code is just a view/page in which we are importing the `login` component, the main login logic is written in the `login` component that we will be creating in the `src/components` folder. + +Now, lets create our login component. Create a file `src/components/Login.vue` and the following code to it. + +```js + +``` +Here is a short overview of what the above code is doing: +- Importing the pinia `useAuthenticationStore()` and the useRouter() hook. +- Creating a data section and define the following variables: `email`, `password`, and `name`. +- Creating a setup section and define the following methods: `login()`, `register()`, and `sendPasswordRecoveryMail()`. +- In the `beforeMount()` lifecycle hook, check if the user is already authenticated. If the user is authenticated, redirect the user to the home. +- In the `login()` method, call the `login() action` from the auth store and also we are using `getUser()` action that gets user data from appwrite and fills the user object. +- In the `register()` method, call the `register() action` from the auth store. +- In the `sendPasswordRecoveryMail()` method, call the `UpdatePassword() action` from the auth store. + + +```html + +``` + +In the above code we are doing the following things: + +- Using three variables: `isLogin`, `forgotPassword`, and `email`. +- Creating a Vue.js template with three sections: login, register, and forgot password. +- Using the `v-if` directive to conditionally render each section of the page. +- Using the `@submit.prevent` directive to prevent the default form submission behavior and call the corresponding method instead. + +Once you have completed these steps, you will have a basic Vue.js login, register, and forgot password form. Now, let's discuss the login, register, logout actions in deep. + +## Login action + +```js +async login() { + const loginResponse = await account.createEmailSession(this.email, this.password); + this.isAuthenticated = true; + } +``` + +To login to our app, we use `createEmailSession` function which appwrite provides this checks if the user is registered to the platform. +if user is registered, the user will be redirected to the `dashboard page` which will contain the user info, else the console will give the error invalid credentials. + + +The login action takes inputs such as email and password of the user. + +## Logout Action + +We can find the logout button in the navbar once the user is logged in. + +```js + await account.deleteSession("current"); + this.user = null; + this.isAuthenticated = false; +``` +we can logout the user using `deleteSession` and providing 'current' as the session ID to logout on this device. Also, this action makes the state of the user null. + +## getUser Action + +Using this action, we can fill the user state object with the user data which we will get via appwrite. + +```js + async getUser() { + this.user = await account.get(); + this.isVerified = this.user.emailVerification; + }, +``` +The above action fills our user state object with the user data we are getting via appwrite and also, assigns `isVerified` boolean state with `emailVerification` user data which is also boolean. + +# Dashboard page {% #Dashboard-page %} + +Now, we want to create our dashboard view/page which will show all the user information. Let's create a file `src/views/dashboard.vue` and add the following code to it. + +```js + +``` +In the above code we are doing the following things: + +- Importing the `useAuthenticationStore()`, `storeToRefs()`, and `computed` functions from Vue.js and the pinia library. +- Creating a variable called `authenticationStore` and assign it the result of calling the useAuthenticationStore() function. +- Creating a computed property called `isAuthenticated` that returns the value of the `isAuthenticated` property in the authentication store. +- Creating a computed property called `isVerified` that returns the value of the `isVerified` property in the authentication store. +- Creating a reactive reference to the `user` object in the authentication store by calling the `storeToRefs()` function and passing in the `authenticationStore` variable. +- Creating a method called `userVerify()` that calls the `verifyUser()` method on the authentication store. + + +```html + +``` +Here is what is happening in the above code: + +- The template first checks the value of the `isAuthenticated` computed property. If the user is authenticated, the template displays the "You are Logged In ✅" heading. Otherwise, the template displays the "You are Logged Out ❌" heading. +- If the user is authenticated, the template displays the user's name, email address, and ID. +- If the user is not verified and authenticated, the template displays the "Verify Account" button. +- If the user is verified and authenticated, the template displays the "Verified" button. +- If the user is authenticated, the template displays the "Delete Account" button. + +In the next step, we will be discussing about the **user verification** and **password recovery** functionality. \ No newline at end of file diff --git a/src/routes/docs/tutorials/vue-auth/step-6/+page.markdoc b/src/routes/docs/tutorials/vue-auth/step-6/+page.markdoc new file mode 100644 index 0000000000..31ee3a7ff4 --- /dev/null +++ b/src/routes/docs/tutorials/vue-auth/step-6/+page.markdoc @@ -0,0 +1,58 @@ +--- +layout: tutorial +title: Create signup page +description: Everything about the signup functionality. +step: 6 +--- + +# Signup page {% #signup-page %} + +We are going to conditionally render our signup form besides our login form only with the help of `v-if` directive. + +Now, lets add our signup logic. Go to file `src/components/Login.vue` and add the following code to the script. + +```js + async register() { + authenticationStore.email = this.email; + authenticationStore.password = this.password; + authenticationStore.name = this.name; + await authenticationStore.register(this.email, this.password, this.name); + } + +``` +The above function is setting the state of `email` , `password` and `name` and using the register action from the `authenticationStore`. + + +Now, add the following html to the template under the Signup comment. + +```html + +
+

Sign up

+
+ + + + +
+
+ + +
+
+``` +The `signup` div will only be rendered when he is not on either `forgotPassword` or `login` div. + +## Register action + +```js +async register() { + const registerResponse = await account.create(ID.unique(), this.email, this.password, this.name); + alert("Account Created") + } +``` + +To register to our app, we use `create` function which appwrite provides, this creates a user in our appwrite console. Now, user can login to the app with the credentials, the user entered during registration. + + +The register action takes inputs such as email, password and the name of the user. diff --git a/src/routes/docs/tutorials/vue-auth/step-7/+page.markdoc b/src/routes/docs/tutorials/vue-auth/step-7/+page.markdoc new file mode 100644 index 0000000000..b472dcdcb5 --- /dev/null +++ b/src/routes/docs/tutorials/vue-auth/step-7/+page.markdoc @@ -0,0 +1,121 @@ +--- +layout: tutorial +title: Password Recovery +description: This page deals with password recovery with Vue and Appwrite. +step: 7 +--- + +# forgotPassword page {% #forgotPassword-page %} +Appwrite also provides us the functionality of recovering our password. The application will take the user email and Sends the user an email with a temporary secret key for password reset. + +When the user clicks the confirmation link he is redirected back to your app password reset URL with the secret key and email address values attached to the URL query string. + +We are going to conditionally render our forgotPassword form besides our login and signup form with the help of `v-if` directive. + +Now, lets add our forgotPassword logic. Go to file `src/components/Login.vue` and add the following code to the script. + +```js + async sendPasswordRecoveryMail() { + authenticationStore.email = this.email; + await authenticationStore.UpdatePassword(this.email); + alert("Recovery Mail sent!") + } +``` +The above function is setting the state of `email` and using the UpdatePassword action from the `authenticationStore`. + + +Now, add the following html to the template under the forgot comment. + +```html + +
+

Forgot Password

+ +
+ +
+
+``` +The `forgotPassword` div will only be rendered when he is not on either `signup` or `login`. + +## UpdatePassword action + +```js + async UpdatePassword(email){ + const update = await account.createRecovery(email, 'http://localhost:5174/forgot') + } +``` + +The `UpdatePassword` action takes up the user email and a path for where the user will enter the new password. + +So, we have create a page, where we will take the query string params and the new password. Then, user can submit a request to update the password. + +**NOTE: The verification link sent to the user's email address is valid for 1 hour.** + +Now, let's create a new view/page `src/views/forgotPassword.vue` and copy the below code to it. + +```js + +``` +In the above script we are doing the following things: + +- Importing the `ref`, `computed`, `useRoute()`, `useRouter()`, and `useAuthenticationStore()` hooks from Vue.js. +- Creating a variable called `password` and initialize it with a ref. +- Creating a variable called `passwordAgain` and initialize it with a ref. +- Creating a method called `PasswordVerificationConfirm()`. This method should check if the `userID` and `secret` are present in the route query parameters. If they are, then the method should call the `UpdatePasswordConfirm()` method on the authentication store to update the user's password. + +```html + +``` +In the above code we are just taking password of the user and also we are confirming the password. Then, we are using the `PasswordVerificationConfirm` method to call `UpdatePasswordConfirm` action to submit a password update request to appwrite. + +## UpdatePasswordConfirm action + +```js +async UpdatePasswordConfirm(id,secret, password, passwordAgain){ + const confirResponse = await account.updateRecovery(id, secret, password, passwordAgain) + } +``` + +In the above `updateRecovery` request, we are sending the `userId`, `secret`, `password` and `passwordAgain` for updating the user password. diff --git a/src/routes/docs/tutorials/vue-auth/step-8/+page.markdoc b/src/routes/docs/tutorials/vue-auth/step-8/+page.markdoc new file mode 100644 index 0000000000..e75fbd2283 --- /dev/null +++ b/src/routes/docs/tutorials/vue-auth/step-8/+page.markdoc @@ -0,0 +1,88 @@ +--- +layout: tutorial +title: User verification +description: This page deals with user verification with Vue and Appwrite. +step: 8 +--- +# User Verfication {% #user-verification %} + +It is a good practice to verify whether a user is authentic or not. Appwrite provides us a way to verify the user using different methods such as + +- Phone verification +- email verification + +In this tutorial we are using email verification. + +## createVerification action + +This action uses `createVerification` method provided by appwrite to send a verification email to the user. The parameter that this method requires is a page where the user will be redirected to from the mail where the user can be verified. + +```js + async verifyUser(){ + const verfication = await account.createVerification('http://localhost:5174/verify') + }, +``` + +So, we have create a page, where we will verify the user. Then, user can submit a request to verify using `updateVerification` action. + +Now, let's create a new view/page `src/views/verify.vue` and copy the below code to it. + +```js + +``` +In the above script we are doing the following things: + +- Storing the `userId` and `secret` query parameters from query string present in the URL. +- Then, using `verificationConfirm` function to first check if `userID` and `secret` are present in the URL, then only use the `confirmVerification` action from the store to send a verified request to appwrite. +- After verification the user will be redirected to the `home page`. +- If the user if successfully verified, the dashboard will show `verified`, else it will show `verify user` + + +```html + +``` +In the above code we have a verify button which will trigger the `verificationConfirm` method and based on the `verificationDone` state the above text will be rendered. + +## confirmVerification action + +```js + async confirmVerification(id, secret){ + const confirResponse = await account.updateVerification(id, secret) + }, +``` +The above action uses the `updateVerification` method which appwrite provides to send a verified request to the appwrite. This method takes two parameters `userId` and `secret` that is present in the query string from the URL we got in the email. + diff --git a/src/routes/docs/tutorials/vue-auth/step-9/+page.markdoc b/src/routes/docs/tutorials/vue-auth/step-9/+page.markdoc new file mode 100644 index 0000000000..325c778a50 --- /dev/null +++ b/src/routes/docs/tutorials/vue-auth/step-9/+page.markdoc @@ -0,0 +1,33 @@ +--- +layout: tutorial +title: Protected routes +description: In this step we discuss about how routes are protected from being accessed when the user is not yet authenticated. +step: 9 +--- + +Route protection is a powerful feature of the Vue Router that allows you to restrict access to certain routes based on the user's authentication status. This can help you to create more secure and user-friendly applications. + +Let's visit the [index.js](https://gist.github.com/Vaibhav91one/02a2bc139625b985cc597c9fb0e7156e) file present in `src/router` to better understand how route protection is done. + +A simple step by step explanatin what we are doing is the following: + +- To protect a route, add the `requiresAuth` meta property to it. +- The `router.beforeEach` global navigation guard is called before every navigation. +- The `router.beforeEach` guard checks if the target route requires authentication and the user is not authenticated. +- If the target route requires authentication and the user is not authenticated, the navigation is canceled and the user is - redirected to the home page. +- Otherwise, the navigation is allowed to continue. + +We also want to restritct access to pages such as `login` and `forgot` when the user is logged in. To acheive that we are using `beforeMount` lifecycle hook. + +## beforeMount lifecycle hook + +```js + beforeMount(){ + const authenticationStore = useAuthenticationStore(); + const router = useRouter(); + if(authenticationStore.isAuthenticated){ + router.push({path: '/'}) + } + }, +``` +The above code just checks if the user is authenticated and is accessing `login` and `forgot` routes then, the user will be redirected to home page. Also, we have to use this lifecyle hook in both pages. \ No newline at end of file