Files
denshooter bf070ec47f Fix UI issues, add tests, and patch missing auth on API routes
- Rewrote CandleSection with properly aligned animated flames (fix
  Framer Motion transform-overwrite bug by using left:0 / pixel offsets
  instead of translateX(-50%)); added size prop for inline flames
- Fixed Timeline: CSS dots/line replacing broken SVG estimates, mobile
  padding (pl-10), larger dots, cards grow with content
- Fixed MusicPlayer: actual play/pause (not mute), visibilitychange +
  pagehide handlers so music stops on iOS lock screen / app switch
- Fixed nav: horizontal scroll on mobile (overflow-x-auto whitespace-nowrap)
- Fixed footer: Impressum centered, admin link moved to absolute/hidden
- Removed meine-oma link from TributeSection (page still accessible)
- Added admin auth (isAdmin cookie check) to /api/upload POST,
  /api/contributions/[id] PUT/DELETE, and /api/candles/[id] PUT/DELETE
- Extracted sp(), relativeTime(), formatDate() to src/lib/utils.ts
- Added Vitest with 15 unit tests for utility functions (npm test)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-21 23:20:48 +01:00

81 lines
3.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
Memorial website for Maria Malejka (19452026), built in German. Production-deployed at `maria-malejka.de`.
## Commands
```bash
# Development
npm run dev # Start dev server (with Turbopack)
npm run build # Production build
npm run start # Start production server
# Docker (local development)
docker compose up # Start with Docker Compose
docker compose build # Rebuild Docker image
```
No linting or test scripts are configured.
## Environment Variables
```
ADMIN_PASSWORD= # Admin dashboard password (SHA256 hashed)
DATA_DIR=/data # SQLite database + uploads location
NEXT_PUBLIC_URL= # Public site URL (used for OG tags, QR codes)
OLLAMA_URL= # AI moderation endpoint (default: http://localhost:11434)
```
## Architecture
### Tech Stack
- **Next.js** (App Router) + **React 18** + **TypeScript**
- **SQLite** via Node.js built-in `node:sqlite` (no ORM)
- **Tailwind CSS** with custom warm-toned palette (`cream`, `warm-brown`, `warm-gold`)
- **Framer Motion** for animations
- **Ollama** (llama3.2) for AI content moderation
### Data Layer
Database singleton in `src/lib/db.ts` (`getDb()`). All API routes use `export const runtime = 'nodejs'` to access SQLite and the filesystem.
Key tables: `memories`, `media`, `candles`, `timeline`, `contributions`, `recipes`.
The `contributions` table is the user submission queue — content flows through `pending → approved/rejected/flagged`. Status `flagged` means the auto-moderator caught something but admin review is needed.
### Content Moderation Pipeline (`/api/contributions` POST)
1. Hardcoded German bad-word list → auto-flag
2. Ollama AI review (fire-and-forget, 15s timeout, very lenient prompt) → flag if rejected
3. Clean content → immediately `approved`
### File Uploads
`/api/upload` handles photos, videos, and audio. SHA256 deduplication prevents duplicate files. Files are stored in `$DATA_DIR/uploads/{photos,videos,music}/` with UUID filenames. The `/api/files/[...path]` route serves them with 1-year immutable cache headers.
### Home Page Data Fetching (`src/app/page.tsx`)
Server component with `dynamic = 'force-dynamic'` and `revalidate = 10`. Fetches all data server-side and merges:
- Admin memories + approved memory contributions
- Official timeline + approved timeline contributions
- Photos from media table + timeline entries + photo contributions (deduplicated by filename)
### Admin Auth
Cookie `admin_auth` with SHA256(password). Routes at `/api/auth` (GET/POST/DELETE). 30-day expiry.
### Styling Conventions
- Fonts: `font-cormorant` (headings, serif/italic) and `font-lora` (body)
- All UI text is in German
- Custom Tailwind colors: `cream`, `warm-brown`, `warm-brown-light`, `warm-gold`, `warm-gold-light`, `warm-border`
- Animations: `animate-fade-in`, `animate-float` (defined in tailwind.config.ts)
### Deployment
Docker multi-stage build → standalone Next.js output. The container runs as non-root user `nextjs` (uid 1001). Data persisted via volume at `/app/data`. Deployed behind a reverse proxy (no external port exposure). CI/CD via Gitea Actions (`.gitea/workflows/`).