Markdown Converter
Agent skill for markdown-converter
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Sign in to like and favorite skills
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
This is a multi-event RSVP, waiver signing, and attendance tracking system for Fubar Labs (New Jersey's first hackerspace) built with Remix and deployed to Cloudflare Pages. The system manages robot combat events, maker faires, workshops, and community gatherings with persistent database storage.
When working with this codebase:
gh) for all version control operationsUser Browser ↓ Remix App (Cloudflare Pages) ↓ Loaders (Data Fetching) ↓ Database (D1 or Turso) ↓ Actions (Form Submissions) ↓ Server-Side Logic ↓ Response (SSR or JSON)
app/ ├── routes/ # File-based routing │ ├── _index.tsx # Homepage - upcoming events list │ ├── events.$id.tsx # Event detail + RSVP form │ ├── events.$id.waiver.tsx # Waiver signing page │ ├── events.$id.checkin.tsx # QR code check-in page │ ├── my-rsvps.tsx # User's RSVP history │ ├── admin.tsx # Admin layout with auth check │ ├── admin._index.tsx # Admin dashboard │ ├── admin.events.tsx # Event management │ ├── admin.events.new.tsx # Create new event │ ├── admin.events.$id.tsx # Edit event + attendee list │ └── admin.login.tsx # Admin login ├── components/ │ ├── ui/ # shadcn/ui components │ ├── EventCard.tsx # Event preview card │ ├── RSVPForm.tsx # Reusable RSVP form │ ├── WaiverForm.tsx # Digital waiver component │ ├── QRCodeDisplay.tsx # QR code generator │ ├── CheckInScanner.tsx # QR scanner for check-ins │ └── AdminNav.tsx # Admin navigation ├── lib/ │ ├── db.server.ts # Database connection + Drizzle setup │ ├── schema.ts # Drizzle schema definitions │ ├── auth.server.ts # Session management │ ├── email.server.ts # Email sending utilities │ └── qr.server.ts # QR code generation ├── utils/ │ ├── validation.ts # Zod schemas for forms │ └── date.ts # Date formatting helpers └── root.tsx # App shell, meta tags, global styles db/ ├── migrations/ # SQL migration files └── seed.ts # Sample data for development tests/ ├── routes/ # Route tests (loaders, actions) ├── components/ # Component tests └── e2e/ # Playwright end-to-end tests public/ ├── favicon.ico └── robots.txt
# Setup pnpm install # Install dependencies # Development pnpm dev # Start dev server (localhost:3000) pnpm typecheck # Run TypeScript type checking # Database pnpm db:generate # Generate migrations from schema pnpm db:migrate # Run migrations (local) pnpm db:migrate:prod # Run migrations (production D1) pnpm db:seed # Seed database with sample data pnpm db:studio # Open Drizzle Studio (database GUI) # Testing (ALWAYS run before committing) pnpm test # Run all tests (Vitest) pnpm test:watch # Run tests in watch mode pnpm test:e2e # Run Playwright E2E tests pnpm test:e2e:ui # Run E2E tests with UI pnpm test:coverage # Run tests with coverage report # Code Quality pnpm lint # ESLint + Prettier check pnpm format # Format code with Prettier pnpm validate # Run typecheck + lint + test # Build & Deploy pnpm build # Build for production pnpm preview # Preview production build locally pnpm deploy # Deploy to Cloudflare Pages pnpm cf:tail # Tail Cloudflare logs # Git and GitHub (using gh CLI) gh pr create --title "feat: add waiver signing" --body "Description" gh pr list gh pr status gh issue create --title "Bug: RSVP form validation" --body "Steps to reproduce"
ALWAYS follow this workflow for new features:
Explore: Read relevant files without writing code yet
Plan: Create detailed implementation plan
Code: Implement the solution
Commit: Create commit and PR
CRITICAL: This project follows TDD. ALWAYS write tests before implementation.
Write Tests First
# Tell Claude explicitly: # "Write tests for X using TDD. Do not create mock implementations."
Implement Code
# Tell Claude explicitly: # "Now implement code to pass the tests. Do not modify the tests."
Refactor
Branch Naming:
feature/* - New features (e.g., feature/waiver-signing)fix/* - Bug fixes (e.g., fix/rsvp-validation)test/* - Test improvementsrefactor/* - Code refactoringdocs/* - Documentation updatesCommit Message Format (Conventional Commits):
feat: add digital waiver signing flow fix: resolve RSVP capacity validation error test: add E2E tests for check-in workflow refactor: extract QR code component docs: update CLAUDE.md with deployment steps chore: update dependencies
Pre-Commit Checklist:
pnpm validate # Runs typecheck + lint + test git status # Review staged changes git diff # Review actual changes
When adding new components:
When adding new routes:
events { id: string (uuid) name: string slug: string (unique, url-friendly) description: text date: date timeStart: time timeEnd: time location: string capacity: integer (nullable) requiresWaiver: boolean waiverText: text (nullable) discordLink: string (nullable) status: enum ['draft', 'published', 'cancelled'] createdAt: timestamp updatedAt: timestamp }
attendees { id: string (uuid) email: string (unique) name: string createdAt: timestamp }
rsvps { id: string (uuid) eventId: string (FK → events.id) attendeeId: string (FK → attendees.id) status: enum ['yes', 'no', 'maybe', 'waitlist', 'cancelled'] notes: text (nullable) createdAt: timestamp updatedAt: timestamp UNIQUE (eventId, attendeeId) }
waivers { id: string (uuid) eventId: string (FK → events.id) attendeeId: string (FK → attendees.id) waiverText: text (snapshot of waiver at signing time) signedAt: timestamp ipAddress: string consent: boolean (must be true) UNIQUE (eventId, attendeeId) }
attendance { id: string (uuid) eventId: string (FK → events.id) attendeeId: string (FK → attendees.id) checkedInAt: timestamp checkInMethod: enum ['manual', 'qr_code', 'email_link'] UNIQUE (eventId, attendeeId) }
events.slug (unique)events.date (for upcoming events queries)rsvps.eventId (for attendee lists)rsvps.attendeeId (for user's RSVP history)attendance.eventId (for check-in stats)Required in
.env file (see .env.example for reference):
# Session Secret (generate with: openssl rand -base64 32) SESSION_SECRET=your_random_secret_key # Database (choose one) # Option 1: Cloudflare D1 (production) DATABASE_ID=your_d1_database_id # Option 2: Turso (alternative) DATABASE_URL=libsql://your-database.turso.io DATABASE_AUTH_TOKEN=your_turso_token # Email Service (choose one) # Option 1: Resend (recommended) RESEND_API_KEY=re_your_key [email protected] # Option 2: SendGrid SENDGRID_API_KEY=SG.your_key [email protected] # Admin Credentials (change in production!) [email protected] ADMIN_PASSWORD_HASH=your_bcrypt_hash # Cloudflare (for deployment) CLOUDFLARE_ACCOUNT_ID=your_account_id CLOUDFLARE_API_TOKEN=your_api_token # Optional DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...
Install Wrangler CLI:
pnpm add -g wrangler wrangler login
Create D1 Database:
wrangler d1 create fubar-rsvp # Copy the database_id to wrangler.toml
Run Migrations:
pnpm db:migrate:prod
Deploy:
pnpm deploy # Or connect GitHub repo for automatic deployments
Set Environment Variables:
wrangler pages secret put SESSION_SECRET wrangler pages secret put RESEND_API_KEY wrangler pages secret put ADMIN_PASSWORD_HASH
Connect Repository:
pnpm buildbuild/client/Auto-Deployments:
main branch → Production deploymentStart Dev Server:
pnpm dev # Runs on http://localhost:3000 # Uses local SQLite database (dev.db)
Test with Production Database:
pnpm dev:remote # Connects to Cloudflare D1 for testing
Run E2E Tests:
pnpm test:e2e # Starts dev server, runs Playwright tests
pnpm test -- --reporter=verbose # See detailed failures pnpm typecheck # Check for type errors
pnpm db:studio # Open GUI to inspect data wrangler d1 execute fubar-rsvp --command "SELECT * FROM events"
wrangler pages deployment tail # View real-time logs pnpm build # Test build locally
git status # View conflicts # Resolve in editor, then: git add <resolved-files> git commit
When ready to add Claude AI:
/api/chat route for streaming responses