diff --git a/Makefile b/Makefile
index 693ef9b2aaec37942c81b422312ea0b5f0751ac4..c483e0b12516af8ea4d80e3cf72efbf340d9a9a1 100644
--- a/Makefile
+++ b/Makefile
@@ -1,10 +1,19 @@
-.PHONY: build run
+.PHONY: build run run-dev unit e2e clean-docker
 
 build-docker:
 	docker build -t sparesti_frontend .
 
 run-docker:
-	docker run -p 5173:5173 sparesti_frontend
+	docker run --rm --name sparesti_frontend_container -p 5173:5173 sparesti_frontend
+
+clean-docker:
+	-docker stop sparesti_frontend_container
+	-docker rm sparesti_frontend_container
+
+run:
+	make build-docker
+	make clean-docker
+	make run-docker
 
 run-dev:
 	npm run dev
@@ -13,4 +22,4 @@ unit:
 	npm run test:unit
 
 e2e:
-	npm run test:e2e
\ No newline at end of file
+	npm run test:e2e
diff --git a/src/App.vue b/src/App.vue
index be78194d361500e3ee20a20eb0d46747b92c4a2a..6cd1e8f97ea32c80831eb29c2ff51bc86c2722ac 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -10,7 +10,8 @@ const showNavBar = computed(() => {
         route.path == '/' ||
         route.path == '/registrer' ||
         route.path == '/logginn' ||
-        route.path == '/forgotPassword'
+        route.path == '/forgotPassword' ||
+        route.path.startsWith('/konfigurasjon')
     )
 })
 </script>
diff --git a/src/assets/bioAuthFace.png b/src/assets/bioAuthFace.png
new file mode 100644
index 0000000000000000000000000000000000000000..b03bb5d400029bcbc6d7bea9f5657da31e3e63a0
Binary files /dev/null and b/src/assets/bioAuthFace.png differ
diff --git a/src/assets/bioAuthTouch.png b/src/assets/bioAuthTouch.png
new file mode 100644
index 0000000000000000000000000000000000000000..363627b9c744b2a8dcabc9d2a69485d055045f43
Binary files /dev/null and b/src/assets/bioAuthTouch.png differ
diff --git a/src/components/FormLogin.vue b/src/components/FormLogin.vue
index 731e224e722324e37fb36ffd35f3bfe4ee2344f7..363580072249635f9a74c6a5e1e9ec0eac6cbdc3 100644
--- a/src/components/FormLogin.vue
+++ b/src/components/FormLogin.vue
@@ -15,11 +15,18 @@ const emailRegex = /^[a-zA-Z0-9_+&*-]+(?:\.[a-zA-Z0-9_+&*-]+)*@(?:[a-zA-Z0-9-]+\
 const userStore = useUserStore()
 
 const isEmailValid = computed(() => emailRegex.test(resetEmail.value))
+const isSendingEmail = ref(false)
+const successMessage = ref<string>('')
+const modalErrorMessage = ref<string>('')
 
 const submitForm = () => {
     userStore.login(username.value, password.value)
 }
 
+const bioLogin = () => {
+    userStore.bioLogin(username.value)
+}
+
 const toggleShowPassword = () => {
     showPassword.value = !showPassword.value
 }
@@ -30,17 +37,36 @@ const openForgotPasswordModal = (event: MouseEvent) => {
 }
 
 const submitReset = async () => {
-    await axios.post('http://localhost:8080/forgotPassword/changePasswordRequest', {
-        email: resetEmail.value
-    })
-
-    resetEmail.value = ''
-    isModalOpen.value = false
+    isSendingEmail.value = true
+    modalErrorMessage.value = ''
+    successMessage.value = ''
+    try {
+        const response = await axios.post(
+            'http://localhost:8080/forgotPassword/changePasswordRequest',
+            {
+                email: resetEmail.value
+            }
+        )
+        successMessage.value =
+            'E-posten er sendt. Vennligst sjekk innboksen din for instrukser. OBS: E-posten kan havne i spam-mappen'
+        isSendingEmail.value = false
+        setTimeout(() => {
+            isModalOpen.value = false
+            successMessage.value = ''
+        }, 5000)
+    } catch (error) {
+        console.error(error)
+        modalErrorMessage.value = 'Noe gikk galt. Vennligst prøv igjen.'
+        isSendingEmail.value = false
+    }
 }
 
 const closeModal = () => {
-    resetEmail.value = ''
     isModalOpen.value = false
+    isSendingEmail.value = false
+    modalErrorMessage.value = ''
+    resetEmail.value = ''
+    successMessage.value = ''
 }
 
 watch(
@@ -95,36 +121,58 @@ watch(
                 Logg inn
             </button>
             <p>{{ errorMessage }}</p>
+            <button @click="bioLogin">biologin</button>
         </div>
     </div>
     <modal-component
         :title="'Glemt passord'"
         :message="'Vennligst skriv inn e-posten din for å endre passordet.'"
         :is-modal-open="isModalOpen"
-        @close="isModalOpen = false"
+        @close="closeModal"
     >
         <template v-slot:input>
-            <input
-                type="email"
-                v-model="resetEmail"
-                class="border border-gray-300 p-2 w-full mb-7"
-                placeholder="Skriv e-postadressen din her"
-            />
-        </template>
-        <template v-slot:buttons>
-            <button
-                :disabled="!isEmailValid"
-                @click="submitReset"
-                class="active-button font-bold py-2 px-4 w-1/2 border-2 disabled:border-transparent"
-            >
-                Send mail
-            </button>
-            <button
-                @click="closeModal"
-                class="active-button font-bold py-2 px-4 w-1/2 border-2 disabled:border-transparent"
-            >
-                Lukk
-            </button>
+            <div v-if="isSendingEmail" class="flex justify-center items-center">
+                <div
+                    class="p-3 animate-spin drop-shadow-2xl bg-gradient-to-r from-lime-500 from-30% to-green-600 to-90% md:w-18 md:h-20 h-20 w-20 aspect-square rounded-full"
+                >
+                    <div class="rounded-full h-full w-full bg-slate-100 background-blur-md"></div>
+                </div>
+            </div>
+            <div v-else-if="successMessage">
+                <p class="text-green-500 text-center">{{ successMessage }}</p>
+            </div>
+            <div v-else-if="modalErrorMessage">
+                <p class="text-red-500 text-center">{{ modalErrorMessage }}</p>
+                <button
+                    @click="closeModal"
+                    class="active-button font-bold py-2 px-4 w-1/2 mt-4 border-2 disabled:border-transparent"
+                >
+                    Lukk
+                </button>
+            </div>
+            <div v-else>
+                <input
+                    type="email"
+                    v-model="resetEmail"
+                    class="border border-gray-300 p-2 w-full mb-7"
+                    placeholder="Skriv e-postadressen din her"
+                />
+                <div class="flex gap-5 mt-4">
+                    <button
+                        :disabled="!isEmailValid"
+                        @click="submitReset"
+                        class="active-button font-bold py-2 px-4 w-1/2 border-2 disabled:border-transparent"
+                    >
+                        Send mail
+                    </button>
+                    <button
+                        @click="closeModal"
+                        class="active-button font-bold py-2 px-4 w-1/2 border-2 disabled:border-transparent"
+                    >
+                        Lukk
+                    </button>
+                </div>
+            </div>
         </template>
     </modal-component>
 </template>
diff --git a/src/components/ModalEditAvatar.vue b/src/components/ModalEditAvatar.vue
new file mode 100644
index 0000000000000000000000000000000000000000..5474b34e6b346b1206405db3681641638b9f74ff
--- /dev/null
+++ b/src/components/ModalEditAvatar.vue
@@ -0,0 +1,65 @@
+<template>
+    <button @click="openModal" class="text-nowrap">Endre avatar</button>
+    <div
+        v-if="isModalOpen"
+        class="fixed inset-0 bg-black bg-opacity-50 flex justify-center items-center z-50"
+    >
+        <div class="bg-white p-6 rounded-lg shadow-lg max-w-[80vh] h-auto w-full text-center">
+            <h2 class="title">Endre avatar</h2>
+            <div class="avatar-container flex flex-row justify-between items-center my-8">
+                <button @click="cycleArray('prev')">â—€</button>
+                <div class="flex flex-row items-center justify-around">
+                    <img :src="previousAvatar" alt="avatar" class="avatar h-16 w-16" />
+                    <div class="border-4 rounded-full border-green-600 p-8 mx-4">
+                        <img :src="currentAvatar" alt="avatar" class="avatar h-40 w-40" />
+                    </div>
+                    <img :src="nextAvatar" alt="avatar" class="avatar h-16 w-16" />
+                </div>
+                <button @click="cycleArray('next')">â–¶</button>
+            </div>
+            <button @click="saveAvatar" class="save-button">Lagre</button>
+        </div>
+    </div>
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue'
+
+const isModalOpen = ref(false)
+const avatars = [
+    'src/assets/coffee.png',
+    'src/assets/head.png',
+    'src/assets/nose.png',
+    'src/assets/penger.png',
+    'src/assets/pig.png'
+]
+let currentAvatarIndex = 0
+
+const openModal = () => {
+    isModalOpen.value = !isModalOpen.value
+}
+
+const nextAvatar = ref(avatars[(currentAvatarIndex + 1) % avatars.length])
+const currentAvatar = ref(avatars[currentAvatarIndex])
+const previousAvatar = ref(avatars[(currentAvatarIndex - 1 + avatars.length) % avatars.length])
+
+const cycleArray = (direction: string) => {
+    if (direction === 'prev') {
+        currentAvatarIndex = (currentAvatarIndex - 1 + avatars.length) % avatars.length
+        console.log(currentAvatarIndex)
+        currentAvatar.value = avatars[currentAvatarIndex]
+        previousAvatar.value = avatars[(currentAvatarIndex - 1 + avatars.length) % avatars.length]
+        nextAvatar.value = avatars[(currentAvatarIndex + 1) % avatars.length]
+    } else {
+        currentAvatarIndex = (currentAvatarIndex + 1) % avatars.length
+        currentAvatar.value = avatars[currentAvatarIndex]
+        previousAvatar.value = avatars[(currentAvatarIndex - 1 + avatars.length) % avatars.length]
+        nextAvatar.value = avatars[(currentAvatarIndex + 1) % avatars.length]
+    }
+}
+
+const saveAvatar = () => {
+    localStorage.setItem('avatar', currentAvatar.value)
+    isModalOpen.value = false
+}
+</script>
diff --git a/src/components/__tests__/NavBarTest.spec.ts b/src/components/__tests__/NavBarTest.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ea7c2814a609abe8a0e43501fa558e7f45f70dc5
--- /dev/null
+++ b/src/components/__tests__/NavBarTest.spec.ts
@@ -0,0 +1,101 @@
+import { mount, VueWrapper } from '@vue/test-utils'
+import NavBar from '@/components/NavBarComponent.vue'
+import router from '@/router'
+import { createPinia, setActivePinia } from 'pinia'
+import { beforeEach, describe, expect, it, vi } from 'vitest'
+
+vi.stubGlobal('scrollTo', vi.fn())
+
+describe('NavBar Routing', () => {
+    let wrapper: VueWrapper<any>
+
+    beforeEach(async () => {
+        const pinia = createPinia()
+        setActivePinia(pinia)
+
+        wrapper = mount(NavBar, {
+            global: {
+                plugins: [router, pinia]
+            }
+        })
+
+        await router.push('/')
+        await router.isReady()
+    })
+
+    it('renders without errors', () => {
+        expect(wrapper.exists()).toBe(true)
+    })
+
+    it('displays correct active route for home link on full screen', async () => {
+        global.innerWidth = 1200
+        await router.push('/hjem')
+        await router.isReady()
+
+        expect(wrapper.find('.router-link-exact-active').exists()).toBe(true)
+    })
+
+    it('displays correct active route for goals link on full screen', async () => {
+        global.innerWidth = 1200
+
+        await router.push('/sparemaal')
+        await router.isReady()
+        expect(wrapper.find('.router-link-exact-active').exists()).toBe(true)
+    })
+
+    it('displays correct active route for challenges link on full screen', async () => {
+        global.innerWidth = 1200
+
+        await router.push('/spareutfordringer')
+        await router.isReady()
+        expect(wrapper.find('.router-link-exact-active').exists()).toBe(true)
+    })
+
+    it('displays correct active route for profile link on full screen', async () => {
+        global.innerWidth = 1200
+
+        await router.push('/profil')
+        await router.isReady()
+        expect(wrapper.find('.router-link-exact-active').exists()).toBe(true)
+    })
+
+    it('displays correct active route for home link when the hamburger menu is open', async () => {
+        global.innerWidth = 1000
+        wrapper.vm.hamburgerOpen = true
+        await wrapper.vm.$nextTick()
+
+        await router.push('/hjem')
+        await router.isReady()
+        expect(wrapper.find('.router-link-exact-active').exists()).toBe(true)
+    })
+
+    it('displays correct active route for goals link when the hamburger menu is open', async () => {
+        global.innerWidth = 1000
+        wrapper.vm.hamburgerOpen = true
+        await wrapper.vm.$nextTick()
+
+        await router.push('/sparemaal')
+        await router.isReady()
+        expect(wrapper.find('.router-link-exact-active').exists()).toBe(true)
+    })
+
+    it('displays correct active route for challenges link when the hamburger menu is open', async () => {
+        global.innerWidth = 1000
+        wrapper.vm.hamburgerOpen = true
+        await wrapper.vm.$nextTick()
+
+        await router.push('/spareutfordringer')
+        await router.isReady()
+        expect(wrapper.find('.router-link-exact-active').exists()).toBe(true)
+    })
+
+    it('displays correct active route for profile link when the hamburger menu is open', async () => {
+        global.innerWidth = 1000
+        wrapper.vm.hamburgerOpen = true
+        await wrapper.vm.$nextTick()
+
+        await router.push('/profil')
+        await router.isReady()
+        expect(wrapper.find('.router-link-exact-active').exists()).toBe(true)
+    })
+})
diff --git a/src/components/__tests__/savingsPathTest.spec.ts b/src/components/__tests__/savingsPathTest.spec.ts
index af21d03c1b80df3ae2e90e8b92bd8e1782df544f..dea8650e2ad5d6ced6b43bfd45ce7bc012319875 100644
--- a/src/components/__tests__/savingsPathTest.spec.ts
+++ b/src/components/__tests__/savingsPathTest.spec.ts
@@ -1,4 +1,4 @@
-import { describe, expect, it, beforeEach, vi } from 'vitest'
+import { beforeEach, describe, expect, it, vi } from 'vitest'
 import { mount } from '@vue/test-utils'
 import { createPinia, setActivePinia } from 'pinia'
 import SavingsPath from '@/components/SavingsPath.vue'
diff --git a/src/router/index.ts b/src/router/index.ts
index 4ae0e9a4990bd24573cd01d10768f46825ef4c14..5f32e18fa4bcb61cf7ad48446e11dea346712c49 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -33,6 +33,11 @@ const router = createRouter({
             name: 'profile',
             component: () => import('@/views/ProfileView.vue')
         },
+        {
+            path: '/profil/rediger',
+            name: 'edit-profile',
+            component: () => import('@/views/EditProfileView.vue')
+        },
         {
             path: '/sparemaal',
             name: 'goals',
@@ -98,6 +103,11 @@ const router = createRouter({
             name: 'configurations5',
             component: () => import('@/views/ConfigSpendingItemsTotalAmountView.vue')
         },
+        {
+            path: '/konfigurasjonSteg6',
+            name: 'configurations6',
+            component: () => import('@/views/ConfigAccountNumberView.vue')
+        },
         {
             path: '/forsteSparemaal',
             name: 'firstSavingGoal',
@@ -112,6 +122,11 @@ const router = createRouter({
             path: '/:pathMatch(.*)*',
             name: 'not-found',
             component: () => import('@/views/NotFoundView.vue')
+        },
+        {
+            path: '/addAlternativeLogin',
+            name: 'addAlternativeLogin',
+            component: () => import('@/views/AddAlternativeLogin.vue')
         }
     ],
     scrollBehavior() {
diff --git a/src/stores/accountStore.ts b/src/stores/accountStore.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b80263eafa362581f6c2e235d544456ad887274c
--- /dev/null
+++ b/src/stores/accountStore.ts
@@ -0,0 +1,35 @@
+import { defineStore } from 'pinia'
+import { ref } from 'vue'
+import authInterceptor from '@/services/authInterceptor'
+import { AxiosError } from 'axios'
+
+export const useAccountStore = defineStore('account', {
+    state: () => ({
+        errorMessage: ref<string>('')
+    }),
+    actions: {
+        async postAccount(accountType: 'SAVING' | 'SPENDING', accNumber: string, balance: number) {
+            const payload = {
+                accountType,
+                accNumber,
+                balance
+            }
+
+            try {
+                const response = await authInterceptor.post('/accounts', payload)
+                console.log('Success:', response.data)
+            } catch (error) {
+                console.error('Error posting account:', error)
+                this.handleAxiosError(error)
+            }
+        },
+        handleAxiosError(error: any) {
+            const axiosError = error as AxiosError
+            if (axiosError.response && axiosError.response.data) {
+                const errorData = axiosError.response.data as { message: string }
+            } else {
+                this.errorMessage = 'An unexpected error occurred'
+            }
+        }
+    }
+})
diff --git a/src/stores/userConfigStore.ts b/src/stores/userConfigStore.ts
index c2fa6032c4fdfaf6f3e130d465d9cb33dde3c256..6f1e0f1ccbe25f90f463aed9ef97ec9b63ac4319 100644
--- a/src/stores/userConfigStore.ts
+++ b/src/stores/userConfigStore.ts
@@ -1,6 +1,7 @@
 import { defineStore } from 'pinia'
+import { ref } from 'vue'
 import authInterceptor from '@/services/authInterceptor'
-import axios from 'axios'
+import { AxiosError } from 'axios'
 
 export const useUserConfigStore = defineStore('userConfig', {
     state: () => ({
@@ -11,7 +12,8 @@ export const useUserConfigStore = defineStore('userConfig', {
             type: string
             specificAmount: number
             generalAmount: number
-        }[]
+        }[],
+        errorMessage: ref<string>('')
     }),
     actions: {
         setExperience(value: string) {
@@ -23,23 +25,28 @@ export const useUserConfigStore = defineStore('userConfig', {
         addChallengeTypeConfig(type: string, specificAmount: number, generalAmount: number) {
             this.challengeTypeConfigs.push({ type, specificAmount, generalAmount })
         },
-        async postUserConfig() {
+        postUserConfig() {
             const payload = {
                 experience: this.experience,
                 motivation: this.motivation,
                 challengeTypeConfigs: Array.from(this.challengeTypeConfigs)
             }
 
-            try {
-                const response = await authInterceptor.post('/config/challenge', payload)
-                console.log('Success:', response.data)
-            } catch (error: unknown) {
-                if (axios.isAxiosError(error)) {
-                    console.error('Axios error:', error.response?.data || error.message)
-                } else {
-                    console.error('An unexpected error occurred:', error)
-                }
-            }
+            authInterceptor
+                .post('/config/challenge', payload)
+                .then((response) => {
+                    console.log('Success:', response.data)
+                })
+                .catch((error) => {
+                    const axiosError = error as AxiosError
+                    if (axiosError.response && axiosError.response.data) {
+                        const errorData = axiosError.response.data as { message: string }
+                        this.errorMessage = errorData.message || 'An error occurred'
+                    } else {
+                        this.errorMessage = 'An unexpected error occurred'
+                    }
+                    console.error('Axios error:', this.errorMessage)
+                })
         }
     }
 })
diff --git a/src/stores/userStore.ts b/src/stores/userStore.ts
index fe31bd1a782e8feadd79d12e5fc3338ade7f9f93..ace14583f589aece97546bf3c653462a0fe3ee0e 100644
--- a/src/stores/userStore.ts
+++ b/src/stores/userStore.ts
@@ -4,6 +4,10 @@ import type { User } from '@/types/user'
 import router from '@/router'
 import type { AxiosError } from 'axios'
 import axios from 'axios'
+import type { CredentialRequestOptions } from '@/types/CredentialRequestOptions'
+import { base64urlToUint8array, initialCheckStatus, uint8arrayToBase64url } from '@/util'
+import authInterceptor from '@/services/authInterceptor'
+import type { CredentialCreationOptions } from '@/types/CredentialCreationOptions'
 
 export const useUserStore = defineStore('user', () => {
     const defaultUser: User = {
@@ -38,7 +42,7 @@ export const useUserStore = defineStore('user', () => {
                 user.value.lastname = lastname
                 user.value.username = username
 
-                router.push({ name: 'configurations1' })
+                router.push({ name: 'addAlternativeLogin' })
             })
             .catch((error) => {
                 const axiosError = error as AxiosError
@@ -76,10 +80,145 @@ export const useUserStore = defineStore('user', () => {
         router.push({ name: 'login' })
     }
 
+    const bioRegister = async () => {
+        try {
+            const response = await authInterceptor.post('/auth/bioRegistration')
+            initialCheckStatus(response)
+
+            const credentialCreateJson: CredentialCreationOptions = response.data
+
+            const credentialCreateOptions: CredentialCreationOptions = {
+                publicKey: {
+                    ...credentialCreateJson.publicKey,
+                    challenge: base64urlToUint8array(
+                        credentialCreateJson.publicKey.challenge as unknown as string
+                    ),
+                    user: {
+                        ...credentialCreateJson.publicKey.user,
+                        id: base64urlToUint8array(
+                            credentialCreateJson.publicKey.user.id as unknown as string
+                        )
+                    },
+                    excludeCredentials: credentialCreateJson.publicKey.excludeCredentials?.map(
+                        (credential) => ({
+                            ...credential,
+                            id: base64urlToUint8array(credential.id as unknown as string)
+                        })
+                    ),
+                    extensions: credentialCreateJson.publicKey.extensions
+                }
+            }
+
+            const publicKeyCredential = (await navigator.credentials.create(
+                credentialCreateOptions
+            )) as PublicKeyCredential
+
+            const publicKeyResponse =
+                publicKeyCredential.response as AuthenticatorAttestationResponse
+            const encodedResult = {
+                type: publicKeyCredential.type,
+                id: publicKeyCredential.id,
+                response: {
+                    attestationObject: uint8arrayToBase64url(publicKeyResponse.attestationObject),
+                    clientDataJSON: uint8arrayToBase64url(publicKeyResponse.clientDataJSON),
+                    transports: publicKeyResponse.getTransports?.() || []
+                },
+                clientExtensionResults: publicKeyCredential.getClientExtensionResults()
+            }
+
+            await authInterceptor
+                .post('/auth/finishBioRegistration', { credential: JSON.stringify(encodedResult) })
+                .then((response) => {
+                    router.push({ name: 'configurations1' })
+                })
+        } catch (error) {
+            router.push({ name: 'configurations1' })
+            console.error(error)
+        }
+    }
+
+    const bioLogin = async (username: string) => {
+        try {
+            const request = await axios.post(`http://localhost:8080/auth/bioLogin/${username}`)
+
+            initialCheckStatus(request)
+            console.log(request)
+
+            const credentialGetJson: CredentialRequestOptions = request.data
+            console.log(credentialGetJson)
+
+            const credentialGetOptions: CredentialRequestOptions = {
+                publicKey: {
+                    ...credentialGetJson.publicKey,
+                    allowCredentials:
+                        credentialGetJson.publicKey.allowCredentials &&
+                        credentialGetJson.publicKey.allowCredentials.map((credential) => ({
+                            ...credential,
+                            id: base64urlToUint8array(credential.id as unknown as string)
+                        })),
+                    challenge: base64urlToUint8array(
+                        credentialGetJson.publicKey.challenge as unknown as string
+                    ),
+                    extensions: credentialGetJson.publicKey.extensions
+                }
+            }
+
+            const publicKeyCredential = (await navigator.credentials.get(
+                credentialGetOptions
+            )) as PublicKeyCredential
+
+            // Extract response data based on the type of credential
+            const response = publicKeyCredential.response as AuthenticatorAssertionResponse
+
+            const encodedResult = {
+                type: publicKeyCredential.type,
+                id: publicKeyCredential.id,
+                response: {
+                    authenticatorData:
+                        response.authenticatorData &&
+                        uint8arrayToBase64url(response.authenticatorData),
+                    clientDataJSON:
+                        response.clientDataJSON && uint8arrayToBase64url(response.clientDataJSON),
+
+                    signature: response.signature && uint8arrayToBase64url(response.signature),
+                    userHandle: response.userHandle && uint8arrayToBase64url(response.userHandle)
+                },
+                clientExtensionResults: publicKeyCredential.getClientExtensionResults()
+            }
+            console.log(encodedResult)
+
+            await axios
+                .post(`http://localhost:8080/auth/finishBioLogin/${username}`, {
+                    credential: JSON.stringify(encodedResult)
+                })
+                .then((response) => {
+                    sessionStorage.setItem('accessToken', response.data.accessToken)
+                    localStorage.setItem('refreshToken', response.data.refreshToken)
+
+                    user.value.firstname = response.data.firstName
+                    user.value.lastname = response.data.lastName
+                    user.value.username = response.data.username
+
+                    router.push({ name: 'home' })
+                })
+                .catch((error) => {
+                    const axiosError = error as AxiosError
+                    errorMessage.value =
+                        (axiosError.response?.data as string) || 'An error occurred'
+                    console.log('hei :' + errorMessage.value)
+                })
+        } catch (error) {
+            // Handle errors
+            console.log(error)
+        }
+    }
+
     return {
         register,
         login,
         logout,
+        bioLogin,
+        bioRegister,
         errorMessage
     }
 })
diff --git a/src/types/CredentialCreationOptions.ts b/src/types/CredentialCreationOptions.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b6fdd7a76510ca4033a1c763a2ca9545797ab1b5
--- /dev/null
+++ b/src/types/CredentialCreationOptions.ts
@@ -0,0 +1,3 @@
+export interface CredentialCreationOptions {
+    publicKey: PublicKeyCredentialCreationOptions
+}
diff --git a/src/types/CredentialRequestOptions.ts b/src/types/CredentialRequestOptions.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4349a83cdfde9e60fe294adeef87dd4f1792087c
--- /dev/null
+++ b/src/types/CredentialRequestOptions.ts
@@ -0,0 +1,3 @@
+export interface CredentialRequestOptions {
+    publicKey: PublicKeyCredentialRequestOptions
+}
diff --git a/src/types/profile.ts b/src/types/profile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..392aee69615beff857dc324e85cc4f77ea1f7911
--- /dev/null
+++ b/src/types/profile.ts
@@ -0,0 +1,19 @@
+export interface Profile {
+    id: number
+    firstName: string
+    lastName: string
+    email: string
+    username: string
+    password?: string
+    spendingAccount: {
+        accNumber?: number
+        accountType?: string
+        balance?: number
+    }
+    savingAccount: {
+        accNumber?: number
+        accountType?: string
+        balance?: number
+    }
+    badges?: object[]
+}
diff --git a/src/util.ts b/src/util.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7f6cbfc818ab356135d6acf232024019ea4fafe0
--- /dev/null
+++ b/src/util.ts
@@ -0,0 +1,33 @@
+import base64js from 'base64-js'
+import { type AxiosResponse } from 'axios'
+
+export function base64urlToUint8array(base64Bytes: string): Uint8Array {
+    const padding = '===='.substring(0, (4 - (base64Bytes.length % 4)) % 4)
+    return base64js.toByteArray((base64Bytes + padding).replace(/\//g, '_').replace(/\+/g, '-'))
+}
+
+export function uint8arrayToBase64url(bytes: Uint8Array | ArrayBuffer | number[]): string {
+    if (bytes instanceof Uint8Array) {
+        return base64js
+            .fromByteArray(bytes)
+            .replace(/\+/g, '-')
+            .replace(/\//g, '_')
+            .replace(/=/g, '')
+    } else {
+        return uint8arrayToBase64url(new Uint8Array(bytes))
+    }
+}
+
+export function checkStatus(response: AxiosResponse<any>): AxiosResponse<any> | undefined {
+    if (response.status !== 200) {
+        console.log('an error occurred: ', response.statusText)
+        return undefined
+    } else {
+        return response
+    }
+}
+
+export function initialCheckStatus(response: AxiosResponse<any>): any {
+    checkStatus(response)
+    return response.data
+}
diff --git a/src/utilo.js b/src/utilo.js
new file mode 100644
index 0000000000000000000000000000000000000000..4125c85af520a7d429032a90f80c9a4611f07740
--- /dev/null
+++ b/src/utilo.js
@@ -0,0 +1,28 @@
+import base64js from 'base64-js'
+
+export function base64urlToUint8array(base64Bytes) {
+    const padding = '===='.substring(0, (4 - (base64Bytes.length % 4)) % 4)
+    return base64js.toByteArray((base64Bytes + padding).replace(/\//g, '_').replace(/\+/g, '-'))
+}
+export function uint8arrayToBase64url(bytes) {
+    if (bytes instanceof Uint8Array) {
+        return base64js
+            .fromByteArray(bytes)
+            .replace(/\+/g, '-')
+            .replace(/\//g, '_')
+            .replace(/=/g, '')
+    } else {
+        return uint8arrayToBase64url(new Uint8Array(bytes))
+    }
+}
+export function checkStatus(response) {
+    if (response.status !== 200) {
+        console.log('an error occurred: ', response.body)
+    } else {
+        return response
+    }
+}
+export function initialCheckStatus(response) {
+    checkStatus(response)
+    return response.data
+}
diff --git a/src/views/AddAlternativeLogin.vue b/src/views/AddAlternativeLogin.vue
new file mode 100644
index 0000000000000000000000000000000000000000..554f09f25915282f5675244784a6bb212457d036
--- /dev/null
+++ b/src/views/AddAlternativeLogin.vue
@@ -0,0 +1,48 @@
+<template>
+    <div class="alt-login-main">
+        <h1>Alternativ innlogging</h1>
+        <div class="img-div">
+            <img src="@/assets/bioAuthTouch.png" alt="bioAuthTouch" />
+            <img src="@/assets/bioAuthFace.png" alt="bioAuthFace" />
+        </div>
+        <h2>Vil du logge på med touch eller face id?</h2>
+        <div class="btn-div">
+            <button @click="router.push('konfigurasjonSteg1')">Senere</button>
+            <button @click="userStore.bioRegister()">OK</button>
+        </div>
+    </div>
+</template>
+<script setup lang="ts">
+import { useUserStore } from '@/stores/userStore'
+import router from '@/router'
+
+const userStore = useUserStore()
+</script>
+
+<style scoped>
+.alt-login-main {
+    max-width: 800px;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+.img-div {
+    display: flex;
+    justify-content: center;
+}
+
+img {
+    width: 30%;
+}
+
+img:first-child {
+    margin-right: 20px;
+}
+
+button {
+    margin: 10px;
+    width: 100px;
+    height: 40px;
+}
+</style>
diff --git a/src/views/CardTemplate.vue b/src/views/CardTemplate.vue
new file mode 100644
index 0000000000000000000000000000000000000000..6fa731e67776d9e923ea99427b9a23893f3de385
--- /dev/null
+++ b/src/views/CardTemplate.vue
@@ -0,0 +1,9 @@
+<script lang="ts" setup></script>
+
+<template>
+    <div class="border rounded-xl shadow-lg overflow-hidden">
+        <slot></slot>
+    </div>
+</template>
+
+<style scoped></style>
diff --git a/src/views/ConfigAccountNumberView.vue b/src/views/ConfigAccountNumberView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..652cf0d11ba68e92f47d8b6e14171faa565cf321
--- /dev/null
+++ b/src/views/ConfigAccountNumberView.vue
@@ -0,0 +1,114 @@
+<template>
+    <div
+        class="flex flex-col items-center justify-center min-h-screen md:pt-10 pt-4 pb-24 text-center"
+    >
+        <h1 class="mb-8 lg:mb-12 text-4xl font-bold">
+            Legg til kontonummer for sparekonto og brukskonto
+        </h1>
+        <div
+            class="flex flex-col items-center justify-center bg-white rounded-lg p-8 shadow-lg w-full md:w-[45%]"
+        >
+            <div class="w-full mb-4">
+                <label for="savingsAccount" class="block text-lg font-bold mb-2">Sparekonto</label>
+                <input
+                    id="savingsAccount"
+                    v-model="savingsAccount"
+                    @input="restrictToNumbers($event as InputEvent, 'savings')"
+                    @focus="removeFormatting('savings')"
+                    @blur="applyFormatting('savings')"
+                    class="w-full h-11 px-3 rounded-md text-xl focus:outline-none transition-colors border-2 border-gray-300"
+                    type="text"
+                    placeholder="Skriv inn ditt kontonummer..."
+                />
+            </div>
+            <div class="w-full mb-4">
+                <label for="spendingAccount" class="block text-lg font-bold mb-2">Brukskonto</label>
+                <input
+                    id="spendingAccount"
+                    v-model="spendingAccount"
+                    @input="restrictToNumbers($event as InputEvent, 'spending')"
+                    @focus="removeFormatting('spending')"
+                    @blur="applyFormatting('spending')"
+                    class="w-full h-11 px-3 rounded-md text-xl focus:outline-none transition-colors border-2 border-gray-300"
+                    type="text"
+                    placeholder="Skriv inn ditt kontonummer..."
+                />
+            </div>
+        </div>
+        <div class="absolute bottom-36 right-2">
+            <ContinueButtonComponent
+                @click="onButtonClick"
+                :disabled="!isFormValid"
+                class="px-10 py-3 text-2xl font-bold mb-4 mr-2"
+            ></ContinueButtonComponent>
+        </div>
+    </div>
+</template>
+
+<script setup lang="ts">
+import { computed, ref } from 'vue'
+import { useAccountStore } from '@/stores/accountStore'
+import ContinueButtonComponent from '@/components/ContinueButtonComponent.vue'
+import router from '@/router'
+
+const MAX_DIGITS = 11
+const accountStore = useAccountStore()
+
+const spendingAccount = ref('')
+const savingsAccount = ref('')
+
+const isFormValid = computed(() => {
+    return (
+        spendingAccount.value.replace(/\./g, '').length === MAX_DIGITS &&
+        savingsAccount.value.replace(/\./g, '').length === MAX_DIGITS
+    )
+})
+
+async function onButtonClick() {
+    const savingAccountNumber = savingsAccount.value.replace(/\./g, '')
+    const spendingAccountNumber = spendingAccount.value.replace(/\./g, '')
+
+    await accountStore.postAccount('SAVING', savingAccountNumber, 0)
+
+    await accountStore.postAccount('SPENDING', spendingAccountNumber, 0)
+
+    await router.push({ name: 'home' })
+}
+
+function restrictToNumbers(event: InputEvent, type: string) {
+    const inputValue = (event.target as HTMLInputElement)?.value
+    if (inputValue !== undefined) {
+        const sanitizedValue = inputValue.replace(/\D/g, '')
+        const truncatedValue = sanitizedValue.slice(0, MAX_DIGITS)
+        if (type === 'spending') {
+            spendingAccount.value = truncatedValue
+        } else {
+            savingsAccount.value = truncatedValue
+        }
+    }
+}
+
+function applyFormatting(type: string) {
+    if (type === 'spending') {
+        spendingAccount.value = formatAccount(spendingAccount.value)
+    } else {
+        savingsAccount.value = formatAccount(savingsAccount.value)
+    }
+}
+
+function removeFormatting(type: string) {
+    if (type === 'spending') {
+        spendingAccount.value = removeFormat(spendingAccount.value)
+    } else {
+        savingsAccount.value = removeFormat(savingsAccount.value)
+    }
+}
+
+function formatAccount(value: string): string {
+    return value.replace(/\D/g, '').replace(/^(.{4})(.{2})(.*)$/, '$1.$2.$3')
+}
+
+function removeFormat(value: string): string {
+    return value.replace(/\./g, '')
+}
+</script>
diff --git a/src/views/ConfigFamiliarWithSavingsView.vue b/src/views/ConfigFamiliarWithSavingsView.vue
index 3b3c8a4d1c6b6143ce1100e1e850a97a82e27988..ecbd66aa41acbc1aa29f2fd9405ec17cb0c00213 100644
--- a/src/views/ConfigFamiliarWithSavingsView.vue
+++ b/src/views/ConfigFamiliarWithSavingsView.vue
@@ -1,7 +1,9 @@
 <template>
     <div class="flex flex-col items-center justify-center min-h-screen px-4 text-center">
-        <h1 class="mb-16 text-4xl font-bold lg:mb-20">Hvor kjent er du med sparing fra før?</h1>
-        <div class="grid grid-cols-1 gap-14 mb-20 md:grid-cols-3">
+        <h1 class="mb-8 text-2xl font-bold sm:mb-16 sm:text-4xl">
+            Hvor kjent er du med sparing fra før?
+        </h1>
+        <div class="grid grid-cols-1 gap-8 mb-16 sm:gap-14 sm:mb-20 md:grid-cols-3">
             <div
                 :class="{
                     'border-[var(--green)] border-4': selectedOption === 'litt',
@@ -39,7 +41,7 @@
         <ContinueButtonComponent
             :disabled="selectedOption === null"
             @click="onButtonClick"
-            class="px-10 py-3 text-2xl self-end mb-4 mt-0"
+            class="px-10 py-3 text-2xl self-end"
         ></ContinueButtonComponent>
     </div>
 </template>
@@ -67,8 +69,6 @@ const selectOption = (option: string) => {
         case 'godt':
             experienceValue = 'VERY_HIGH'
             break
-        default:
-            experienceValue = 'VERY_LOW'
     }
 
     userConfigStore.setExperience(experienceValue)
@@ -76,7 +76,7 @@ const selectOption = (option: string) => {
 
 const onButtonClick = () => {
     if (selectedOption.value) {
-        router.push('/konfigurasjonSteg3')
+        router.push({ name: 'configurations3' })
     } else {
         console.error('No option selected')
     }
diff --git a/src/views/ConfigHabitChangeView.vue b/src/views/ConfigHabitChangeView.vue
index c686e26112e56a2d298e5e80d5cb59f0b8736f83..a1e8b37350d385d2c3f31db77f2b8c81b56b6e41 100644
--- a/src/views/ConfigHabitChangeView.vue
+++ b/src/views/ConfigHabitChangeView.vue
@@ -69,8 +69,6 @@ const selectOption = (option: string) => {
         case 'store':
             motivationValue = 'VERY_HIGH'
             break
-        default:
-            motivationValue = 'VERY_LOW'
     }
 
     userConfigStore.setMotivation(motivationValue)
@@ -78,7 +76,7 @@ const selectOption = (option: string) => {
 
 const onButtonClick = () => {
     if (selectedOption.value) {
-        router.push('/konfigurasjonSteg2')
+        router.push({ name: 'configurations2' })
     } else {
         console.error('No option selected')
     }
diff --git a/src/views/ConfigSpendingItemsAmountView.vue b/src/views/ConfigSpendingItemsAmountView.vue
index 625bf5335a0e50a61c1db4cb2a388d954430a73e..aa77feb1371de00b5a70dfe7815dd86e77f939c5 100644
--- a/src/views/ConfigSpendingItemsAmountView.vue
+++ b/src/views/ConfigSpendingItemsAmountView.vue
@@ -1,59 +1,74 @@
 <template>
     <div class="flex flex-col items-center justify-center min-h-screen px-4 text-center relative">
-        <h1 class="mb-8 lg:mb-12 text-4xl font-bold">Hvor mye bruker du per kjøp på ...</h1>
-        <div class="grid grid-cols-1 md:grid-cols-2 gap-8 mb-6">
-            <div class="flex flex-col items-center bg-white rounded-lg p-8 shadow-lg w-full">
+        <h1 class="mb-8 text-2xl font-bold sm:mb-16 sm:text-4xl">
+            Hvor mye bruker du per kjøp på ...
+        </h1>
+        <div class="w-full flex justify-center">
+            <div :class="[showSecondBox ? 'md:grid md:grid-cols-2 md:gap-4 sm:gap-8 mb-6' : '']">
                 <div
-                    v-for="(option, index) in options.slice(0, 6)"
-                    :key="`option-${index}`"
-                    class="w-full my-4"
+                    v-if="showFirstBox"
+                    class="flex flex-col items-center bg-white rounded-lg p-4 sm:p-8 shadow-lg"
+                    :class="showSecondBox ? 'w-full' : 'w-full md:w-1/2 mx-auto'"
+                    :style="{ minWidth: '400px', maxWidth: '400px' }"
                 >
-                    <div class="flex justify-between items-center">
-                        <p class="text-xl font-bold mr-4">{{ option.type }}</p>
-                        <div class="flex items-center w-2/3">
-                            <input
-                                v-model="amounts[index]"
-                                @input="filterAmount(index, $event)"
-                                class="h-11 px-3 rounded-md text-lg focus:outline-none border-2 w-full"
-                                :class="{
-                                    'border-gray-300': !amounts[index],
-                                    'border-[var(--green)]': amounts[index]
-                                }"
-                            />
-                            <p class="text-xl font-bold ml-2">kr</p>
+                    <div
+                        v-for="(option, index) in firstBoxOptions"
+                        :key="`first-option-${index}`"
+                        class="w-full my-4"
+                    >
+                        <div class="flex justify-between items-center">
+                            <p class="text-xl font-bold mr-4">{{ option.type }}</p>
+                            <div class="flex items-center w-2/3">
+                                <input
+                                    v-model="amounts[index]"
+                                    @input="filterAmount(index, $event)"
+                                    class="h-11 px-3 rounded-md text-lg focus:outline-none border-2 w-full"
+                                    :class="{
+                                        'border-gray-300': !amounts[index],
+                                        'border-[var(--green)]': amounts[index]
+                                    }"
+                                />
+                                <p class="text-xl font-bold ml-2">kr</p>
+                            </div>
                         </div>
                     </div>
                 </div>
-            </div>
-            <div class="flex flex-col items-center bg-white rounded-lg p-8 shadow-lg w-full">
                 <div
-                    v-for="(option, index) in options.slice(6, 12)"
-                    :key="`option-${index}`"
-                    class="w-full my-4"
+                    v-if="showSecondBox"
+                    class="flex flex-col items-center bg-white rounded-lg p-4 sm:p-8 shadow-lg"
+                    :class="showSecondBox ? 'w-full' : 'w-full md:w-1/2 mx-auto'"
+                    :style="{ minWidth: '400px', maxWidth: '400px' }"
                 >
-                    <div class="flex justify-between items-center">
-                        <p class="text-xl font-bold mr-4">{{ option.type }}</p>
-                        <div class="flex items-center w-2/3">
-                            <input
-                                v-model="amounts[index + 6]"
-                                @input="filterAmount(index + 6, $event)"
-                                class="h-11 px-3 rounded-md text-lg focus:outline-none border-2 w-full"
-                                :class="{
-                                    'border-gray-300': !amounts[index + 6],
-                                    'border-[var(--green)]': amounts[index + 6]
-                                }"
-                            />
-                            <p class="text-xl font-bold ml-2">kr</p>
+                    <div
+                        v-for="(option, index) in secondBoxOptions"
+                        :key="`second-option-${index}`"
+                        class="w-full my-4"
+                    >
+                        <div class="flex justify-between items-center">
+                            <p class="text-xl font-bold mr-4">{{ option.type }}</p>
+                            <div class="flex items-center w-2/3">
+                                <input
+                                    v-model="amounts[index + firstBoxOptions.length]"
+                                    @input="filterAmount(index + firstBoxOptions.length, $event)"
+                                    class="h-11 px-3 rounded-md text-lg focus:outline-none border-2 w-full"
+                                    :class="{
+                                        'border-gray-300': !amounts[index + firstBoxOptions.length],
+                                        'border-[var(--green)]':
+                                            amounts[index + firstBoxOptions.length]
+                                    }"
+                                />
+                                <p class="text-xl font-bold ml-2">kr</p>
+                            </div>
                         </div>
                     </div>
                 </div>
             </div>
         </div>
-        <div class="absolute bottom-36 right-4">
+        <div class="w-full text-right">
             <ContinueButtonComponent
                 @click="onButtonClick"
                 :disabled="!isAllAmountsFilled"
-                class="px-10 py-3 text-2xl font-bold mb-4"
+                class="px-10 py-3 text-2xl font-bold mb-20 mt-10 sm:mb-12 sm:mt-10"
             ></ContinueButtonComponent>
         </div>
     </div>
@@ -77,7 +92,7 @@ const onButtonClick = () => {
         userConfigStore.challengeTypeConfigs[index].specificAmount =
             parseFloat(amounts.value[index]) || 0
     })
-    router.push('/konfigurasjonSteg5')
+    router.push({ name: 'configurations5' })
 }
 
 const filterAmount = (index: number, event: Event) => {
@@ -86,4 +101,10 @@ const filterAmount = (index: number, event: Event) => {
     filteredValue = filteredValue.replace(/(,.*?),/g, '$1').replace(/,+/g, ',')
     amounts.value[index] = filteredValue
 }
+
+const firstBoxOptions = computed(() => options.value.slice(0, 6))
+const secondBoxOptions = computed(() => (options.value.length > 6 ? options.value.slice(6) : []))
+
+const showFirstBox = computed(() => options.value.length > 0)
+const showSecondBox = computed(() => options.value.length > 6)
 </script>
diff --git a/src/views/ConfigSpendingItemsTotalAmountView.vue b/src/views/ConfigSpendingItemsTotalAmountView.vue
index d24cb4f6c652780a935a810a34c0ef3b489a2588..098ba86faec729bcbc8450ad91268d7e65d82536 100644
--- a/src/views/ConfigSpendingItemsTotalAmountView.vue
+++ b/src/views/ConfigSpendingItemsTotalAmountView.vue
@@ -1,61 +1,74 @@
 <template>
-    <div class="flex flex-col items-center justify-center min-h-screen px-4 text-center">
-        <h1 class="mb-8 lg:mb-12 text-4xl font-bold">Hvor mye bruker du totalt per uke på ...</h1>
-        <div class="grid grid-cols-1 md:grid-cols-2 gap-8 mb-6">
-            <div class="flex flex-col items-center bg-white rounded-lg p-8 shadow-lg w-full">
+    <div class="flex flex-col items-center justify-center min-h-screen px-4 text-center relative">
+        <h1 class="mb-8 text-2xl font-bold sm:mb-16 sm:text-4xl">
+            Hvor mye bruker du per uke på ...
+        </h1>
+        <div class="w-full flex justify-center">
+            <div :class="[showSecondBox ? 'md:grid md:grid-cols-2 md:gap-4 sm:gap-8 mb-6' : '']">
                 <div
-                    v-for="(option, index) in options.slice(0, 6)"
-                    :key="`option-${index}`"
-                    class="w-full my-4"
+                    v-if="showFirstBox"
+                    class="flex flex-col items-center bg-white rounded-lg p-4 sm:p-8 shadow-lg"
+                    :class="showSecondBox ? 'w-full' : 'w-full md:w-1/2 mx-auto'"
+                    :style="{ minWidth: '400px', maxWidth: '400px' }"
                 >
-                    <div class="flex justify-between items-center">
-                        <p class="text-xl font-bold mr-4">{{ option.type }}</p>
-                        <div class="flex items-center w-2/3">
-                            <input
-                                type="text"
-                                v-model="amounts[index]"
-                                @input="($event) => filterAmount(index, $event)"
-                                class="h-11 px-3 rounded-md text-lg focus:outline-none border-2 w-full"
-                                :class="{
-                                    'border-gray-300': !amounts[index],
-                                    'border-[var(--green)]': amounts[index]
-                                }"
-                            />
-                            <p class="text-xl font-bold ml-2">kr</p>
+                    <div
+                        v-for="(option, index) in firstBoxOptions"
+                        :key="`first-option-${index}`"
+                        class="w-full my-4"
+                    >
+                        <div class="flex justify-between items-center">
+                            <p class="text-xl font-bold mr-4">{{ option.type }}</p>
+                            <div class="flex items-center w-2/3">
+                                <input
+                                    v-model="amounts[index]"
+                                    @input="filterAmount(index, $event)"
+                                    class="h-11 px-3 rounded-md text-lg focus:outline-none border-2 w-full"
+                                    :class="{
+                                        'border-gray-300': !amounts[index],
+                                        'border-[var(--green)]': amounts[index]
+                                    }"
+                                />
+                                <p class="text-xl font-bold ml-2">kr</p>
+                            </div>
                         </div>
                     </div>
                 </div>
-            </div>
-            <div class="flex flex-col items-center bg-white rounded-lg p-8 shadow-lg w-full">
                 <div
-                    v-for="(option, index) in options.slice(6, 12)"
-                    :key="`option-${index}`"
-                    class="w-full my-4"
+                    v-if="showSecondBox"
+                    class="flex flex-col items-center bg-white rounded-lg p-4 sm:p-8 shadow-lg"
+                    :class="showSecondBox ? 'w-full' : 'w-full md:w-1/2 mx-auto'"
+                    :style="{ minWidth: '400px', maxWidth: '400px' }"
                 >
-                    <div class="flex justify-between items-center">
-                        <p class="text-xl font-bold mr-4">{{ option.type }}</p>
-                        <div class="flex items-center w-2/3">
-                            <input
-                                type="text"
-                                v-model="amounts[index + 6]"
-                                @input="($event) => filterAmount(index + 6, $event)"
-                                class="h-11 px-3 rounded-md text-lg focus:outline-none border-2 w-full"
-                                :class="{
-                                    'border-gray-300': !amounts[index + 6],
-                                    'border-[var(--green)]': amounts[index + 6]
-                                }"
-                            />
-                            <p class="text-xl font-bold ml-2">kr</p>
+                    <div
+                        v-for="(option, index) in secondBoxOptions"
+                        :key="`second-option-${index}`"
+                        class="w-full my-4"
+                    >
+                        <div class="flex justify-between items-center">
+                            <p class="text-xl font-bold mr-4">{{ option.type }}</p>
+                            <div class="flex items-center w-2/3">
+                                <input
+                                    v-model="amounts[index + firstBoxOptions.length]"
+                                    @input="filterAmount(index + firstBoxOptions.length, $event)"
+                                    class="h-11 px-3 rounded-md text-lg focus:outline-none border-2 w-full"
+                                    :class="{
+                                        'border-gray-300': !amounts[index + firstBoxOptions.length],
+                                        'border-[var(--green)]':
+                                            amounts[index + firstBoxOptions.length]
+                                    }"
+                                />
+                                <p class="text-xl font-bold ml-2">kr</p>
+                            </div>
                         </div>
                     </div>
                 </div>
             </div>
         </div>
-        <div class="absolute bottom-24 right-4">
+        <div class="w-full text-right">
             <ContinueButtonComponent
                 @click="onButtonClick"
                 :disabled="!isAllAmountsFilled"
-                class="px-10 py-3 text-2xl font-bold mb-4"
+                class="px-10 py-3 text-2xl font-bold mb-20 mt-10 sm:mb-12 sm:mt-10"
             ></ContinueButtonComponent>
         </div>
     </div>
@@ -80,8 +93,8 @@ const onButtonClick = async () => {
             parseFloat(amounts.value[index]) || 0
     })
 
-    await userConfigStore.postUserConfig()
-    router.push('/hjem')
+    userConfigStore.postUserConfig()
+    await router.push({ name: 'configurations6' })
 }
 
 const filterAmount = (index: number, event: Event) => {
@@ -90,4 +103,10 @@ const filterAmount = (index: number, event: Event) => {
     filteredValue = filteredValue.replace(/(,.*?),/g, '$1').replace(/,+/g, ',')
     amounts.value[index] = filteredValue
 }
+
+const firstBoxOptions = computed(() => options.value.slice(0, 6))
+const secondBoxOptions = computed(() => (options.value.length > 6 ? options.value.slice(6) : []))
+
+const showFirstBox = computed(() => options.value.length > 0)
+const showSecondBox = computed(() => options.value.length > 6)
 </script>
diff --git a/src/views/ConfigSpendingItemsView.vue b/src/views/ConfigSpendingItemsView.vue
index 2226cb066b6cc1ed6a880672f6f3223bd33bbb5d..fbeda5f09011b4a3f8639d752c02eab917c32e14 100644
--- a/src/views/ConfigSpendingItemsView.vue
+++ b/src/views/ConfigSpendingItemsView.vue
@@ -1,9 +1,9 @@
 <template>
     <div class="flex flex-col items-center justify-center min-h-screen text-center">
-        <h1 class="mb-8 lg:mb-12 text-4xl font-bold">Hva bruker du mye penger på?</h1>
+        <h1 class="mb-8 text-2xl font-bold sm:mb-16 sm:text-4xl">Hva bruker du mye penger på?</h1>
         <div class="flex flex-wrap justify-center gap-8 mb-8">
             <div
-                class="flex flex-col items-center justify-center bg-white rounded-lg p-8 shadow-lg w-full md:w-[45%]"
+                class="flex flex-col items-center justify-center bg-white rounded-lg sm:p-8 shadow-lg sm:w-full md:w-[45%]"
             >
                 <div
                     v-for="buttonText in [
@@ -32,7 +32,7 @@
                 </div>
             </div>
             <div
-                class="flex flex-col items-center justify-center bg-white rounded-lg p-8 shadow-lg w-full md:w-[45%]"
+                class="flex flex-col items-center justify-center bg-white rounded-lg sm:p-8 shadow-lg sm:w-full md:w-[45%]"
             >
                 <div
                     v-for="(option, index) in customOptions"
@@ -41,18 +41,23 @@
                 >
                     <input
                         v-model="customOptions[index]"
-                        class="w-full md:w-64 h-11 px-3 rounded-md text-xl focus:outline-none transition-colors border-2 border-gray-300"
+                        :class="[
+                            'w-full md:w-64 h-11 px-3 rounded-md text-xl focus:outline-none transition-colors border-2',
+                            customOptions[index].trim() !== ''
+                                ? 'border-[var(--green)]'
+                                : 'border-gray-300'
+                        ]"
                         type="text"
                         :placeholder="'Annet ' + ' ...'"
                     />
                 </div>
             </div>
         </div>
-        <div class="w-full text-right mb-0 mt-0" style="position: relative; top: -92px; right: 8px">
+        <div class="w-full text-right">
             <ContinueButtonComponent
                 @click="onButtonClick"
                 :disabled="!isFormValid"
-                class="px-10 py-3 text-2xl font-bold mb-4 mr-2"
+                class="px-10 py-3 text-2xl font-bold mt-36 mr-4 sm:mb-12 sm:mt-10"
             ></ContinueButtonComponent>
         </div>
     </div>
@@ -68,24 +73,27 @@ const userConfigStore = useUserConfigStore()
 const selectedOptions = ref<string[]>([])
 const customOptions = ref(['', '', '', '', '', ''])
 
-const toggleOption = (option: string, isCustom: boolean = false) => {
-    if (!isCustom) {
-        const index = selectedOptions.value.indexOf(option)
-        if (index === -1) {
-            selectedOptions.value.push(option)
-        } else {
-            selectedOptions.value.splice(index, 1)
-        }
+const toggleOption = (option: string) => {
+    const index = selectedOptions.value.indexOf(option)
+    if (index === -1) {
+        selectedOptions.value.push(option)
+    } else {
+        selectedOptions.value.splice(index, 1)
     }
 }
 
 const isFormValid = computed(() => {
     const predefinedSelected = selectedOptions.value.length > 0
     const customFilled = customOptions.value.some((option) => option.trim() !== '')
-    return predefinedSelected || (customFilled && predefinedSelected)
+    return predefinedSelected || customFilled
 })
 
 const onButtonClick = () => {
+    if (!isFormValid.value) {
+        console.error('Form is not valid')
+        return
+    }
+
     const predefinedChallengeTypes = selectedOptions.value.map((option) => ({
         type: option,
         specificAmount: 0,
@@ -101,7 +109,6 @@ const onButtonClick = () => {
         }))
 
     userConfigStore.challengeTypeConfigs = [...predefinedChallengeTypes, ...customChallengeTypes]
-    console.log('Selected Challenge Types:', userConfigStore.challengeTypeConfigs)
-    router.push('/konfigurasjonSteg4')
+    router.push({ name: 'configurations4' })
 }
 </script>
diff --git a/src/views/EditProfileView.vue b/src/views/EditProfileView.vue
new file mode 100644
index 0000000000000000000000000000000000000000..82da35481c774c789baffd3264b4a36cbbe45614
--- /dev/null
+++ b/src/views/EditProfileView.vue
@@ -0,0 +1,254 @@
+<script lang="ts" setup>
+import authInterceptor from '@/services/authInterceptor'
+import { computed, onMounted, ref } from 'vue'
+import type { Profile } from '@/types/profile'
+import CardTemplate from '@/views/CardTemplate.vue'
+import router from '@/router'
+import ToolTip from '@/components/ToolTip.vue'
+import InteractiveSpare from '@/components/InteractiveSpare.vue'
+
+const profile = ref<Profile>({
+    id: 0,
+    firstName: '',
+    lastName: '',
+    email: '',
+    username: '',
+    password: '',
+    spendingAccount: {
+        accNumber: undefined,
+        balance: 0
+    },
+    savingAccount: {
+        accNumber: undefined,
+        balance: 0
+    }
+})
+
+const updatePassword = ref<boolean>(false)
+const confirmPassword = ref<string>('')
+const errorMessage = ref<string>('')
+
+const nameRegex = /^[æÆøØåÅa-zA-Z,.'-][æÆøØåÅa-zA-Z ,.'-]{1,29}$/
+const emailRegex =
+    /^[æÆøØåÅa-zA-Z0-9_+&*-]+(?:\.[æÆøØåÅa-zA-Z0-9_+&*-]+)*@(?:[æÆøØåÅa-zA-Z0-9-]+\.)+[æÆøØåÅa-zA-Z]{2,7}$/
+const usernameRegex = /^[ÆØÅæøåA-Za-z][æÆøØåÅA-Za-z0-9_]{2,29}$/
+const passwordRegex = /^(?=.*[0-9])(?=.*[a-zæøå])(?=.*[ÆØÅA-Z])(?=.*[@#$%^&+=!])(?=\S+$).{8,30}$/
+const accountNumberRegex = /^\d{11}$/
+
+const isFirstNameValid = computed(
+    () => nameRegex.test(profile.value.firstName) && profile.value.firstName
+)
+const isLastNameValid = computed(
+    () => nameRegex.test(profile.value.lastName) && profile.value.lastName
+)
+const isEmailValid = computed(() => emailRegex.test(profile.value.email))
+const isUsernameValid = computed(() => usernameRegex.test(profile.value.username))
+const isPasswordValid = computed(() => passwordRegex.test(profile.value.password || ''))
+const isSpendingAccountValid = computed(() =>
+    accountNumberRegex.test(profile.value.spendingAccount.accNumber?.toString() || '')
+)
+const isSavingAccountValid = computed(() =>
+    accountNumberRegex.test(profile.value.savingAccount.accNumber?.toString() || '')
+)
+
+const isFormInvalid = computed(
+    () =>
+        [
+            isFirstNameValid,
+            isLastNameValid,
+            isEmailValid,
+            isUsernameValid,
+            isSpendingAccountValid,
+            isSavingAccountValid
+        ].some((v) => !v.value) ||
+        (updatePassword.value
+            ? profile.value.password !== confirmPassword.value || profile.value.password === ''
+            : false)
+)
+
+onMounted(async () => {
+    await authInterceptor('/profile')
+        .then((response) => {
+            profile.value = response.data
+            console.log(profile.value)
+        })
+        .catch((error) => {
+            return console.log(error)
+        })
+})
+
+const saveChanges = async () => {
+    if (isFormInvalid.value) {
+        errorMessage.value = 'Vennligst fyll ut alle feltene riktig'
+        return
+    }
+
+    if (!updatePassword.value) {
+        delete profile.value.password
+    }
+
+    await authInterceptor
+        .put('/profile', profile.value)
+        .then(() => {
+            router.back()
+        })
+        .catch((error) => {
+            errorMessage.value = error.response.data.message
+        })
+}
+</script>
+
+<template>
+    <div class="w-full flex px-10 justify-center">
+        <div class="flex flex-row flex-wrap justify-center w-full max-w-screen-xl gap-20">
+            <div class="flex flex-col max-w-96 w-full gap-5">
+                <h1>Rediger profil</h1>
+                <div class="w-full flex flex-row gap-5 justify-between justify-items-end">
+                    <div class="flex flex-col justify-center">
+                        <button class="h-min bg-transparent text-4xl" v-text="'⬅️'" />
+                    </div>
+                    <div class="w-32 h-32 border-black border-2 rounded-full shrink-0" />
+                    <div class="flex flex-col justify-center">
+                        <button class="h-min bg-transparent text-4xl" v-text="'➡️'" />
+                    </div>
+                </div>
+
+                <div class="flex flex-col">
+                    <div class="flex flex-row justify-between mx-4">
+                        <p>Fornavn*</p>
+                        <ToolTip
+                            :message="'Must include only letters, spaces, commas, apostrophes, periods, and hyphens. 1-30 characters long'"
+                        />
+                    </div>
+                    <input
+                        v-model="profile.firstName"
+                        :class="{ 'bg-green-200': isFirstNameValid }"
+                        name="firstname"
+                        placeholder="Skriv inn fornavn"
+                        type="text"
+                    />
+                </div>
+                <div class="flex flex-col">
+                    <div class="flex flex-row justify-between mx-4">
+                        <p>Etternavn*</p>
+                        <ToolTip
+                            :message="'Must include only letters, spaces, commas, apostrophes, periods, and hyphens. 1-30 characters long'"
+                        />
+                    </div>
+                    <input
+                        v-model="profile.lastName"
+                        :class="{ 'bg-green-200': isLastNameValid }"
+                        name="lastname"
+                        placeholder="Skriv inn etternavn"
+                        type="text"
+                    />
+                </div>
+                <div class="flex flex-col">
+                    <div class="flex flex-row justify-between mx-4">
+                        <p>E-post*</p>
+                        <ToolTip
+                            :message="'Valid email: Starts with Norwegian letters, numbers, or special characters. Includes \@\ followed by a domain. Ends with 2-7 letters.'"
+                        />
+                    </div>
+                    <input
+                        v-model="profile.email"
+                        :class="{ 'bg-green-200': isEmailValid }"
+                        name="email"
+                        placeholder="Skriv inn e-post"
+                        type="text"
+                    />
+                </div>
+                <div class="flex flex-col">
+                    <div class="flex flex-row justify-between mx-4">
+                        <p>Brukernavn*</p>
+                        <ToolTip
+                            :message="'Must start with a letter and can include numbers and underscores. 3-30 characters long.'"
+                        />
+                    </div>
+                    <input
+                        v-model="profile.username"
+                        :class="{ 'bg-green-200': isUsernameValid }"
+                        name="username"
+                        placeholder="Skriv inn brukernavn"
+                        type="text"
+                    />
+                </div>
+                <div class="flex flex-col">
+                    <div class="flex flex-row justify-between mx-4">
+                        <div class="flex flex-row gap-2">
+                            <p>Endre passord</p>
+                            <input v-model="updatePassword" type="checkbox" />
+                        </div>
+                        <ToolTip
+                            v-if="updatePassword"
+                            :message="'Must be at least 8 characters, including at least one number, one lowercase letter, one uppercase letter, one special character (@#$%^&+=!), and no spaces.'"
+                        />
+                    </div>
+                    <input
+                        v-if="updatePassword"
+                        v-model="profile.password"
+                        :class="{ 'bg-green-200': isPasswordValid }"
+                        class="w-full"
+                        name="password"
+                        placeholder="Skriv inn passord"
+                    />
+                    <input
+                        v-if="updatePassword"
+                        v-model="confirmPassword"
+                        :class="{ 'bg-red-200': profile.password !== confirmPassword }"
+                        class="mt-2"
+                        name="confirm"
+                        placeholder="Bekreft passord"
+                        type="password"
+                    />
+                </div>
+
+                <p v-if="errorMessage" class="text-red-500" v-text="errorMessage" />
+            </div>
+            <div class="flex flex-col justify-end max-w-96 w-full gap-5">
+                <InteractiveSpare
+                    :png-size="10"
+                    :speech="['Her kan du endre på profilen din!']"
+                    direction="left"
+                />
+
+                <CardTemplate>
+                    <div class="bg-red-300">
+                        <p class="font-bold mx-3" v-text="'Brukskonto'" />
+                    </div>
+                    <input
+                        v-model="profile.spendingAccount.accNumber"
+                        :class="{ 'bg-green-200': isSpendingAccountValid }"
+                        class="border-2 rounded-none rounded-b-xl w-full"
+                        placeholder="Kontonummer"
+                        type="number"
+                    />
+                </CardTemplate>
+
+                <CardTemplate>
+                    <div class="bg-red-300">
+                        <p class="font-bold mx-3" v-text="'Sparekonto'" />
+                    </div>
+                    <input
+                        v-model="profile.savingAccount.accNumber"
+                        :class="{ 'bg-green-200': isSavingAccountValid }"
+                        class="border-2 rounded-none rounded-b-xl w-full"
+                        placeholder="Kontonummer"
+                        type="number"
+                    />
+                </CardTemplate>
+
+                <div class="flex flex-row justify-between">
+                    <button class="bg-button-other" @click="router.back()" v-text="'Avbryt'" />
+                    <button
+                        :disabled="isFormInvalid"
+                        @click="saveChanges"
+                        v-text="'Lagre endringer'"
+                    />
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+
+<style scoped></style>
diff --git a/src/views/ProfileView.vue b/src/views/ProfileView.vue
index 255824275b207f62108888007491f385b3b8e1d2..436e522c7c815ad6cb5725724b76a8f76779d75d 100644
--- a/src/views/ProfileView.vue
+++ b/src/views/ProfileView.vue
@@ -1,21 +1,115 @@
 <script lang="ts" setup>
 import authInterceptor from '@/services/authInterceptor'
-import { onMounted } from 'vue'
+import { computed, onMounted, ref } from 'vue'
+import type { Profile } from '@/types/profile'
+import CardTemplate from '@/views/CardTemplate.vue'
+import InteractiveSpare from '@/components/InteractiveSpare.vue'
+import type { Challenge } from '@/types/challenge'
+import type { Goal } from '@/types/goal'
+import CardGoal from '@/components/CardGoal.vue'
+import router from '@/router'
+
+const profile = ref<Profile>()
+const completedGoals = ref<Goal[]>([])
+const completedChallenges = ref<Challenge[]>([])
 
 onMounted(async () => {
-    await authInterceptor
-        .get('/config')
+    await authInterceptor('/profile')
+        .then((response) => {
+            profile.value = response.data
+            console.log(profile.value)
+        })
+        .catch((error) => {
+            return console.log(error)
+        })
+
+    await authInterceptor(`/goals/completed?page=0&size=3`)
         .then((response) => {
-            console.log(response.data)
+            completedGoals.value = response.data.content
         })
         .catch((error) => {
-            console.log(error)
+            return console.log(error)
         })
+
+    await authInterceptor('/challenges/completed?page=0&size=3')
+        .then((response) => {
+            completedChallenges.value = response.data.content
+        })
+        .catch((error) => {
+            return console.log(error)
+        })
+})
+
+const welcome = computed(() => {
+    return [`Velkommen, ${profile.value?.firstName} ${profile.value?.lastName} !`]
 })
 </script>
 
 <template>
-    <h1>Din profil</h1>
+    <div class="w-full flex px-10 justify-center">
+        <div class="flex flex-row flex-wrap justify-center w-full max-w-screen-xl gap-20">
+            <div class="flex flex-col max-w-96 w-full gap-5">
+                <h1>Profile</h1>
+                <div class="flex flex-row gap-5">
+                    <div class="w-32 h-32 border-black border-2 rounded-full shrink-0" />
+                    <div class="w-full flex flex-col justify-between">
+                        <h3 class="font-thin my-0">{{ profile?.username }}</h3>
+                        <h3 class="font-thin my-0">
+                            {{ profile?.firstName + ' ' + profile?.lastName }}
+                        </h3>
+                        <h3 class="font-thin my-0">{{ profile?.email }}</h3>
+                    </div>
+                </div>
+
+                <h3 class="font-bold" v-text="'Du har spart ' + '< totalSaved >' + 'kr'" />
+
+                <CardTemplate>
+                    <div class="bg-red-300">
+                        <p class="font-bold mx-3" v-text="'Brukskonto'" />
+                    </div>
+                    <p
+                        class="mx-3"
+                        v-text="profile?.spendingAccount.accNumber || 'Ingen brukskonto oppkoblet'"
+                    />
+                </CardTemplate>
+
+                <CardTemplate>
+                    <div class="bg-red-300">
+                        <p class="font-bold mx-3" v-text="'Sparekonto'" />
+                    </div>
+                    <p
+                        class="mx-3"
+                        v-text="profile?.savingAccount.accNumber || 'Ingen sparekonto oppkoblet'"
+                    />
+                </CardTemplate>
+
+                <button @click="router.push({ name: 'edit-profile' })" v-text="'Rediger bruker'" />
+            </div>
+
+            <div class="flex flex-col">
+                <InteractiveSpare :png-size="10" :speech="welcome" direction="left" />
+                <div class="flex flex-row justify-between mx-4">
+                    <p class="font-bold">Fullførte sparemål</p>
+                    <a class="hover:p-0 cursor-pointer" v-text="'Se alle'" />
+                </div>
+                <CardTemplate class="p-4 flex flex-row flex-wrap justify-center gap-2 mb-4 mt-2">
+                    <CardGoal v-for="goal in completedGoals" :key="goal.id" :goal-instance="goal" />
+                </CardTemplate>
+
+                <div class="flex flex-row justify-between mx-4">
+                    <p class="font-bold">Fullførte utfordringer</p>
+                    <a class="hover:p-0 cursor-pointer" v-text="'Se alle'" />
+                </div>
+                <CardTemplate class="p-4 flex flex-row flex-wrap justify-center gap-2 mb-4 mt-2">
+                    <CardGoal
+                        v-for="challenge in completedChallenges"
+                        :key="challenge.id"
+                        :goal-instance="challenge"
+                    />
+                </CardTemplate>
+            </div>
+        </div>
+    </div>
 </template>
 
 <style scoped></style>
diff --git a/src/views/ResetPasswordView.vue b/src/views/ResetPasswordView.vue
index 6eacf26404a862292a847529cf8486b8c33d9d0e..cce6427a6d0dbea6bd91a5dfb1905a439374ca56 100644
--- a/src/views/ResetPasswordView.vue
+++ b/src/views/ResetPasswordView.vue
@@ -91,16 +91,11 @@ const canResetPassword = computed(() => {
 const resetPassword = async () => {
     isModalOpen.value = true
 
-    const resetPasswordDTO = {
-        resetID: resetID.value,
-        userID: userID.value,
-        newPassword: newPassword.value
-    }
     try {
         await axios.post('http://localhost:8080/forgotPassword/resetPassword', {
-            method: 'POST',
-            headers: { 'Content-Type': 'application/json' },
-            body: JSON.stringify(resetPasswordDTO)
+            resetID: resetID.value,
+            userID: userID.value,
+            newPassword: newPassword.value
         })
     } catch (error) {
         const err = error as Error