# 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

```bash
npm run dev        # Start dev server at http://localhost:3000
npm run build      # Production build
npm run preview    # Preview production build
```

**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.

No test framework is currently configured.

## 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-api` for member invitations and notifications
- **Images:** Cloudinary
- **Analytics:** Plausible (`ghostguild.org`)

### Key Directories

- `app/composables/` — State management via `useState()` (no Pinia/Vuex). Key composables: `useAuth`, `useHelcim`, `useMemberPayment`, `useMemberStatus`
- `app/config/` — Circle definitions (`circles.js`) and contribution tiers (`contributions.js`) used across frontend and forms
- `app/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-soon`
- `server/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`, `Update`
- `server/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` / `.dark` blocks in `app/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 in `app/app.config.ts`. Tailwind `@theme` maps `--font-sans` and `--font-mono` to Commit Mono, `--font-display` to 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-mode` with preference `system`, fallback `light`. Dark mode via `.dark` class 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` (not `UToggle`) — 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 include `status` in the returned member object — `useMemberStatus` defaults to `PENDING_PAYMENT` if missing
- Helcim payment testing requires ngrok: `npx nuxi dev --https` then `ngrok http https://localhost:3000` — Helcim blocks localhost origins
- The `/api/helcim/initialize-payment` endpoint skips auth for `event_ticket` type 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
