Frontend Routing¶
The frontend is a Svelte 5 single-page application using @mateothegreat/svelte5-router for client-side routing.
Routes are defined in App.svelte with authentication guards for protected pages.
Route Overview¶
| Route | Component | Auth Required | Admin Required | Description |
|---|---|---|---|---|
/ |
Home.svelte |
No | No | Landing page with features |
/login |
Login.svelte |
No | No | User login form |
/register |
Register.svelte |
No | No | User registration form |
/privacy |
Privacy.svelte |
No | No | Privacy policy |
/editor |
Editor.svelte |
Yes | No | Code execution interface |
/settings |
Settings.svelte |
Yes | No | User preferences |
/notifications |
Notifications.svelte |
Yes | No | Notification center |
/admin/events |
AdminEvents.svelte |
Yes | Yes | Event browser |
/admin/sagas |
AdminSagas.svelte |
Yes | Yes | Saga monitoring |
/admin/users |
AdminUsers.svelte |
Yes | Yes | User management |
/admin/settings |
AdminSettings.svelte |
Yes | Yes | System settings |
Route Configuration¶
Routes are defined in src/App.svelte using the router's declarative syntax:
{ path: "^/admin$", component: AdminEvents, hooks: { pre: requireAuth } },
];
</script>
{#if appError.current}
<ErrorDisplay error={appError.current.error} title={appError.current.title} />
{:else}
<div class="flex flex-col min-h-screen bg-bg-default dark:bg-dark-bg-default pt-16">
<Header/>
<Toaster richColors position="top-right" />
<main class="flex-grow">
{#if !authInitialized}
<div class="flex items-center justify-center min-h-[50vh]">
<Spinner size="large" />
</div>
{:else}
<Router base="/" {routes} />
Authentication Guard¶
The requireAuth hook checks the isAuthenticated store before allowing navigation:
const routes = [
// Public routes
{ path: "/", component: Home },
{ path: "/login", component: Login },
{ path: "/register", component: Register },
{ path: "/privacy", component: Privacy },
// Protected routes
{ path: "/editor", component: Editor, hooks: { pre: requireAuth } },
{ path: "/settings", component: Settings, hooks: { pre: requireAuth } },
{ path: "/notifications", component: Notifications, hooks: { pre: requireAuth } },
{ path: "/admin/events", component: AdminEvents, hooks: { pre: requireAuth } },
{ path: "/admin/sagas", component: AdminSagas, hooks: { pre: requireAuth } },
{ path: "/admin/users", component: AdminUsers, hooks: { pre: requireAuth } },
When an unauthenticated user tries to access a protected route:
- The original URL is saved to
sessionStorage - User is redirected to
/login - After successful login, user is redirected back to the original URL
Admin Role Check¶
Admin routes perform an additional role check in the component:
// In AdminEvents.svelte, AdminUsers.svelte, etc.
import { userRole } from '$stores/auth';
import { get } from 'svelte/store';
if (get(userRole) !== 'ADMIN') {
goto('/editor');
}
Navigation¶
Programmatic Navigation¶
Use the goto function for programmatic navigation:
import { goto } from '@mateothegreat/svelte5-router';
// Navigate to editor
goto('/editor');
// Navigate with redirect after login
sessionStorage.setItem('redirectAfterLogin', '/editor');
goto('/login');
Link Navigation¶
Use the route directive for link navigation:
Route Components¶
Public Pages¶
| Component | Path | Purpose |
|---|---|---|
Home.svelte |
src/routes/Home.svelte |
Landing page with features overview |
Login.svelte |
src/routes/Login.svelte |
Login form with credential handling |
Register.svelte |
src/routes/Register.svelte |
Registration form with validation |
Privacy.svelte |
src/routes/Privacy.svelte |
Privacy policy content |
Protected Pages¶
| Component | Path | Purpose |
|---|---|---|
Editor.svelte |
src/routes/Editor.svelte |
Code editor with execution |
Settings.svelte |
src/routes/Settings.svelte |
User preferences (theme, editor) |
Notifications.svelte |
src/routes/Notifications.svelte |
Notification list and management |
Admin Pages¶
| Component | Path | Purpose |
|---|---|---|
AdminEvents.svelte |
src/routes/admin/AdminEvents.svelte |
Event browser with filters |
AdminSagas.svelte |
src/routes/admin/AdminSagas.svelte |
Saga status monitoring |
AdminUsers.svelte |
src/routes/admin/AdminUsers.svelte |
User CRUD and rate limits |
AdminSettings.svelte |
src/routes/admin/AdminSettings.svelte |
System configuration |
State Management¶
Routes interact with several Svelte stores:
| Store | Location | Purpose |
|---|---|---|
isAuthenticated |
stores/auth.ts |
Authentication state |
username |
stores/auth.ts |
Current username |
userRole |
stores/auth.ts |
User role (USER/ADMIN) |
csrfToken |
stores/auth.ts |
CSRF token for API calls |
theme |
stores/theme.ts |
Current theme (light/dark/auto) |
notifications |
stores/notificationStore.ts |
Notification list |
SSE Connections¶
Protected routes may establish SSE connections for real-time updates:
- Editor: Connects to
/api/v1/events/executions/{id}during execution - Notifications: Connects to
/api/v1/events/notifications/stream
Connections are managed in the component lifecycle:
onMount(() => {
// Establish SSE connection
const eventSource = new EventSource('/api/v1/events/notifications/stream');
eventSource.onmessage = (event) => {
// Handle notification
};
return () => {
eventSource.close();
};
});
Deep Linking¶
The router supports deep linking with proper URL handling:
- Direct URL access works for all routes
- 404 handling redirects to home or shows error
- Query parameters are preserved across navigation
Key Files¶
| File | Purpose |
|---|---|
src/App.svelte |
Route definitions and layout |
src/stores/auth.ts |
Authentication state |
src/lib/auth-init.ts |
Auth initialization on app load |
src/components/Header.svelte |
Navigation links |
src/components/ProtectedRoute.svelte |
Route protection wrapper |