Router
File: apps/frontend/src/router/index.ts
The router uses createWebHashHistory (hash-based URLs, e.g. /#/dashboard). This avoids the need for server-side catch-all redirects when deployed as a static SPA on AWS Amplify.
Route Guard
router.beforeEach
Runs before every navigation:
router.beforeEach((to, from, next) => {
NProgress.start()
if (to.meta.requiresAuth && !authStore.isAuthenticated) {
next({ name: 'signin' })
} else {
next()
}
})- Starts the NProgress loading bar
- Checks
meta.requiresAuthon the target route - Reads
authStore.isAuthenticated(from persisted Pinia state) - Redirects unauthenticated users to
/signin
router.afterEach
router.afterEach((to) => {
NProgress.done()
document.title = to.meta.title ?? 'IoT Monitoring'
})Route Definitions
Public Routes
Rendered inside the SignUpAndSignIn layout (centered card, no sidebar):
| Path | Name | Component | Description |
|---|---|---|---|
/signup | signup | views/signup.vue | Registration form |
/signin | signin | views/signin.vue | Login form |
/404 | 404 | views/newPages/404.vue | Not found page |
User Routes
Rendered inside the Home layout (sidebar + header). All have meta: { requiresAuth: true }.
| Path | Name | Component |
|---|---|---|
/dashboard | dashboard | views/dashboard.vue |
/live-alerts | liveAlerts | views/live-alerts.vue |
/current-conditions | currentConditions | views/current-conditions.vue |
/reports | reports | views/reports.vue |
/profile | profile | views/profile.vue |
/settings | settings | views/settings.vue |
/storage-settings | storage-settings | views/storage-settings.vue |
/notification-settings | notification-settings | views/notification-settings.vue |
/recipient-settings | recipient-settings | views/recipient-settings.vue |
/device-settings | device-settings | views/device-settings.vue |
Admin Routes
Also rendered inside the Home layout, prefixed with /admin. All have meta: { requiresAuth: true }.
| Path | Name | Component |
|---|---|---|
/admin/devices | devices | views/admin/devices.vue |
/admin/sensor-data | sensorData | views/admin/sensorData.vue |
/admin/diagnostic-data | diagnosticData | views/admin/diagnosticData.vue |
/admin/users | users | views/admin/users.vue |
/admin/device-logs | deviceLogs | views/admin/deviceLogs.vue |
/admin/raw-sensor-data | rawSensorData | views/admin/rawSensorData.vue |
Lazy Loading
All routes are lazy-loaded via dynamic imports with webpack chunk names:
{
path: '/dashboard',
name: 'dashboard',
component: () => import(/* webpackChunkName: "dashboard" */ '@/views/dashboard.vue'),
meta: { requiresAuth: true, title: 'Dashboard' }
}This splits each view into a separate JS chunk and only loads the code when the route is first visited.
Layouts
SignUpAndSignIn layout
File: views/signUpAndSignIn.vue
Renders a centered card with a branded header (components/signUpAndSignInHeader.vue). Used for authentication pages.
Home layout
File: views/home.vue
The main authenticated shell:
- Sidebar (
components/sidebar.vue) — collapsible navigation - Header (
components/header.vue) — user menu, notifications - Tab bar (
components/tabs.vue) — open page tabs <router-view>— current page content
Navigation Redirect
If a user visits / (root), they are redirected to /dashboard (or /signin if not authenticated). A catch-all /:pathMatch(.*)* route redirects unmatched paths to /404.
