Project Structure
SvelteForge Admin follows SvelteKit's file-based routing conventions and Svelte 5's component architecture. Every directory and file has a specific purpose — understanding this structure is key to extending the dashboard efficiently.
Because SvelteKit uses the filesystem as its router, the src/routes/ directory directly maps to URL paths. Route groups (directories in parentheses) share layouts without
affecting the URL, which is how SvelteForge separates protected, auth, public, and documentation pages.
Complete File Tree
svelteforge-admin/
├── src/
│ ├── routes/ # SvelteKit file-based routing
│ │ ├── (app)/ # Protected routes (auth required)
│ │ │ ├── +layout.server.ts # Auth guard + maintenance mode check
│ │ │ ├── +layout.svelte # App shell (sidebar + topbar)
│ │ │ ├── +page.svelte # Dashboard (/)
│ │ │ ├── users/ # User management CRUD
│ │ │ ├── content/ # CMS pages
│ │ │ │ ├── +page.svelte # Content list
│ │ │ │ ├── new/ # Create new page
│ │ │ │ └── [id]/edit/ # Edit existing page (dynamic route)
│ │ │ ├── analytics/ # Charts and data visualization
│ │ │ ├── notifications/ # Notification center
│ │ │ ├── roles/ # Role management
│ │ │ ├── database/ # Database browser
│ │ │ └── settings/ # Application settings
│ │ ├── (auth)/ # Public auth routes (no auth required)
│ │ │ ├── +layout.svelte # Auth layout (centered card)
│ │ │ ├── login/ # Login page
│ │ │ │ ├── +page.svelte # Login form
│ │ │ │ ├── +page.server.ts # Login action (Argon2 verify)
│ │ │ │ ├── google/ # Google OAuth initiation
│ │ │ │ │ ├── +server.ts # Redirect to Google
│ │ │ │ │ └── callback/ # Google OAuth callback
│ │ │ │ └── github/ # GitHub OAuth initiation
│ │ │ │ ├── +server.ts # Redirect to GitHub
│ │ │ │ └── callback/ # GitHub OAuth callback
│ │ │ ├── register/ # Registration page
│ │ │ ├── forgot-password/ # Password reset request
│ │ │ ├── reset-password/ # Password reset form
│ │ │ └── lock/ # Screen lock (re-enter password)
│ │ ├── (public)/ # Public marketing pages
│ │ │ └── pricing/ # Pricing page
│ │ ├── docs/ # Documentation (this site)
│ │ │ ├── +layout.svelte # Docs layout (sidebar nav + prose)
│ │ │ ├── +page.svelte # Introduction
│ │ │ ├── getting-started/ # Installation guide
│ │ │ ├── project-structure/ # This page
│ │ │ ├── authentication/ # Auth documentation
│ │ │ └── ... # Additional doc pages
│ │ ├── logout/ # Logout action (server-only)
│ │ ├── api/
│ │ │ └── search/ # Command palette search endpoint
│ │ └── sitemap.xml/ # Auto-generated sitemap
│ │
│ ├── lib/
│ │ ├── server/ # Server-only code (never sent to client)
│ │ │ ├── auth.ts # Session management functions
│ │ │ ├── oauth.ts # Arctic OAuth provider setup
│ │ │ ├── id.ts # Cryptographic ID generator
│ │ │ └── db/
│ │ │ ├── index.ts # Database connection (better-sqlite3)
│ │ │ ├── schema.ts # Drizzle ORM schema definitions
│ │ │ └── seed.ts # Database seeder script
│ │ │
│ │ ├── components/ # App-level Svelte 5 components
│ │ │ ├── app-sidebar.svelte # Main navigation sidebar
│ │ │ ├── command-palette.svelte # Ctrl+K search overlay
│ │ │ ├── notification-bell.svelte # Notification dropdown
│ │ │ ├── theme-toggle.svelte # Dark/light mode switch
│ │ │ ├── animated-counter.svelte # Number animation component
│ │ │ ├── data-table-pagination.svelte # Table pagination
│ │ │ ├── delete-confirm-dialog.svelte # Confirmation modal
│ │ │ ├── role-change-dialog.svelte # Role assignment modal
│ │ │ ├── user-form-dialog.svelte # User create/edit form
│ │ │ └── apps-menu.svelte # Application switcher menu
│ │ │
│ │ ├── components/ui/ # shadcn-svelte primitives
│ │ │ ├── button/
│ │ │ ├── card/
│ │ │ ├── dialog/
│ │ │ ├── dropdown-menu/
│ │ │ ├── input/
│ │ │ ├── table/
│ │ │ └── ... # More shadcn-svelte components
│ │ │
│ │ ├── hooks/ # Svelte 5 reactive utilities
│ │ │ └── is-mobile.svelte.ts # Responsive breakpoint detection
│ │ │
│ │ ├── utils/ # Utility modules
│ │ │ ├── export.ts # CSV and JSON export functions
│ │ │ └── user-agent.ts # User-agent string parser
│ │ │
│ │ └── utils.ts # cn() helper (clsx + tailwind-merge)
│ │
│ ├── app.css # Tailwind CSS 4 theme configuration
│ ├── app.d.ts # TypeScript type definitions
│ ├── app.html # HTML shell template
│ └── hooks.server.ts # SvelteKit server hooks
│
├── drizzle/ # Generated Drizzle migration files
├── static/ # Static assets (favicon, images)
├── tests/ # Playwright E2E test files
│
├── svelteforge.db # SQLite database (gitignored)
├── drizzle.config.ts # Drizzle ORM configuration
├── vite.config.ts # Vite + SvelteKit configuration
├── tailwind.config.ts # Tailwind CSS configuration
├── tsconfig.json # TypeScript configuration
├── package.json # Dependencies and scripts
├── pnpm-lock.yaml # pnpm lockfile
└── .env.example # Environment variable template Route Groups Explained
SvelteKit route groups are a powerful organizational tool. Directories wrapped in
parentheses — like (app) — create layout boundaries without adding URL segments. SvelteForge
uses four route groups to cleanly separate concerns:
(app)/ — Protected Routes
Every route inside (app)/ requires authentication. The auth guard lives in (app)/+layout.server.ts and runs before any page load:
// src/routes/(app)/+layout.server.ts
export const load: LayoutServerLoad = async ({ locals }) => {
if (!locals.user) {
redirect(302, "/login");
}
// Check maintenance mode
const maintenanceSetting = await db.query.appSettings.findFirst({
where: eq(appSettings.key, "maintenanceMode"),
});
if (maintenanceSetting?.value === "true" && locals.user.role !== "admin") {
error(503, "The application is currently under maintenance.");
}
return { user: locals.user, ... };
}; This single SvelteKit layout server load function protects the dashboard, user management, content, analytics, notifications, roles, database, and settings pages — all without repeating auth logic in each route. The layout also enforces maintenance mode, blocking non-admin users with a 503 error.
The (app)/+layout.svelte provides the app shell: a collapsible sidebar, topbar with breadcrumbs,
command palette, and notification bell.
(auth)/ — Public Auth Routes
Authentication pages that must be accessible without being logged in: login, register, forgot password, reset password, and screen lock. These use a minimal centered-card layout — no sidebar, no topbar.
OAuth callback routes nest under login/ as login/google/callback/ and login/github/callback/, keeping OAuth flow
URLs clean and organized within SvelteKit's file-based router.
(public)/ — Marketing Pages
Public-facing pages like pricing that use their own layout — no auth required, no app shell. These pages are designed for unauthenticated visitors.
docs/ — Documentation
The documentation section (the pages you are reading now) uses its own layout with sidebar
navigation and prose styling. This route group is not wrapped in parentheses because docs appears in the URL path.
Server-Only Code: src/lib/server/
SvelteKit enforces a strict server boundary. Any module inside #lib/server/ is guaranteed to never be bundled into client-side JavaScript. If you
accidentally import a server module from a .svelte component, the build will fail with
a clear error. This is critical for SvelteForge because sensitive code lives here:
auth.ts — Session Management
The core authentication module. Generates session tokens, hashes them with SHA-256, creates and
validates sessions, and manages httpOnly cookies. Uses node:crypto for cryptographic
operations — no external auth framework needed. See the Authentication page for a deep dive.
oauth.ts — Arctic OAuth Providers
Configures Google and GitHub OAuth via the Arctic library. Providers are environment-driven — they are null when env vars are missing, and the login page conditionally renders social
login buttons. This means OAuth is entirely optional; the dashboard works with password-only auth out
of the box.
id.ts — Cryptographic ID Generator
A simple utility that generates cryptographically random IDs using crypto.getRandomValues() and base32 encoding. Used for user IDs, OAuth account IDs, and password reset tokens throughout the
application.
db/ — Database Layer
index.ts— Creates the better-sqlite3 connection with WAL mode enabled for concurrent reads. Exports the Drizzle ORMdbinstance.schema.ts— Defines all database tables using Drizzle's type-safe schema builder:users,sessions,pages,notifications,oauthAccounts,appSettings, andpasswordResetTokens. Each table export includes inferred TypeScript types.seed.ts— Populates the database with sample data. Runs viapnpm db:seedusingtsx(not SvelteKit's runtime), so it uses relative imports instead of#lib/aliases.
App-Level Components: src/lib/components/
These are Svelte 5 components built with the runes API ($state, $props, $derived). Each component is self-contained with its own
reactive state:
| Component | Purpose |
|---|---|
app-sidebar.svelte | Main navigation sidebar with collapsible groups, user avatar, and role display. Uses Svelte 5 $state for open/close tracking. |
command-palette.svelte | Keyboard-driven search overlay (Ctrl+K / Cmd+K). Queries the /api/search endpoint and renders results in real time. |
notification-bell.svelte | Topbar notification icon with unread count badge and dropdown list of recent notifications. |
theme-toggle.svelte | Dark/light mode switch using mode-watcher. Accesses mode.current (runes
object, not a Svelte store). |
animated-counter.svelte | Smoothly animates between numeric values for dashboard stat cards. |
data-table-pagination.svelte | Reusable pagination controls for data tables with page size selection. |
delete-confirm-dialog.svelte | Confirmation modal for destructive actions (delete user, delete page, etc.). |
role-change-dialog.svelte | Modal for changing a user's role (admin, editor, viewer) with confirmation. |
user-form-dialog.svelte | Create/edit user form in a dialog, used by the user management page. |
apps-menu.svelte | Application switcher dropdown in the topbar for navigating between app sections. |
UI Primitives: src/lib/components/ui/
This directory contains shadcn-svelte components — accessible, composable UI primitives built on Bits UI. These are copy-pasted into your project (not installed as a dependency), giving you full control over their source.
Important: Do not edit these files directly. To update or add components, use the CLI:
npx shadcn-svelte@latest add button
npx shadcn-svelte@latest add dialog
npx shadcn-svelte@latest add dropdown-menu shadcn-svelte components are fully compatible with Svelte 5 runes and use @render snippets instead of slots for child content.
Reactive Utilities: src/lib/hooks/
Svelte 5 runes enable reactive hooks similar to React's custom hooks, but with
compile-time optimization. The .svelte.ts extension tells the Svelte compiler to process
runes in these files:
is-mobile.svelte.ts
A reactive hook that tracks viewport width using $state and $effect. Returns a boolean that automatically updates when the window resizes. Used
by the sidebar to determine default open/closed state on mobile.
Utility Modules: src/lib/utils/
| File | Purpose |
|---|---|
export.ts | Functions to export data tables as CSV or JSON files. Handles column mapping, date formatting, and triggers browser download. |
user-agent.ts | Parses user-agent strings to extract browser name and OS. Used in the Settings page to display active sessions with device info. |
src/lib/utils.ts
The cn() helper function, which combines clsx (conditional class names)
with tailwind-merge (deduplication of Tailwind classes). Used extensively by shadcn-svelte
components and throughout the application:
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
} App-Level Configuration Files
src/app.css — Tailwind CSS 4 Theme
Tailwind CSS 4 replaces the traditional JavaScript config with native CSS.
SvelteForge defines its design tokens using the @theme directive with OKLCH colors, supporting
both light and dark modes. This is where you customize the color palette, border radii, fonts, and other
design tokens.
src/app.d.ts — TypeScript Definitions
Extends SvelteKit's App.Locals interface to include user and session properties. This ensures TypeScript knows about the authenticated
user data available in every server load function and form action:
declare global {
namespace App {
interface Locals {
user: SessionUser | null;
session: Session | null;
}
}
} src/hooks.server.ts — Server Hooks
SvelteKit server hooks run on every single request. SvelteForge
uses this to validate the session cookie, populate event.locals.user and event.locals.session, auto-extend session cookies, and update session metadata (user
agent and IP address). This is the foundation of the authentication system — see Authentication for details.
Root Configuration Files
| File | Purpose |
|---|---|
vite.config.ts | Vite configuration with the SvelteKit plugin. Marks LayerChart and svelte-ux as noExternal for SSR compatibility. Configures Vitest. |
drizzle.config.ts | Drizzle ORM configuration pointing to src/lib/server/db/schema.ts as the
schema source and svelteforge.db as the SQLite database file. |
vite.config.ts | SvelteKit configuration, Node adapter, Tailwind, and Vitest. |
package.json | Project dependencies and npm scripts. Key scripts: dev, build, check, db:push, db:seed, test. |
tsconfig.json | TypeScript configuration extending SvelteKit's recommended settings. |
.env.example | Template for environment variables: OAuth client IDs/secrets, ORIGIN, and database path. |
Database File
The SQLite database file svelteforge.db lives at the project root. It is gitignored and created automatically when you run pnpm db:push. The
database runs in WAL (Write-Ahead Logging) mode for better concurrent read performance. You will
also see svelteforge.db-shm and svelteforge.db-wal files — these are WAL support
files managed by SQLite.
To inspect the database visually, use pnpm db:studio to open Drizzle Studio in your browser.
Need More?
Go Premium with DashboardPack
SvelteForge Admin gives you a clean, well-organized Svelte 5 + SvelteKit foundation. When your project outgrows it — 50+ pages, multiple dashboard layouts, advanced CRUD generators, theme customizers, and production-grade components — DashboardPack has you covered.
- Apex (Svelte) — SvelteKit admin with 6 dashboards and 39 demo pages
- Zenith — Modern analytics dashboard with advanced data visualization
- Signal — Real-time monitoring dashboard with live data feeds
- Ember — Sleek SaaS dashboard with subscription management
- Flux — Minimalist admin with focus on speed and simplicity