bf070ec47f
- 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>
81 lines
3.2 KiB
Markdown
81 lines
3.2 KiB
Markdown
# 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 (1945–2026), 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/`).
|