Files
ogb-solutions/CLAUDE.md
T
oscar 9842a7a0e3 feat: initial PayloadCMS 3.64.0 setup for OGB Solutions
- PayloadCMS 3.64.0 + Next.js 15.4.7 + React 19.1.0
- PostgreSQL database configured
- Plugins: form-builder, search, nested-docs, seo, redirects
- Basic collections: Pages, Posts, Categories, Media, Users
- Basic Header/Footer globals
- Ready for Kit Digital grant enhancements
2025-11-17 08:33:12 +01:00

14 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

OGB Solutions is a personal branding website built on PayloadCMS 3.64.0 and Next.js 15.4.7. The project serves as Oscar Gimenez's professional portfolio and meets Kit Digital grant requirements for Spanish businesses.

Technology Stack:

  • PayloadCMS 3.64.0 (headless CMS)
  • Next.js 15.4.7 (App Router)
  • React 19.1.0
  • PostgreSQL (via @payloadcms/db-postgres)
  • TypeScript 5.7.3
  • TailwindCSS 3.4.3 + shadcn/ui
  • Lexical editor for rich text
  • pnpm (package manager)

Related Project: This project is derived from /home/oscar/daemez.io/x/daemez.solutions, a B2B corporate site. When adding features, you may reference Daemez for structure but adapt content and tone for personal branding rather than corporate B2B.

Essential Commands

Development

# Install dependencies
pnpm install

# Start development server (http://localhost:3000)
pnpm dev

# Build for production
pnpm build

# Start production server
pnpm start

# Dev with production mode (clean build + start)
pnpm dev:prod

Code Quality

# Run linter
pnpm lint

# Fix linting issues
pnpm lint:fix

# Run all tests (integration + e2e)
pnpm test

# Run integration tests only (Vitest)
pnpm test:int

# Run e2e tests only (Playwright)
pnpm test:e2e

PayloadCMS Operations

# Generate TypeScript types from Payload config
pnpm generate:types

# Generate import map for admin panel
pnpm generate:importmap

# Access Payload CLI directly
pnpm payload [command]

Database Operations (PostgreSQL)

Local development: The Postgres adapter has push: true enabled for development, allowing schema changes without migrations. This is safe ONLY when pointing to a local database.

Creating migrations (when deploying to production):

# Create a new migration after schema changes
pnpm payload migrate:create

# Run pending migrations on server
pnpm payload migrate

Important: Never run migrations with push: true against production data.

Architecture

Monorepo Structure

This is a monorepo with backend (PayloadCMS) and frontend (Next.js) in the same codebase:

src/
├── app/                    # Next.js App Router
│   ├── (frontend)/         # Public website routes
│   └── (payload)/          # PayloadCMS admin panel
├── collections/            # Payload collections (data models)
│   ├── Pages/              # Landing pages with layout builder
│   ├── Posts/              # Blog posts with rich content
│   ├── Media/              # Uploads (images, files)
│   ├── Categories/         # Taxonomy for organizing posts
│   └── Users/              # Authentication-enabled users
├── globals/                # Site-wide settings
│   ├── Header/             # Navigation configuration
│   └── Footer/             # Footer configuration
├── blocks/                 # Reusable content blocks for layout builder
│   ├── ArchiveBlock/       # Post listings
│   ├── CallToAction/       # CTA sections
│   ├── Content/            # Rich text content
│   ├── MediaBlock/         # Image/video blocks
│   ├── Banner/             # Alert/announcement banners
│   ├── Code/               # Syntax-highlighted code blocks
│   └── Form/               # Contact forms
├── heros/                  # Hero section variants
│   ├── HighImpact/         # Full-screen hero
│   ├── MediumImpact/       # Standard hero
│   ├── LowImpact/          # Minimal hero
│   └── PostHero/           # Blog post hero
├── components/             # React components
├── fields/                 # Reusable Payload field configs
├── access/                 # Access control policies
├── hooks/                  # Payload lifecycle hooks
├── utilities/              # Helper functions
└── payload.config.ts       # Main Payload configuration

Key Architectural Patterns

1. Layout Builder System

Pages use a blocks-based layout builder that allows content editors to compose pages from reusable blocks. Each block has:

  • config.ts - Payload field configuration
  • Component.tsx - React component for frontend rendering
  • Server-side rendering via Next.js App Router

2. Draft Preview & Live Preview

Both Pages and Posts support:

  • Draft mode: Preview unpublished content via secure tokens
  • Live preview: Real-time preview in admin panel while editing
  • Scheduled publishing: Uses Payload jobs queue for timed publication

3. On-Demand Revalidation

Hooks automatically revalidate Next.js cache when content changes:

  • revalidatePage - Triggered on page updates
  • revalidatePost - Triggered on post updates
  • revalidateHeader - Triggered on navigation changes
  • revalidateFooter - Triggered on footer changes

4. SEO Integration

Using @payloadcms/plugin-seo for comprehensive SEO management:

  • Auto-generates meta tags
  • Open Graph support
  • Twitter Card support
  • Sitemap generation (via next-sitemap)

5. Access Control

Three-tier access system:

  • authenticated - Only logged-in users
  • authenticatedOrPublished - Users or published content (public)
  • anyone - Public access

Collections enforce access at the API level, not just UI.

Collections Deep Dive

Pages Collection

  • Purpose: Marketing pages, landing pages, about, contact
  • Features: Layout builder with hero variants, draft preview, SEO
  • Blocks Available: CallToAction, Content, MediaBlock, Archive, FormBlock
  • URL Pattern: /{slug} (homepage is slug: "home")

Posts Collection

  • Purpose: Blog articles, news, thought leadership
  • Features: Rich text editor (Lexical), categories, related posts, author attribution
  • Content Blocks: Banner, Code, MediaBlock (inline content blocks)
  • URL Pattern: /posts/{slug}

Media Collection

  • Purpose: Asset management (images, videos, files)
  • Features: Focal point selection, manual resizing, responsive image optimization
  • Storage: Uses Sharp for image processing

Categories Collection

  • Purpose: Taxonomy for organizing posts
  • Features: Nested categories (via @payloadcms/plugin-nested-docs)
  • Current Limitations: Basic implementation (name + slug only)

Users Collection

  • Purpose: Admin authentication
  • Features: Access to admin panel, content authorship
  • Security: Authentication required for all CMS operations

Important Conventions

Path Aliases

TypeScript path aliases are configured in tsconfig.json:

  • @/*src/* (all source files)
  • @payload-configsrc/payload.config.ts (Payload config)

Admin Component References

Payload admin components use file-based imports with hash notation:

components: {
  RowLabel: '@/Header/RowLabel#RowLabel'
}

Hook Execution

Payload hooks run in this order:

  1. beforeValidate
  2. beforeChange
  3. afterChange
  4. afterRead
  5. afterDelete

Use beforeChange for data transformation, afterChange for side effects (like revalidation).

Environment Variables

Required variables (see .env.example):

  • DATABASE_URI - PostgreSQL connection string
  • PAYLOAD_SECRET - JWT encryption key
  • NEXT_PUBLIC_SERVER_URL - Base URL for links/CORS
  • CRON_SECRET - For scheduled publishing authentication
  • PREVIEW_SECRET - For secure draft previews

Plugin Configuration

Active Plugins

  1. @payloadcms/plugin-form-builder - Contact forms with email notifications
  2. @payloadcms/plugin-search - Full-text search (currently posts only)
  3. @payloadcms/plugin-nested-docs - Hierarchical categories
  4. @payloadcms/plugin-seo - Meta tags, Open Graph, Twitter Cards
  5. @payloadcms/plugin-redirects - URL redirect management

Plugin Configuration Location

All plugins configured in src/plugins/index.ts. When adding new collections to search, update the searchPlugin collections array.

Testing Strategy

Integration Tests (Vitest)

  • Location: tests/int/**/*.int.spec.ts
  • Purpose: Test Payload API endpoints, hooks, access control
  • Environment: jsdom with React testing library
  • Run: pnpm test:int

E2E Tests (Playwright)

  • Location: tests/e2e/**/*.e2e.spec.ts
  • Purpose: Test full user flows, admin panel, frontend
  • Browser: Chromium (Desktop Chrome)
  • Run: pnpm test:e2e

Running Single Tests

# Single integration test
pnpm exec vitest run tests/int/api.int.spec.ts

# Single e2e test
pnpm exec playwright test tests/e2e/frontend.e2e.spec.ts

Grant Requirements (Kit Digital)

This project must meet Spanish government grant requirements. Ensure these features remain functional:

Mandatory Features

  • Minimum 3 pages (home, about, contact)
  • Responsive design (mobile, tablet, desktop)
  • Contact form functionality
  • WCAG 2.1 AA accessibility compliance
  • Self-managed CMS (PayloadCMS admin)
  • SEO optimization (meta tags, sitemap)
  • 12-month hosting and domain in beneficiary name

Testing Accessibility

# Run Playwright accessibility tests
pnpm test:e2e

# Manual check: Chrome DevTools Lighthouse
# 1. pnpm dev
# 2. Open http://localhost:3000
# 3. Chrome DevTools → Lighthouse → Run accessibility audit

Development Workflow

Adding a New Collection

  1. Create collection file in src/collections/CollectionName/index.ts
  2. Define fields, access control, hooks
  3. Register in src/payload.config.ts collections array
  4. Run pnpm generate:types to update TypeScript types
  5. Add to search plugin if searchable (in src/plugins/index.ts)
  6. Create migration if deploying to production: pnpm payload migrate:create

Adding a New Block

  1. Create block directory in src/blocks/BlockName/
  2. Add config.ts (Payload field config)
  3. Add Component.tsx (React rendering component)
  4. Register block in relevant collection (Pages or Posts)
  5. Add to RenderBlocks.tsx for frontend rendering

Adding a New Page

  1. Log into admin: http://localhost:3000/admin
  2. Navigate to Pages collection
  3. Click "Create New"
  4. Set slug (e.g., "about" → URL: /about)
  5. Choose hero type
  6. Build layout with blocks
  7. Configure SEO metadata
  8. Save as draft or publish

Modifying Header/Footer

  1. Navigate to Globals → Header or Footer in admin
  2. Modify navigation items
  3. Changes automatically revalidate frontend via hooks
  4. For code changes, edit src/Header/config.ts or src/Footer/config.ts

Common Pitfalls

TypeScript Errors After Schema Changes

Problem: TypeScript errors about missing fields after changing Payload config. Solution: Always run pnpm generate:types after modifying collections/globals.

Image Not Loading

Problem: Uploaded images return 404. Solution:

  • Check NEXT_PUBLIC_SERVER_URL in .env
  • Verify Sharp installation: pnpm rebuild sharp
  • Check next.config.js remotePatterns configuration

Draft Preview Not Working

Problem: Preview links return 404 or show published version. Solution:

  • Verify PREVIEW_SECRET in .env
  • Check generatePreviewPath utility is correctly configured
  • Ensure draft is saved before previewing

Revalidation Not Triggering

Problem: Content changes don't appear on frontend immediately. Solution:

  • Check hooks are registered in collection config
  • Verify Next.js is running in dev mode (revalidation is automatic)
  • In production, check afterChange hooks are executing

Migration Conflicts

Problem: pnpm payload migrate fails with conflicts. Solution:

  • Never run migrations against a database with push: true
  • Set push: false in payload.config.ts for production databases
  • Manually resolve migration conflicts in generated SQL files

Project-Specific Notes

Personal Branding vs Corporate

This is a personal branding website, not corporate B2B. When adding features:

  • Use first-person tone ("I", "my work") not third-person ("we", "our services")
  • Focus on portfolio/projects, not services/products
  • CTAs should be "Hire Me", "Get in Touch", not "Request Demo"

Future Enhancements Planned

Based on OGB_SETUP_GUIDE.md, these collections may be added:

  • Projects - Portfolio items, case studies
  • Skills - Technology expertise tags
  • Experience - Career timeline
  • Speaking - Conference talks, publications

When implementing these, reference /home/oscar/daemez.io/x/daemez.solutions/src/collections/ for structural inspiration.

Localization

Currently English-only. Multilingual support may be added via:

// In payload.config.ts
localization: {
  locales: [
    { label: 'English', code: 'en' },
    { label: 'Español', code: 'es' },
  ],
  defaultLocale: 'en',
  fallback: true,
}

Deployment

Vercel Deployment

This project is configured for Vercel deployment:

  • PostgreSQL: Use Vercel Postgres or external database
  • Environment variables: Configure in Vercel dashboard
  • Build command: pnpm build
  • Output directory: .next
  • Install command: pnpm install

Manual Deployment

  1. Build project: pnpm build
  2. Run migrations: pnpm payload migrate
  3. Start server: pnpm start
  4. Configure reverse proxy (nginx) to point to port 3000
  5. Use PM2 or similar for process management

Resources