BootCamp Tutorial 2: Vue.js Fundamentals: Setting Up Authentication & Routing
π Learning Objectives
Now that youβve learned the basics of Vue.js authentication with Login & Signup, in this tutorial, we will review: β
Vue Project Structure
β
Configuring Vue Router for Navigation
β
Handling Authentication (Login & Signup) Using API
β
Storing JWT Token Locally
By the end of this tutorial, youβll have a working authentication system with routing in Vue.js.
1οΈβ£ Setting Up Vue Project Structure
A typical Vue.js project contains the following key files:
1
2
3
4
5
6
7
8
9
10
11
12
π vue-auth-project/
βββ π src/
β βββ π components/ # Reusable components (optional)
β βββ π views/ # Main pages (Login, Signup, Home)
β βββ π router/ # Vue Router Configuration
β β βββ index.js
β βββ π assets/ # Static assets (images, CSS)
β βββ App.vue # Root Vue component
β βββ main.js # Main entry file
βββ index.html # Base HTML file
βββ vite.config.js # Vite configuration (for Vue)
βββ package.json # Dependencies & scripts
2οΈβ£ Configuring Vue.js with Routing
π main.js
- Registering Vue App & Router
π src/main.js
1
2
3
4
5
6
7
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
const app = createApp(App);
app.use(router);
app.mount('#app');
β This initializes the Vue application and registers the router.
π App.vue
- Root Component
π src/App.vue
1
2
3
<template>
<RouterView />
</template>
β
<RouterView />
is a placeholder for dynamically loaded pages.
- It loads different pages based on the URL path.
π index.html
- The Main Entry Point
π public/index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>
β
Vue renders the app inside <div id="app"></div>
.
3οΈβ£ Setting Up Vue Router
π router/index.js
- Defining Routes
π src/router/index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { createRouter, createWebHistory } from 'vue-router';
import Home from '../views/HomeView.vue';
import Login from '../views/LoginView.vue';
import Signup from '../views/SignupView.vue';
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{ path: '/', name: 'home', component: Home },
{ path: '/login', name: 'login', component: Login },
{ path: '/signup', name: 'signup', component: Signup }
]
});
export default router;
β Key Features:
- Uses
createWebHistory()
for clean URLs (/login
instead of#/login
). - Defines routes (
/
,/login
,/signup
). - Each route loads a view component dynamically.
4οΈβ£ Creating Authentication Pages
π₯ Login Page
π src/views/LoginView.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<template>
<h2>Login</h2>
<form @submit.prevent="loginUser">
<div>
<label for="email">Email</label>
<input type="email" id="email" v-model="email" required />
</div>
<div>
<label for="password">Password</label>
<input type="password" id="password" v-model="password" required />
</div>
<button type="submit">Login</button>
</form>
<div>
<RouterLink to="/">Home</RouterLink> |
<RouterLink to="/signup">Signup</RouterLink>
</div>
</template>
<script>
export default {
data() {
return {
email: "",
password: "",
};
},
methods: {
async loginUser() {
if (!this.email || !this.password) {
alert("All fields are required!");
return;
}
try {
const response = await fetch("http://localhost:5000/login", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ email: this.email, password: this.password })
});
const res = await response.json();
if (res.token) {
localStorage.setItem("token", res.token);
alert("Login successful!");
this.$router.push("/"); // Redirect to Home
} else {
alert("Invalid login credentials.");
}
} catch (error) {
alert("Login failed! Please try again.");
}
}
}
};
</script>
β Key Features:
- Form submission using
@submit.prevent
- Stores JWT token in
localStorage
- Redirects user after login (
this.$router.push("/")
)
π₯ Signup Page
π src/views/SignupView.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<template>
<h2>Signup</h2>
<form @submit.prevent="signupUser">
<div>
<label for="username">Username</label>
<input type="text" id="username" v-model="username" required />
</div>
<div>
<label for="email">Email</label>
<input type="email" id="email" v-model="email" required />
</div>
<div>
<label for="password">Password</label>
<input type="password" id="password" v-model="password" required />
</div>
<button type="submit">Sign Up</button>
</form>
<div>
<RouterLink to="/">Home</RouterLink> |
<RouterLink to="/login">Login</RouterLink>
</div>
</template>
<script>
import axios from "axios";
export default {
data() {
return {
username: "",
email: "",
password: "",
};
},
methods: {
async signupUser() {
if (!this.username || !this.email || !this.password) {
alert("All fields are required!");
return;
}
try {
const response = await axios.post("http://localhost:5000/signup", {
username: this.username,
email: this.email,
password: this.password
});
alert(response.data.message || "Signup successful");
this.$router.push("/login"); // Redirect to Login
} catch (error) {
alert(error.response?.data.message || "Signup failed!");
}
}
}
};
</script>
β Key Features:
- Uses
axios
for API requests - Handles signup validation
- Redirects user to login page on success
5οΈβ£ Adding Navigation
π src/components/Navbar.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
<nav>
<RouterLink to="/">Home</RouterLink> |
<RouterLink v-if="!isAuthenticated" to="/login">Login</RouterLink> |
<RouterLink v-if="!isAuthenticated" to="/signup">Signup</RouterLink> |
<button v-if="isAuthenticated" @click="logout">Logout</button>
</nav>
</template>
<script>
export default {
computed: {
isAuthenticated() {
return !!localStorage.getItem("token");
}
},
methods: {
logout() {
localStorage.removeItem("token");
this.$router.push("/login");
}
}
};
</script>
β This creates a dynamic navbar that:
- Shows Login/Signup if the user is not logged in
- Shows Logout if the user is logged in
- Clears token & redirects on logout
π Next: