# 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 ```bash # 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 ```bash # 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 ```bash # 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):** ```bash # 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-config` → `src/payload.config.ts` (Payload config) #### Admin Component References Payload admin components use file-based imports with hash notation: ```typescript 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 ```bash # 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 ```bash # 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: ```typescript // 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 - [Payload CMS Docs](https://payloadcms.com/docs) - [Next.js App Router Docs](https://nextjs.org/docs/app) - [Project Setup Guide](./OGB_SETUP_GUIDE.md) - Detailed setup instructions - [Related Project](../daemez.solutions) - Reference for advanced features