Skip to main content

Overview

Campus is built with modern, cutting-edge technologies that prioritize developer experience, performance, and maintainability. The stack is carefully chosen to minimize configuration overhead while maximizing productivity.

Frontend Stack

Svelte 5

Version: ^5.43.14 Why Svelte 5?
  • Runes-based reactivity: New $state, $derived, $effect primitives
  • Compilation approach: Framework logic compiled away at build time
  • Minimal runtime: ~3KB gzipped for core runtime
  • Performance: No virtual DOM overhead
  • Developer experience: Less boilerplate than React/Vue
Usage in Campus:
<script>
  let count = $state(0)  // New Svelte 5 runes syntax
  let doubled = $derived(count * 2)
  
  $effect(() => {
    console.log(`Count is now ${count}`)
  })
</script>

<button onclick={() => count++}>
  {count} (doubled: {doubled})
</button>

SvelteKit

Version: ^2.49.0
Adapter: @sveltejs/adapter-node (v5.4.0)
Features Used:
  • File-based routing (src/routes/)
  • Server-side rendering (SSR)
  • API routes (+server.ts files)
  • Load functions (+page.server.ts, +page.ts)
  • Hooks for request interception
  • Form actions for progressive enhancement
Configuration (svelte.config.js):
import adapter from '@sveltejs/adapter-node'
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'

const config = {
  preprocess: vitePreprocess(),
  kit: {
    adapter: adapter(),
    alias: { $types: 'src/types' }
  }
}

Tailwind CSS v4

Version: ^4.1.17
Vite Plugin: @tailwindcss/vite (v4.1.17)
Why Tailwind v4?
  • Vite-first architecture: No PostCSS required
  • Performance: Faster builds with Rust-based engine
  • CSS-first config: Configure via CSS variables
  • Smaller footprint: Optimized bundle size
Plugins Used:
  • @tailwindcss/forms - Better form styling defaults
  • @tailwindcss/typography - Prose content styling
Additional Utilities:
  • tailwind-merge (v3.4.0) - Merge Tailwind classes intelligently
  • tailwind-variants (v1.0.0) - Create component variants
  • tw-animate-css (v1.4.0) - Extended animation utilities

Backend Stack

PocketBase

Version: ^0.26.3 (SDK)
Runtime: Standalone Go binary
What is PocketBase? Open-source backend-as-a-service providing:
  • Database: Embedded SQLite with migrations
  • Authentication: Email/password, OAuth2, SSO
  • File Storage: Automatic thumbnails and serving
  • Realtime: WebSocket subscriptions
  • Admin UI: Built-in dashboard at /_/
  • Access Rules: SQL-like permission system
SDK Usage:
import PocketBase from 'pocketbase'

const pb = new PocketBase('http://localhost:8090')

// Authentication
await pb.collection('users').authWithPassword(email, password)

// CRUD operations
const posts = await pb.collection('posts').getList(1, 20, {
  sort: '-created',
  expand: 'author'
})

// Realtime subscriptions
pb.collection('posts').subscribe('*', (e) => {
  console.log(e.action, e.record)
})
Database Structure:
  • SQLite 3 (pb_data/data.db)
  • Migrations in pb_migrations/ (JavaScript files)
  • Server-side hooks in pb_hooks/ (optional JavaScript)

Bun Runtime

Version: Latest stable
Purpose: JavaScript/TypeScript runtime (alternative to Node.js)
Why Bun?
  • Speed: 3-4x faster than npm/yarn
  • Built-in TypeScript: No separate transpilation
  • Native bundler: Fast builds without extra tools
  • Web API compatibility: Fetch, WebSocket, etc.
  • Drop-in replacement: Works with existing Node packages
Usage:
bun install           # Install dependencies
bun run dev          # Start dev server
bun run build        # Build for production

UI Component Libraries

Bits UI

Version: ^2.14.4 What is Bits UI? Headless, accessible component library for Svelte based on Melt UI:
  • Unstyled primitives (bring your own styles)
  • WAI-ARIA compliant
  • Keyboard navigation
  • Focus management
Components Used:
  • Dialog/Modal
  • Dropdown Menu
  • Tabs
  • Switch (toggle)
  • Form elements with labels
Example:
<script>
import { Dialog } from 'bits-ui'
</script>

<Dialog.Root>
  <Dialog.Trigger>Open</Dialog.Trigger>
  <Dialog.Portal>
    <Dialog.Overlay />
    <Dialog.Content>
      <Dialog.Title>Title</Dialog.Title>
      <Dialog.Description>Content</Dialog.Description>
    </Dialog.Content>
  </Dialog.Portal>
</Dialog.Root>

Lucide Icons

Version: ^0.548.0
Package: lucide-svelte
Features:
  • 1000+ consistent SVG icons
  • Tree-shakeable (only import what you use)
  • Customizable size, color, stroke width
Usage:
<script>
import { Calendar, User, Settings } from 'lucide-svelte'
</script>

<Calendar size={24} strokeWidth={1.5} />

Mode Watcher

Version: ^1.1.0 Purpose: Dark/light mode management for Svelte
  • Automatic system preference detection
  • Local storage persistence
  • Smooth transitions
  • SSR-safe

Svelte Sonner

Version: ^1.0.6 Purpose: Toast notifications for Svelte
  • Beautiful default styles
  • Promise-based API
  • Dismissible and stackable
  • Accessible

Form Handling & Validation

Sveltekit Superforms

Version: ^2.28.1 Features:
  • Server-side and client-side validation
  • Progressive enhancement
  • Zod schema integration
  • Error handling
  • Loading states
Example:
// +page.server.ts
import { superValidate } from 'sveltekit-superforms'
import { zod } from 'sveltekit-superforms/adapters'
import { postSchema } from '$lib/schemas'

export const load = async () => {
  const form = await superValidate(zod(postSchema))
  return { form }
}

export const actions = {
  default: async ({ request, locals }) => {
    const form = await superValidate(request, zod(postSchema))
    if (!form.valid) return fail(400, { form })
    // Process valid data...
  }
}

Zod

Version: ^3.25.76 Purpose: TypeScript-first schema validation
  • Type inference
  • Runtime validation
  • Composable schemas
  • Custom error messages
Schemas Location: src/lib/schemas/
  • post.js - Post creation/editing
  • comment.js - Comment validation
  • space.js - Space creation
  • group.js - Group creation
  • material.js - Material uploads

Utility Libraries

date-fns

Version: ^4.1.0 Purpose: Modern date utility library
  • Modular (tree-shakeable)
  • Immutable
  • TypeScript support
  • Timezone handling
Usage in Campus:
  • Format event dates
  • Calculate relative time (“2 hours ago”)
  • Parse calendar dates

linkify-it

Version: ^5.0.0 Purpose: Detect and linkify URLs in text
  • Email addresses
  • URLs without protocol
  • Customizable schemas
Usage: Auto-link URLs in post content and comments

sanitize-html

Version: ^2.17.0 Purpose: Clean HTML to prevent XSS attacks
  • Whitelist tags and attributes
  • Strip malicious content
  • Preserve safe formatting
Configuration:
import sanitizeHtml from 'sanitize-html'

const clean = sanitizeHtml(userInput, {
  allowedTags: ['b', 'i', 'em', 'strong', 'a', 'p', 'br'],
  allowedAttributes: { a: ['href'] }
})

clsx

Version: ^2.1.1 Purpose: Tiny utility for constructing className strings
import clsx from 'clsx'

const buttonClass = clsx(
  'btn',
  isActive && 'btn-active',
  disabled && 'btn-disabled'
)

Media Processing

Sharp

Version: ^0.33.5 Purpose: High-performance image processing
  • Resize images
  • Generate thumbnails
  • Format conversion
  • Optimize file sizes
Usage Location: src/lib/server/media/thumbnails.ts

Mediabunny

Version: ^1.25.1 Purpose: Media handling utilities
  • MIME type detection
  • File validation
  • Upload helpers

Development Tools

Biome

Version: 2.3.5 Purpose: All-in-one toolchain (replaces ESLint + Prettier)
  • Linter: Fast JavaScript/TypeScript linting
  • Formatter: Opinionated code formatting
  • Built in Rust: 10-100x faster than ESLint
Scripts:
{
  "biome:check": "biome check --write",
  "biome:format": "biome format --write",
  "biome:lint": "biome lint --write"
}

TypeScript

Version: ^5.9.3 (peer dependency) Purpose: Type safety and better IDE support
  • Catch errors at compile time
  • Enhanced autocomplete
  • Refactoring confidence
tsconfig.json: Configured for SvelteKit with strict mode

Vite

Version: ^7.2.4 Features:
  • Lightning-fast HMR: Hot module replacement
  • Native ESM: No bundling in dev
  • Optimized builds: Rollup under the hood
  • Plugin ecosystem: SvelteKit, Tailwind integration
Configuration Highlights (vite.config.ts):
export default defineConfig({
  plugins: [sveltekit(), tailwindcss()],
  server: { port: 5173 },
  build: {
    target: 'es2022',
    sourcemap: true,
    rollupOptions: {
      output: {
        manualChunks: { /* split vendors */ }
      }
    }
  }
})

Additional Utilities

Internationalization

Package: @internationalized/date (v3.10.0) Purpose: Locale-aware date/time handling
  • Calendar systems
  • Timezone conversions
  • Format according to user locale
Usage Location: Event creation, calendar views

State Management

Built-in Svelte features:
  • writable, readable, derived stores
  • Context API for component trees
  • $state runes (Svelte 5)
Custom Stores:
  • src/lib/stores/queryCache.ts - Query result caching
  • src/lib/stores/connection.ts - Network status

Runtime Environments

Development

# Frontend dev server (Vite + SvelteKit)
bun run dev              # http://localhost:5173

# Backend server (PocketBase)
./pocketbase serve       # http://localhost:8090

Production

# Build SvelteKit app
bun run build

# Run production server (Node.js via adapter-node)
node build/index.js      # Port 3000

# Run PocketBase
./pocketbase serve --http="0.0.0.0:8090"

Version Compatibility

TechnologyMinimum VersionTarget Runtime
Node.js18.xES2022
Bun1.0+Native
PocketBase0.26.xN/A (Go binary)
Browser TargetModern (2022+)ES2022

Dependency Tree Size

Approximate production bundle sizes:
  • Core SvelteKit + Svelte: ~40KB gzipped
  • PocketBase SDK: ~25KB gzipped
  • Tailwind CSS: ~10-15KB (purged)
  • UI Components (Bits UI): ~20KB
  • Icons (Lucide): ~3KB per 20 icons
  • Form handling: ~15KB
  • Total: ~120-150KB gzipped (first load)

Package Manager

Primary: Bun
Compatible with: npm, yarn, pnpm
Lock file: bun.lockb (binary format)

Build Output

Target Directory: build/
Format: Node.js-compatible ESM
Entry Point: build/index.js
Assets:
  • build/_app/ - Client-side JavaScript bundles
  • build/_app/immutable/ - Hashed static assets
  • static/ - Copied as-is to build root

Performance Budget

Goals:
  • First Contentful Paint: < 1.5s
  • Time to Interactive: < 3.5s
  • Bundle size: < 200KB initial load
  • Lighthouse score: > 90
Optimizations Applied:
  • Code splitting by route
  • Manual vendor chunks (vite.config.ts:32)
  • Tree-shaking unused code
  • Image optimization via Sharp
  • CSS purging via Tailwind

Build docs developers (and LLMs) love