feat: add shared @sexy.pivoine.art/types package and fix type safety across frontend/backend
- Create packages/types with shared TypeScript domain model interfaces (User, Video, Model, Article, Comment, Recording, etc.) - Wire both frontend and backend packages to use @sexy.pivoine.art/types via workspace:* - Update backend Pothos objectRef types to use shared interfaces instead of inline types - Update frontend $lib/types.ts to re-export from shared package - Fix all type errors introduced by more accurate nullable types (avatar/banner as string|null UUIDs, author nullable, events/device_info as object[]) - Add artist_name to comment user select in backend resolver - Widen utility function signatures (getAssetUrl, getUserInitials, calcReadingTime) to accept null/undefined Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
94
CLAUDE.md
Normal file
94
CLAUDE.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Overview
|
||||
|
||||
`sexy.pivoine.art` is a self-hosted adult content platform (18+) built as a pnpm monorepo with three packages: `frontend` (SvelteKit 5), `backend` (Fastify + GraphQL), and `buttplug` (hardware integration via WebBluetooth/WASM).
|
||||
|
||||
## Common Commands
|
||||
|
||||
Run from the repo root unless otherwise noted.
|
||||
|
||||
```bash
|
||||
# Development
|
||||
pnpm dev:data # Start postgres & redis via Docker
|
||||
pnpm dev:backend # Start backend on http://localhost:4000
|
||||
pnpm dev # Start backend + frontend (frontend on :3000)
|
||||
|
||||
# Linting & Formatting
|
||||
pnpm lint # ESLint across all packages
|
||||
pnpm lint:fix # Auto-fix ESLint issues
|
||||
pnpm format # Prettier format all files
|
||||
pnpm format:check # Check formatting without changes
|
||||
|
||||
# Build
|
||||
pnpm build:frontend # SvelteKit production build
|
||||
pnpm build:backend # Compile backend TypeScript to dist/
|
||||
|
||||
# Database migrations (from packages/backend/)
|
||||
pnpm migrate # Run pending Drizzle migrations
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
### Monorepo Layout
|
||||
|
||||
```
|
||||
packages/
|
||||
frontend/ # SvelteKit 2 + Svelte 5 + Tailwind CSS 4
|
||||
backend/ # Fastify v5 + GraphQL Yoga v5 + Drizzle ORM
|
||||
buttplug/ # TypeScript/Rust hybrid, compiles to WASM
|
||||
```
|
||||
|
||||
### Backend (`packages/backend/src/`)
|
||||
|
||||
- **`index.ts`** — Fastify server entry: registers plugins (CORS, multipart, static), mounts GraphQL at `/graphql`, serves transformed assets at `/assets/:id`
|
||||
- **`graphql/builder.ts`** — Pothos schema builder (code-first GraphQL)
|
||||
- **`graphql/context.ts`** — Injects `currentUser` from Redis session into every request
|
||||
- **`lib/auth.ts`** — Session management: `nanoid(32)` token stored in Redis with 24h TTL, set as httpOnly cookie
|
||||
- **`db/schema/`** — Drizzle ORM table definitions (users, videos, files, comments, gamification, etc.)
|
||||
- **`migrations/`** — SQL migration files managed by Drizzle Kit
|
||||
|
||||
### Frontend (`packages/frontend/src/`)
|
||||
|
||||
- **`lib/api.ts`** — GraphQL client (graphql-request)
|
||||
- **`lib/services.ts`** — All API calls (login, videos, comments, models, etc.)
|
||||
- **`lib/types.ts`** — Shared TypeScript types
|
||||
- **`hooks.server.ts`** — Auth guard: reads session cookie, fetches `me` query, redirects if needed
|
||||
- **`routes/`** — SvelteKit file-based routing: `/`, `/login`, `/signup`, `/me`, `/models`, `/models/[slug]`, `/videos`, `/play/[slug]`, `/magazine`, `/leaderboard`
|
||||
|
||||
### Asset Pipeline
|
||||
|
||||
Backend serves images with server-side Sharp transforms, cached to disk as WebP. Presets: `mini` (80×80), `thumbnail` (300×300), `preview` (800px wide), `medium` (1400px wide), `banner` (1600×480 cropped).
|
||||
|
||||
### Gamification
|
||||
|
||||
Points + achievements system tracked in `user_points` and `user_stats` tables. Logic in `packages/backend/src/lib/gamification.ts` and the `gamification` resolver.
|
||||
|
||||
## Code Style
|
||||
|
||||
- **TypeScript strict mode** in all packages
|
||||
- **ESLint flat config** (`eslint.config.js` at root) — `any` is allowed but discouraged; enforces consistent type imports
|
||||
- **Prettier**: 2-space indent, trailing commas, 100-char line width, Svelte plugin
|
||||
- Migrations folder (`packages/backend/src/migrations/`) is excluded from lint
|
||||
|
||||
## Environment Variables (Backend)
|
||||
|
||||
| Variable | Purpose |
|
||||
|----------|---------|
|
||||
| `DATABASE_URL` | PostgreSQL connection string |
|
||||
| `REDIS_URL` | Redis connection string |
|
||||
| `COOKIE_SECRET` | Session cookie signing |
|
||||
| `CORS_ORIGIN` | Frontend origin URL |
|
||||
| `UPLOAD_DIR` | File storage path |
|
||||
| `SMTP_HOST/PORT/EMAIL_FROM` | Email (Nodemailer) |
|
||||
|
||||
## Docker
|
||||
|
||||
```bash
|
||||
docker compose up -d # Start all services (postgres, redis, backend, frontend)
|
||||
arty up -d <service> # Preferred way to manage containers in this project
|
||||
```
|
||||
|
||||
Production images are built and pushed to `dev.pivoine.art` via Gitea Actions on push to `main`.
|
||||
Reference in New Issue
Block a user