chore: Add CLAUDE.md, TODO.md, and fix ReadBooks Tailwind classes

- Add CLAUDE.md with project architecture, conventions, and common tasks
- Add TODO.md with prioritized roadmap (book reviews, CMS, n8n, frontend)
- Fix invalid Tailwind classes in ReadBooks.tsx (h-30 -> h-[7.5rem], w-22 -> w-24)

https://claude.ai/code/session_017E8W9CcHFM5WQVHw74JP34
This commit is contained in:
Claude
2026-02-15 12:59:55 +00:00
committed by denshooter
parent 032568562c
commit 99d0d1dba1
3 changed files with 207 additions and 1 deletions

155
CLAUDE.md Normal file
View File

@@ -0,0 +1,155 @@
# CLAUDE.md - Portfolio Project Guide
## Project Overview
Personal portfolio website for Dennis Konkol (dk0.dev). Built with Next.js 15 (App Router), TypeScript, Tailwind CSS, and Framer Motion. Uses a "liquid" design system with soft gradient colors and glassmorphism effects.
## Tech Stack
- **Framework**: Next.js 15 (App Router), TypeScript 5.9
- **Styling**: Tailwind CSS 3.4 with custom `liquid-*` color tokens
- **Animations**: Framer Motion 12
- **3D**: Three.js + React Three Fiber (shader gradient background)
- **Database**: PostgreSQL via Prisma ORM
- **Cache**: Redis (optional)
- **CMS**: Directus (self-hosted, REST/GraphQL, optional)
- **Automation**: n8n webhooks (status, chat, hardcover, image generation)
- **i18n**: next-intl (EN + DE), message files in `messages/`
- **Monitoring**: Sentry
- **Deployment**: Docker + Nginx, CI via Gitea Actions
## Commands
```bash
npm run dev # Full dev environment (Docker + Next.js)
npm run dev:simple # Next.js only (no Docker)
npm run dev:next # Plain Next.js dev server
npm run build # Production build
npm run lint # ESLint
npm run test # Jest unit tests
npm run test:e2e # Playwright E2E tests
```
## Project Structure
```
app/
[locale]/ # i18n routes (en, de)
page.tsx # Homepage (hero, about, projects, contact)
projects/ # Project listing + detail pages
api/ # API routes
book-reviews/ # Book reviews from Directus CMS
content/ # CMS content pages
hobbies/ # Hobbies from Directus
n8n/ # n8n webhook proxies
hardcover/ # Currently reading (Hardcover API via n8n)
status/ # Activity status (coding, music, gaming)
chat/ # AI chatbot
generate-image/ # AI image generation
projects/ # Projects API (PostgreSQL + Directus fallback)
tech-stack/ # Tech stack from Directus
components/ # React components
About.tsx # About section (tech stack, hobbies, books)
CurrentlyReading.tsx # Currently reading widget (n8n/Hardcover)
ReadBooks.tsx # Read books with ratings (Directus CMS)
Projects.tsx # Featured projects section
Hero.tsx # Hero section
Contact.tsx # Contact form
lib/
directus.ts # Directus GraphQL client (no SDK)
auth.ts # Auth utilities + rate limiting
prisma/
schema.prisma # Database schema
messages/
en.json # English translations
de.json # German translations
docs/ # Documentation
```
## Architecture Patterns
### Data Source Hierarchy (Fallback Chain)
1. Directus CMS (if configured via `DIRECTUS_STATIC_TOKEN`)
2. PostgreSQL (for projects, analytics)
3. JSON files (`messages/*.json`)
4. Hardcoded defaults
5. Display key itself as last resort
All external data sources fail gracefully - the site never crashes if Directus, PostgreSQL, n8n, or Redis are unavailable.
### CMS Integration (Directus)
- REST/GraphQL calls via `lib/directus.ts` (no Directus SDK)
- Collections: `tech_stack_categories`, `tech_stack_items`, `hobbies`, `content_pages`, `projects`, `book_reviews`
- Translations use Directus native translation system (M2O to `languages`)
- Locale mapping: `en` -> `en-US`, `de` -> `de-DE`
### n8n Integration
- Webhook base URL: `N8N_WEBHOOK_URL` env var
- Auth via `N8N_SECRET_TOKEN` and/or `N8N_API_KEY` headers
- All n8n endpoints have rate limiting and timeout protection (10s)
- Hardcover data cached for 5 minutes
### Component Patterns
- Client components with `"use client"` for interactive/data-fetching parts
- `useEffect` for data loading on mount
- `useTranslations` from next-intl for i18n
- Framer Motion `variants` pattern with `staggerContainer` + `fadeInUp`
- Gradient cards with `liquid-*` color tokens and `backdrop-blur-sm`
## Design System
Custom Tailwind colors prefixed with `liquid-`:
- `liquid-sky`, `liquid-mint`, `liquid-lavender`, `liquid-pink`
- `liquid-rose`, `liquid-peach`, `liquid-coral`, `liquid-teal`, `liquid-lime`
Cards use gradient backgrounds (`bg-gradient-to-br from-liquid-*/15 via-liquid-*/10 to-liquid-*/15`) with `border-2` and `rounded-xl`.
## Key Environment Variables
```bash
# Required for CMS
DIRECTUS_URL=https://cms.dk0.dev
DIRECTUS_STATIC_TOKEN=...
# Required for n8n features
N8N_WEBHOOK_URL=https://n8n.dk0.dev
N8N_SECRET_TOKEN=...
N8N_API_KEY=...
# Database
DATABASE_URL=postgresql://...
# Optional
REDIS_URL=redis://...
SENTRY_DSN=...
```
## Conventions
- Language: Code in English, user-facing text via i18n (EN + DE)
- Commit messages: Conventional Commits (`feat:`, `fix:`, `chore:`)
- Components: PascalCase files in `app/components/`
- API routes: kebab-case directories in `app/api/`
- CMS data always has a static fallback - never rely solely on Directus
- Error logging: Only in `development` mode (`process.env.NODE_ENV === "development"`)
- No emojis in code unless explicitly requested
## Common Tasks
### Adding a new CMS-managed section
1. Define the GraphQL query + types in `lib/directus.ts`
2. Create an API route in `app/api/<name>/route.ts`
3. Create a component in `app/components/<Name>.tsx`
4. Add i18n keys to `messages/en.json` and `messages/de.json`
5. Integrate into the parent component (usually `About.tsx`)
### Adding i18n strings
1. Add keys to `messages/en.json` and `messages/de.json`
2. Access via `useTranslations("key.path")` in client components
3. Or `getTranslations("key.path")` in server components
### Working with Directus collections
- All queries go through `directusRequest()` in `lib/directus.ts`
- Uses GraphQL endpoint (`/graphql`)
- 2-second timeout, graceful null fallback
- Translations filtered by `languages_code.code` matching Directus locale

51
TODO.md Normal file
View File

@@ -0,0 +1,51 @@
# TODO - Portfolio Roadmap
## Book Reviews (Neu)
- [ ] **Directus Collection erstellen**: `book_reviews` mit Feldern:
- `status` (draft/published)
- `book_title` (String)
- `book_author` (String)
- `book_image` (String, URL zum Cover)
- `rating` (Integer, 1-5)
- `hardcover_id` (String, optional)
- `finished_at` (Datetime, optional)
- Translations: `review` (Text) + `languages_code` (FK)
- [ ] **n8n Workflow**: Automatisch Directus-Entwurf erstellen wenn Buch auf Hardcover als "gelesen" markiert wird
- [ ] **Hardcover GraphQL Query** für gelesene Bücher: `status_id: {_eq: 3}` (Read)
- [ ] **Erste Testdaten**: 2-3 gelesene Bücher mit Rating + Kommentar in Directus anlegen
## Directus CMS
- [ ] Messages Collection: `messages` mit key + translations (ersetzt `messages/*.json`)
- [ ] Projects vollständig zu Directus migrieren (`node scripts/migrate-projects-to-directus.js`)
- [ ] Directus Webhooks einrichten: On-Demand ISR Revalidation bei Content-Änderungen
- [ ] Directus Roles: Public Read Token, Admin Write
## n8n Integrationen
- [ ] Hardcover "Read Books" Webhook: Gelesene Bücher automatisch in Directus importieren
- [ ] Spotify Now Playing verbessern: Album-Art Caching
- [ ] Discord Rich Presence: Gaming-Status automatisch aktualisieren
## Frontend
- [ ] Dark Mode Support (Theme Toggle)
- [ ] Blog/Artikel Sektion (Directus-basiert)
- [ ] Projekt-Detail Seite: Bildergalerie/Lightbox
- [ ] Performance: Bilder auf Next.js `<Image>` umstellen (statt `<img>`)
- [ ] SEO: Structured Data (JSON-LD) für Projekte
## Testing & Qualität
- [ ] Jest Tests für neue API-Routes (`book-reviews`, `hobbies`, `tech-stack`)
- [ ] Playwright E2E: Book Reviews Sektion testen
- [ ] Lighthouse Score > 95 auf allen Seiten sicherstellen
- [ ] Accessibility Audit (WCAG 2.1 AA)
## DevOps
- [ ] Staging Environment aufräumen und dokumentieren
- [ ] GitHub Actions Migration (von Gitea Actions)
- [ ] Docker Image Size optimieren (Multi-Stage Build prüfen)
- [ ] Health Check Endpoint erweitern: Directus + n8n Connectivity

View File

@@ -133,7 +133,7 @@ const ReadBooks = () => {
transition={{ duration: 0.5, delay: 0.2 + index * 0.1 }}
className="flex-shrink-0"
>
<div className="relative w-20 h-30 sm:w-22 sm:h-32 rounded-lg overflow-hidden shadow-lg border-2 border-white/50">
<div className="relative w-20 h-[7.5rem] sm:w-24 sm:h-32 rounded-lg overflow-hidden shadow-lg border-2 border-white/50">
<img
src={review.book_image}
alt={review.book_title}