# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview BlogWoman.de frontend - a Next.js 16 application consuming Payload CMS as a headless backend. This is a multi-tenant system where **Tenant ID 9 (slug: blogwoman)** is the target tenant. **Tech Stack:** Next.js 16, React 19, TypeScript, Tailwind CSS 4 **Backend API:** https://cms.c2sgmbh.de/api (Production) **Package Manager:** pnpm ## Commands ```bash pnpm dev # Development server (localhost:3000) pnpm build # Production build pnpm start # Start production server pnpm lint # ESLint ``` ## Environment Variables Create `.env.local`: ```env NEXT_PUBLIC_PAYLOAD_URL=https://cms.c2sgmbh.de NEXT_PUBLIC_API_URL=https://cms.c2sgmbh.de/api NEXT_PUBLIC_TENANT_ID=9 NEXT_PUBLIC_TENANT_SLUG=blogwoman NEXT_PUBLIC_SITE_URL=https://blogwoman.de NEXT_PUBLIC_UMAMI_HOST=https://analytics.c2sgmbh.de NEXT_PUBLIC_UMAMI_WEBSITE_ID= ``` ## Shared Contracts Package This project uses `@c2s/payload-contracts` for the API client layer. **Architecture:** - `src/lib/cms.ts` — Shared PayloadClient instance (tenant: blogwoman, ID: 9) - `src/lib/api.ts` — API functions powered by contracts client - `src/lib/types.ts` — Local type aliases (simplified for component compatibility) **Contracts Repo:** `github:complexcaresolutions/payload-contracts` ```typescript // How the API client works (src/lib/cms.ts) import { createPayloadClient } from "@c2s/payload-contracts/api-client" export const cms = createPayloadClient({ baseUrl: process.env.NEXT_PUBLIC_PAYLOAD_URL!, tenantId: process.env.NEXT_PUBLIC_TENANT_ID!, }) // Usage in api.ts — tenant isolation is automatic const page = await cms.pages.getPage("home") const posts = await cms.posts.getPosts({ type: "blog", limit: 10 }) const nav = await cms.navigation.getNavigation("header") ``` **Type Bridge:** Local types in `types.ts` use simplified interfaces (e.g., `meta` instead of `seo`). The api.ts bridges between contracts types and local types via `as unknown as`. This will be cleaned up when components are aligned with real CMS types. **Block Catalog:** See `node_modules/@c2s/payload-contracts/docs/BLOCK_CATALOG.md` for all 43 block definitions. **Updating Contracts:** ```bash pnpm update @c2s/payload-contracts # Check for work orders in node_modules/@c2s/payload-contracts/work-orders/ ``` ## Architecture ### Directory Structure ``` src/ ├── app/ # Next.js App Router │ ├── layout.tsx # Root layout (Header/Footer/Analytics) │ ├── page.tsx # Home page │ ├── [slug]/page.tsx # Dynamic pages from Payload │ ├── blog/ # Blog routes │ ├── serien/ # BlogWoman YouTube series pages │ └── favoriten/ # BlogWoman affiliate products ├── components/ │ ├── layout/ # Header, Footer, Navigation, MobileMenu │ ├── blocks/ # CMS block components (see Block System below) │ ├── ui/ # Reusable UI components │ └── analytics/ # UmamiScript ├── lib/ │ ├── api.ts # Payload API client functions │ ├── types.ts # TypeScript types │ └── structuredData.ts # JSON-LD helpers for SEO └── hooks/ └── useAnalytics.ts # Umami event tracking ``` ### API Pattern - CRITICAL **Every API call MUST include tenant filtering:** ```typescript const PAYLOAD_URL = process.env.NEXT_PUBLIC_PAYLOAD_URL const TENANT_ID = process.env.NEXT_PUBLIC_TENANT_ID // CORRECT - always filter by tenant fetch(`${PAYLOAD_URL}/api/pages?where[tenant][equals]=${TENANT_ID}&where[slug][equals]=about`) // WRONG - will return 403 or empty results fetch(`${PAYLOAD_URL}/api/pages?where[slug][equals]=about`) ``` ### Block System Pages from Payload contain a `layout` array of blocks. Each block has a `blockType` field: | Block Type | Purpose | |------------|---------| | `hero-block` | Hero banner with image | | `hero-slider-block` | Multi-slide hero carousel | | `text-block` | Rich text content | | `image-text-block` | Image + text side-by-side | | `card-grid-block` | Card grid layout | | `cta-block` | Call-to-action section | | `posts-list-block` | Blog/news listing | | `testimonials-block` | Customer testimonials | | `faq-block` | FAQ accordion (with JSON-LD) | | `newsletter-block` | Newsletter signup form | | `contact-form-block` | Contact form | | `video-block` | Video embed | | `favorites-block` | Affiliate products (BlogWoman) | | `series-block` | YouTube series overview (BlogWoman) | | `series-detail-block` | Series hero (BlogWoman) | | `video-embed-block` | Privacy-mode video embed | **Block Renderer pattern:** ```typescript // src/components/blocks/index.tsx export function BlockRenderer({ blocks }) { return blocks.map(block => { const Component = blockComponents[block.blockType] return Component ? : null }) } ``` ### BlogWoman-Specific Collections Beyond standard CMS collections (pages, posts, testimonials), BlogWoman uses: - **favorites** - Affiliate products with categories (fashion, beauty, travel, tech, home) and badges (investment-piece, daily-driver, grfi-approved, new, bestseller) - **series** - YouTube series with branding (logo, cover image, brand color) ### API Endpoints Reference | Endpoint | Purpose | |----------|---------| | `GET /api/pages?where[tenant][equals]=9` | Fetch pages | | `GET /api/posts?where[tenant][equals]=9` | Fetch blog posts | | `GET /api/navigations?where[tenant][equals]=9&where[type][equals]=header` | Get navigation | | `GET /api/site-settings?where[tenant][equals]=9` | Site configuration | | `GET /api/favorites?where[tenant][equals]=9` | Affiliate products | | `GET /api/series?where[tenant][equals]=9` | YouTube series | | `POST /api/newsletter/subscribe` | Newsletter signup (body: email, tenantId, source) | | `POST /api/form-submissions` | Contact form submission | **API Documentation:** https://cms.c2sgmbh.de/api/docs (Swagger UI) ## Design System (Styleguide) **Philosophy:** "Editorial Warmth" - Premium but approachable, like a lifestyle magazine. ### Colors (60/30/10 Rule) | Name | Hex | Use | |------|-----|-----| | Ivory | `#F7F3EC` | Backgrounds (60%) | | Sand | `#C6A47E` | Cards, modules (30%) | | Espresso | `#2B2520` | Text, headlines | | Brass | `#B08D57` | Primary buttons, highlights (10%) | | Bordeaux | `#6B1F2B` | Accent for P&L series | | Rosé | `#D4A5A5` | SPARK series accent | | Gold | `#C9A227` | Premium badges | | Soft White | `#FBF8F3` | Cards, surfaces | | Warm Gray | `#DDD4C7` | Borders | **Forbidden:** Neon colors, pure black (#000), pure white (#FFF), cold blue. ### Typography - **Headlines:** Playfair Display (600 weight) - **Body/UI:** Inter (400, 500, 600) - **NO CAPSLOCK HEADLINES** - use uppercase only for small labels with letter-spacing ### Series Pills (BlogWoman) YouTube series use color-coded pills: - GRFI: Sand background - Investment: Brass background - P&L: Bordeaux background - SPARK: Rosé background - Inner Circle: Gold background ## SEO Requirements 1. **Meta tags** from page.meta field 2. **JSON-LD** for Organization, FAQPage, Article schemas 3. **Open Graph** tags for social sharing 4. Sitemap available at: https://cms.c2sgmbh.de/sitemap.xml ## Analytics (Umami) Umami is cookieless and DSGVO-compliant - runs without consent banner. ```typescript // Track custom events import { useAnalytics } from '@/hooks/useAnalytics' const { trackEvent, trackNewsletterSubscribe, trackAffiliateClick } = useAnalytics() ``` ## Documentation References | Document | Path | |----------|------| | Styleguide | `/docs/guides/styleguide.md` | | Universal Features | `/docs/architecture/UNIVERSAL_FEATURES.md` | | API Guide | `/docs/api/API_ANLEITUNG.md` | | SEO | `/docs/guides/SEO_ERWEITERUNG.md` | | Analytics | `/docs/architecture/Analytics.md` | | Frontend Guide | `/docs/guides/FRONTEND.md` | | Development Prompt | `/prompts/2026-01-20_blogwoman-frontend-entwicklung.md` | ## Import Alias `@/*` maps to `./src/*` (configured in tsconfig.json)