Skip to content

Latest commit

 

History

History
97 lines (72 loc) · 4.85 KB

File metadata and controls

97 lines (72 loc) · 4.85 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

SvelteForge Admin is a SvelteKit admin dashboard using Svelte 5, Tailwind CSS v4, custom session-based auth with Arctic OAuth, and Drizzle ORM with SQLite.

Commands

pnpm dev              # Start dev server
pnpm build            # Production build
pnpm preview          # Preview production build
pnpm check            # Type-check with svelte-check
pnpm check:watch      # Type-check in watch mode

pnpm db:generate      # Generate Drizzle migrations from schema
pnpm db:push          # Push schema changes directly to database
pnpm db:studio        # Open Drizzle Studio GUI
pnpm db:seed          # Seed database with sample data (npx tsx)

pnpm test             # Run all unit tests (Vitest)
pnpm test:watch       # Run tests in watch mode
pnpm test:e2e         # Run E2E tests (Playwright)

# Run a single test file
npx vitest run src/routes/\(app\)/users/users.test.ts

pnpm lint             # ESLint
pnpm format           # Prettier (write)
pnpm format:check     # Prettier (check only)

Architecture

Tech Stack

  • Svelte 5 with runes API ($props, $state, $derived, {@render})
  • Tailwind CSS v4 — native CSS with @theme directive in src/app.css, no JS config file. OKLCH color system
  • shadcn-svelte — UI components in $lib/components/ui/, added via npx shadcn-svelte@latest add <component>
  • Custom session auth — SHA-256 hashed tokens with @oslojs/crypto, Argon2id password hashing, optional OAuth via Arctic (Google, GitHub)
  • Drizzle ORM — SQLite with better-sqlite3, WAL mode. Schema in src/lib/server/db/schema.ts
  • LayerChart v2 — D3-based charts. Marked noExternal in vite.config.ts alongside svelte-ux for SSR compatibility
  • Package manager: pnpm

Routing & Auth

Routes use SvelteKit route groups for layout separation:

  • (app)/ — Protected routes. Auth guard in (app)/+layout.server.ts redirects unauthenticated users to /login
  • (auth)/ — Public auth routes (login, register, OAuth callbacks at login/google/, login/github/)
  • (public)/ — Public pages (pricing)
  • logout/ — Standalone logout action (server-only)
  • api/search/ — Search endpoint for command palette
  • sitemap.xml/ — Auto-generated sitemap

Session validation runs on every request via hooks.server.ts, populating event.locals.user and event.locals.session. OAuth providers are environment-driven — see .env.example for configuration.

Key Directories

  • src/lib/server/ — Server-only code (auth, OAuth, database). Never import from client-side code
  • src/lib/server/auth.ts — Session management (create, validate, invalidate, cookies)
  • src/lib/server/oauth.ts — Arctic OAuth providers (conditional on env vars)
  • src/lib/server/db/schema.ts — Drizzle schema (users, sessions, pages, notifications, oauthAccounts, appSettings, passwordResetTokens)
  • src/lib/server/db/seed.ts — Database seeder (run via pnpm db:seed, uses npx tsx not SvelteKit aliases)
  • src/lib/server/id.ts — Crypto ID generator (generateId())
  • src/lib/components/ui/ — shadcn-svelte components (don't edit directly, re-add to update)
  • src/lib/components/ — App-level components (sidebar, theme toggle, command palette, notification bell)
  • src/lib/hooks/ — Svelte 5 reactive utilities (e.g., is-mobile.svelte.ts)
  • src/lib/utils.tscn() helper (clsx + tailwind-merge) and component type utilities
  • src/lib/utils/ — Export utilities (CSV/JSON), user-agent parser

Database

SQLite database file: svelteforge.db (project root, gitignored). Roles enum: admin | editor | viewer. First registered user gets admin role.

Testing

Tests co-locate with their route: e.g., src/routes/(app)/users/users.test.ts tests the users/+page.server.ts load and actions.

Test DB pattern: Tests mock $lib/server/db/index.js with a getter that returns an in-memory SQLite database created via createTestDb() from test-utils.ts. The mock must be set up before dynamically importing the server module:

vi.mock("$lib/server/db/index.js", () => ({
  get db() { return testDb; },
}));
const { load, actions } = await import("./+page.server.js");

After modifying schema.ts, also update the SCHEMA_SQL in test-utils.ts and run pnpm db:push.

Patterns

  • Forms use SvelteKit form actions with use:enhance for progressive enhancement
  • Dark/light mode via mode-watcher — use mode.current (runes object), NOT $mode
  • App shell layout: sidebar (app-sidebar.svelte) + topbar with breadcrumbs (generated from URL pathname)
  • App.Locals typed in src/app.d.tsuser: SessionUser | null, session: Session | null
  • seed.ts runs outside SvelteKit context — use relative imports (not $lib/) and generateId() from $lib/server/id.js