mirror of
https://github.com/complexcaresolutions/frontend.blogwoman.de.git
synced 2026-03-17 15:04:01 +00:00
235 lines
8.1 KiB
Markdown
235 lines
8.1 KiB
Markdown
# 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=<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 ? <Component {...block} /> : 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)
|