Last Updated: October 2025
Version: 2.0.0 (After Refactoring)
- Overview
- URL Structure
- Session Management
- Student Routes
- Admin Routes
- Authentication Flow
- Migration Guide
Aplikasi We Will Shine menggunakan struktur routing yang intuitif dan aman dengan session-based authentication.
✅ Clean URLs - Tidak ada parameter code di URL
✅ Session-based Auth - Student code disimpan di sessionStorage
✅ Intuitive Paths - /app untuk siswa, /dashboard untuk admin
✅ Secure - Session hilang saat tab ditutup
http://localhost:5173/
├── / ← Landing page
├── /unlock ← Student login dengan code
├── /login ← Admin login ⭐
│
├── /app/ ← Student portal (authenticated)
│ ├── /app/ ← Home siswa
│ ├── /app/careers ← Eksplorasi karir
│ ├── /app/careers/:id ← Detail karir
│ ├── /app/quiz ← Quiz kepribadian
│ ├── /app/achievements ← Pencapaian siswa
│ ├── /app/dreams ← Halaman impian
│ ├── /app/analytics ← Analytics siswa
│ └── /app/ai-mentor ← AI Mentor chat
│
└── /dashboard/ ← Admin panel (authenticated)
├── /dashboard/ ← Admin home
├── /dashboard/overview ← Student overview
├── /dashboard/students ← Manage students
├── /dashboard/analytics ← Platform analytics
├── /dashboard/settings ← App settings
├── /dashboard/qr-generator ← Generate QR codes
└── /dashboard/migrate-codes ← Migrate student codes
https://username.github.io/we-will-shine/
├── /we-will-shine/
├── /we-will-shine/unlock ← Student login
├── /we-will-shine/login ← Admin login ⭐
│
├── /we-will-shine/app/ ← Student portal
│ └── ... (same as development)
│
└── /we-will-shine/dashboard/ ← Admin panel
└── ... (same as development)
File: src/lib/stores/session.ts
// Store student code (with 7-day expiry)
setStudentCode('NAYIKUVIIIC2025');
// Get student code (auto-checks expiry)
const code = getStudentCode(); // Returns: 'NAYIKUVIIIC2025' or ''
// Check if logged in
const isLoggedIn = isStudentLoggedIn(); // Returns: true/false
// Clear session (logout)
clearStudentCode();
// Get session info (optional, for debugging)
const sessionInfo = getSessionInfo();
// Returns: { code, timestamp, expiresAt } or null
// Get remaining time (optional, for UI)
const remaining = getSessionRemainingTime();
// Returns: milliseconds until expiry- Storage Type:
localStorage(with auto-expiry) - Key:
student_session - Lifetime: 7 hari (auto-clear setelah expired)
- Security: Auto-expiry + timestamp validation
Session Data Structure:
{
"code": "NAYIKUVIIIC2025",
"timestamp": 1729234567890,
"expiresAt": 1729839367890
}✅ Better UX - User tidak perlu login ulang di tab baru
✅ Persistent - Session bertahan setelah tab ditutup
✅ Auto-expire - Otomatis clear setelah 7 hari
✅ Secure - Timestamp validation mencegah session hijacking
✅ Balance - Security & convenience yang optimal
Expiry Configuration:
- Default: 7 hari (untuk app pendidikan)
- Configurable di
src/lib/stores/session.ts - Auto-clear expired sessions
Semua route student menggunakan base path /app/ tanpa parameter code.
src/routes/app/(main)/
├── +layout.svelte ← Layout dengan navbar & header
├── +layout.ts ← CSR only, no SSR
├── +page.svelte ← Home page siswa
├── careers/
│ ├── +page.svelte ← Daftar karir
│ └── [id]/
│ └── +page.svelte ← Detail karir
├── quiz/
│ └── +page.svelte ← Quiz kepribadian
├── achievements/
│ └── +page.svelte ← Pencapaian
├── dreams/
│ └── +page.svelte ← Halaman impian
└── analytics/
└── +page.svelte ← Analytics siswa
src/routes/app/(ai-mentor)/
└── ai-mentor/
├── +layout.svelte ← Full-screen layout
└── +page.svelte ← AI Chat interface
Main Layout ((main)/+layout.svelte):
- ✅ Dashboard Header (top)
- ✅ Dashboard Navbar (bottom)
- ✅ Session validation
- ✅ Auto-redirect jika tidak login
AI Mentor Layout ((ai-mentor)/ai-mentor/+layout.svelte):
- ✅ Full-screen mode
- ✅ No header/navbar
- ✅ Dedicated untuk chat experience
DashboardNavbar (src/lib/components/DashboardNavbar.svelte):
<!-- Navigation items -->
<a href="{base}/app">Home</a>
<a href="{base}/app/careers">Karir</a>
<a href="{base}/app/ai-mentor">AI</a>
<a href="{base}/app/quiz">Quiz</a>
<a href="{base}/app/achievements">Trophy</a>Key Changes:
- ❌ Tidak lagi menggunakan
$page.params.code - ✅ Semua link menggunakan static
/appbase path
Semua route admin menggunakan base path /dashboard/.
src/routes/
├── login/ ← Admin login (NO dashboard layout!) ⭐
│ └── +page.svelte ← Standalone login page
│
└── dashboard/ ← Admin panel (WITH dashboard layout)
├── +layout.svelte ← Admin layout dengan auth check
├── +page.svelte ← Admin home (quick actions)
├── overview/
│ └── +page.svelte ← Student overview & stats
├── students/
│ └── +page.svelte ← Manage students (CRUD)
├── analytics/
│ └── +page.svelte ← Platform analytics & insights
├── settings/
│ └── +page.svelte ← App settings (AI API, DB, etc)
├── qr-generator/
│ └── +page.svelte ← Generate student QR codes
└── migrate-codes/
└── +page.svelte ← Migrate student code formats
Key Point:
- ✅
/loginis OUTSIDE/dashboard/folder - ✅
/logindoes NOT use dashboard layout - ✅
/dashboard/*pages ALWAYS use dashboard layout - ✅ Clean separation of concerns
Login Page (login/+page.svelte):
// Standalone page - No dashboard layout // Full-screen login form // Redirects to /dashboard after
successDashboard Layout (dashboard/+layout.svelte):
// Check if admin is logged in
if (!$adminStore) {
goto(`${base}/login`); // ← Now redirects to /login
}Admin Store (src/lib/stores/admin.ts):
- Username & password validation
- Session management
- Role-based access (future)
┌─────────────┐
│ Landing │
│ Page (/) │
└──────┬──────┘
│
v
┌─────────────┐
│ Unlock │ ← User input student code
│ /unlock │
└──────┬──────┘
│
v
┌─────────────────────┐
│ Validate Code │ ← Check di Supabase database
│ db.getStudent() │
└──────┬──────────────┘
│
v
┌─────────────────────┐
│ Save to Session │ ← setStudentCode(code)
│ sessionStorage │
└──────┬──────────────┘
│
v
┌─────────────────────┐
│ Redirect to App │ ← goto(`${base}/app`)
│ /app/ │
└─────────────────────┘
┌─────────────┐
│ App Layout │
│ (onMount) │
└──────┬──────┘
│
v
┌──────────────────┐
│ Check Session │ ← getStudentCode()
│ & User Progress │
└──────┬───────────┘
│
├── ✅ Valid → Continue
│
└── ❌ Invalid → Redirect to /unlock
┌─────────────────┐
│ Dashboard Login │ ← Username & password
│ /dashboard/login│
└────────┬────────┘
│
v
┌─────────────────┐
│ Validate Auth │ ← Check credentials
│ adminStore │
└────────┬────────┘
│
v
┌─────────────────────┐
│ Set Admin Session │ ← Save to store
│ localStorage │
└────────┬────────────┘
│
v
┌─────────────────────┐
│ Redirect Dashboard │ ← goto(`${base}/dashboard`)
│ /dashboard/ │
└─────────────────────┘
Old URL Structure:
/dashboard/[code]/ ← Student portal
/admin/ ← Admin panel
New URL Structure (v2.0):
/app/ ← Student portal
/dashboard/ ← Admin panel
Before:
<!-- Navigation dengan code parameter -->
<a href="{base}/dashboard/{$page.params.code}/careers"> Karir </a>
<!-- Redirect dengan code -->
goto(`${base}/dashboard/${code}/quiz`);After:
<!-- Navigation tanpa code parameter -->
<a href="{base}/app/careers"> Karir </a>
<!-- Redirect tanpa code -->
goto(`${base}/app/quiz`);Before:
<a href="{base}/admin/students">Students</a>After:
<a href="{base}/dashboard/students">Students</a>Before:
// Code di URL params const code = $page.params.code;After:
// Code di session import {getStudentCode} from '$lib/stores/session'; const code = getStudentCode();- Update all navigation links
- Update all
goto()redirects - Update layout authentication checks
- Update components that use
$page.params.code - Test login flow
- Test navigation between pages
- Test logout/session clearing
-
Student Login
1. Go to /unlock 2. Enter student code 3. Verify redirect to /app 4. Check sessionStorage has 'student_code' -
Student Navigation
1. Click all navbar items 2. Verify URLs don't have [code] parameter 3. Verify navigation works correctly -
Session Persistence
1. Login as student 2. Navigate to different pages 3. Refresh page → Should stay logged in 4. Close tab → Session should clear 5. Open new tab → Should redirect to /unlock -
Admin Routes
1. Go to /dashboard/login 2. Login with admin credentials 3. Verify all admin routes accessible 4. Verify URLs use /dashboard prefix
# Run development server
pnpm dev
# Test routes in browser
# Student: http://localhost:5173/app
# Admin: http://localhost:5173/dashboard
# Build for production
pnpm build
# Preview production build
pnpm preview- Admin Guide - Panduan lengkap admin panel
- Admin Structure - Struktur folder admin
- Quick Start - Getting started guide
- Session Store - Session management code
Cause: Session tidak tersimpan dengan benar
Solution:
// Check if sessionStorage is working
console.log(getStudentCode()); // Should return code
// Manually set code for testing
setStudentCode('TEST2025XXX');Cause: Masih menggunakan old routing pattern
Solution: Update code untuk tidak menggunakan $page.params.code
// ❌ Old const code = $page.params.code; // ✅ New import {getStudentCode} from '$lib/stores/session';
const code = getStudentCode();Cause: Masih menggunakan /admin/ prefix
Solution: Update semua link ke /dashboard/
// ❌ Old
<a href="{base}/admin/students">
// ✅ New
<a href="{base}/dashboard/students">- Session menggunakan
sessionStorage, bukanlocalStorage - Student code tidak pernah muncul di URL (lebih aman)
- Semua route student menggunakan
/appbase path - Semua route admin menggunakan
/dashboardbase path - Layout groups
(main)dan(ai-mentor)untuk organization
Maintained by: IT Team We Will Shine
Last Review: October 2025
Status: ✅ Active & Production-Ready