Files
workshop-manager/CLAUDE.md

4.6 KiB

CLAUDE.md

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

Commands

# Development
pnpm dev          # Start dev server (http://localhost:3000)
pnpm build        # Production build (standalone output)
pnpm lint         # Run ESLint

# Database (use pnpm instead of npx)
pnpm prisma migrate dev --name <name>   # Create and apply migration
pnpm prisma generate                    # Regenerate Prisma client
pnpm prisma studio                      # Open DB GUI

Stack

  • Next.js 16 (App Router, standalone output)
  • SQLite + Prisma 7 via @prisma/adapter-better-sqlite3 (not the default SQLite adapter)
  • NextAuth.js v5 (beta.30) — JWT sessions, Credentials provider only
  • Tailwind CSS v4 — CSS Variables theming in src/app/globals.css
  • Drag & Drop@dnd-kit and @hello-pangea/dnd (both present)
  • pnpm — package manager (use pnpm, not npm/yarn)

Architecture Overview

Workshop Types

There are 5 workshop types: swot (sessions), motivators, year-review, weekly-checkin, weather.

Single source of truth: src/lib/workshops.ts exports WORKSHOPS, WORKSHOP_BY_ID, and helpers. Every place that lists or routes workshop types must use this file.

All types and UI config constants are in src/lib/types.ts (e.g. MOTIVATORS_CONFIG, YEAR_REVIEW_SECTIONS, SWOT_QUADRANTS, EMOTIONS_CONFIG).

Layer Structure

src/
├── actions/          # Next.js Server Actions ('use server') — call services, revalidate paths
├── services/         # Prisma queries + business logic (server-only)
│   ├── database.ts   # Prisma singleton (global for dev HMR)
│   ├── session-permissions.ts  # Shared permission factories
│   └── session-share-events.ts # Shared share + SSE event handlers
├── app/
│   ├── api/          # Route handlers (SSE subscribe + auth)
│   ├── (auth)/       # Login/register pages
│   └── [workshop]/   # One folder per workshop type
├── components/
│   └── collaboration/ # BaseSessionLiveWrapper + share/live UI
├── hooks/
│   └── useLive.ts    # SSE client hook (EventSource + reconnect)
└── lib/
    ├── workshops.ts   # Workshop metadata registry
    ├── types.ts       # All TypeScript types + UI config
    └── share-utils.ts # Shared share types

Real-Time Collaboration (SSE)

Each workshop has /api/[path]/[id]/subscribe — a GET route that opens a ReadableStream (SSE). The server polls the DB every 1 second for new events and pushes them to connected clients. Server Actions write events to the DB after mutations.

Client side: useLive hook (src/hooks/useLive.ts) connects to the subscribe endpoint with EventSource, filters out events from the current user (to avoid duplicates), and calls router.refresh() on incoming events.

BaseSessionLiveWrapper (src/components/collaboration/) is the shared wrapper component that wires useLive, CollaborationToolbar, and ShareModal for all workshop session pages.

Shared Permission System

createSessionPermissionChecks(model) in src/services/session-permissions.ts returns canAccess, canEdit, canDelete for any Prisma model that follows the session shape (has userId + shares relation). Team admins have implicit access to their members' sessions.

createShareAndEventHandlers(...) in src/services/session-share-events.ts returns share, removeShare, getShares, createEvent, getEvents — used by all workshop services.

Auth

  • src/lib/auth.ts — NextAuth config (signIn, signOut, auth exports)
  • src/lib/auth.config.ts — config object (used separately for Edge middleware)
  • src/middleware.ts — protects all routes except /api/auth, _next/static, _next/image, favicon.ico
  • Session user ID is available via auth() call server-side; token includes id field

Database

Prisma client is a singleton in src/services/database.ts. DATABASE_URL env var controls the SQLite file path (default: file:./prisma/dev.db). Schema is at prisma/schema.prisma.

Adding a New Workshop

Pattern followed by all existing workshops:

  1. Add entry to WORKSHOPS in src/lib/workshops.ts
  2. Add Prisma models (Session, Item, Share, Event) following the existing pattern
  3. Create service in src/services/ using createSessionPermissionChecks and createShareAndEventHandlers
  4. Create server actions in src/actions/
  5. Create API route src/app/api/[path]/[id]/subscribe/route.ts (copy from existing)
  6. Create pages under src/app/[path]/
  7. Use BaseSessionLiveWrapper for the session live page