Add comprehensive testing covering 420 unit/handler tests across 24 Vitest files, 9 Playwright E2E specs, accessibility scans, and visual regression. Includes GitHub Actions CI, Husky pre-push hook, and TESTING.md docs.
5.8 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Ghost Guild is a membership community platform for game developers exploring cooperative business models. Built with Nuxt 4, Vue 3, MongoDB, and Nuxt UI 4.
Commands
npm run dev # Start dev server at http://localhost:3000
npm run build # Production build
npm run preview # Preview production build
npm run test:run # Vitest single run (pre-push hook)
npm run test:e2e # Playwright E2E (needs dev server + MongoDB)
npm run test:a11y # Accessibility scans
npm run test:all # Vitest + Playwright
Dev helpers: GET /api/dev/test-login — creates a test admin user and sets auth cookie (dev only, blocked in production). Navigate to this URL to access admin pages during development.
Testing: Vitest for unit/handler tests (tests/), Playwright for E2E (e2e/). Husky pre-push hook runs Vitest. See TESTING.md for details.
Architecture
Stack
- Framework: Nuxt 4 (Vue 3 + Nitro server)
- UI: Nuxt UI 4 (
@nuxt/ui@^4) with Tailwind CSS - Database: MongoDB via Mongoose
- Auth: JWT magic link (email-only, no passwords)
- Payments: Helcim (recurring subscriptions + ticket sales)
- Email: Resend
- Slack:
@slack/web-apifor member invitations and notifications - Images: Cloudinary
- Analytics: Plausible (
ghostguild.org)
Key Directories
app/composables/— State management viauseState()(no Pinia/Vuex). Key composables:useAuth,useHelcim,useMemberPayment,useMemberStatusapp/config/— Circle definitions (circles.js) and contribution tiers (contributions.js) used across frontend and formsapp/middleware/— Route guards:auth.js(member pages),admin.js(admin pages),coming-soon.global.js(launch gate)app/layouts/—default(sidebar, member/public),admin(sidebar, admin pages),landing,coming-soonserver/api/— Nitro API routes organized by feature:auth/,events/,members/,helcim/,series/,updates/,admin/,slack/,dev/(dev-only helpers)server/models/— Mongoose schemas:Member,Event,Series,Updateserver/utils/— Service integrations:mongoose.js,helcim.js,resend.js,slack.ts,tickets.js
Domain Model
Three membership circles: Community, Founder, Practitioner — each with different access and context. Five contribution tiers: $0, $5, $15, $30, $50/month via Helcim subscriptions.
Member statuses: pending_payment, active, suspended, cancelled.
Events support ticketing with circle-specific pricing overrides and can be grouped into Series with bundled passes.
Design System (Zine Direction)
- Palette: CSS custom properties in
:root/.darkblocks inapp/assets/css/main.css—--bg(cream/#f4efe4),--surface,--border,--candle(gold accent),--ember(rust accent),--text,--text-bright,--text-dim,--text-faint,--parch(inverted blocks),--c-community,--c-founder,--c-practitioner - Typography: Brygada 1918 (serif, display/headings) + Commit Mono (monospace, body/UI/everything structural) — loaded via Google Fonts in
nuxt.config.ts - Theme:
primary: amber,neutral: stone— configured inapp/app.config.ts. Tailwind@thememaps--font-sansand--font-monoto Commit Mono,--font-displayto Brygada 1918 - Key classes:
.btn/.btn-primary/.btn-danger(buttons),.field(form groups),.badge(circle badges),.section-label(10px uppercase headers),.dashed-box(bordered containers),.section-divider - Visual language: Dashed borders (1px dashed), cream backgrounds, no rounded corners, text-forward density, minimal decoration
- Color mode:
@nuxtjs/color-modewith preferencesystem, fallbacklight. Dark mode via.darkclass on<html> - Layouts:
default(sidebar + main, member/public pages),admin(sidebar + main, admin pages),landing(horizontal nav, unused)
Environment
Copy .env.example to .env. Required: MONGODB_URI, JWT_SECRET, RESEND_API_KEY, HELCIM_API_TOKEN, SLACK_BOT_TOKEN. Public vars are prefixed NUXT_PUBLIC_. The NUXT_PUBLIC_COMING_SOON flag gates access behind a launch page.
Conventions
- All frontend code is plain JavaScript (not TypeScript), using Vue 3 Composition API
- Server utilities auto-imported by Nitro — no explicit imports needed in API routes
- Use
USwitch(notUToggle) — this is the correct Nuxt UI 3+ component name - No fallback/placeholder data — always use real data
- Follow Nuxt 4 file-based routing conventions for route naming
- Always check Nuxt UI 4 latest documentation on the web when implementing UI components
- Auth API responses (
/api/auth/status,/api/auth/member) must includestatusin the returned member object —useMemberStatusdefaults toPENDING_PAYMENTif missing - Helcim payment testing requires ngrok:
npx nuxi dev --httpsthenngrok http https://localhost:3000— Helcim blocks localhost origins - The
/api/helcim/initialize-paymentendpoint skips auth forevent_tickettype payments (public users can buy tickets)
Product Spec
The sections below describe planned and in-progress features for reference.
Member Features
- Profiles with privacy controls (public/members-only/private per field)
- Member updates/mini blog with rich text and images
- Peer support system with Cal.com integration for 1:1 scheduling
Events System
- RSVP with capacity limits and waitlist management
- Calendar export (.ics), ticketing, series passes
- Member-proposed events with interest threshold
Resources (Planned)
- Learning paths by circle, templates and tools, case studies
- Tag by circle relevance, download tracking, version control