# CLAUDE.md

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

## Project Overview

This is a **Next.js 16** blog/portfolio application built with **TypeScript**, **Tailwind CSS**, and **React 19**. The project uses **App Router** with Static Site Generation (SSG) for blog posts stored as Markdown files.

**Design Philosophy:** Industrial/SCP-inspired aesthetic with terminal/cyberpunk elements. Sharp edges, thick borders, monospace fonts, darker color palettes (slate/zinc/cyan/emerald tones). No modern Material UI feel - think government documents, classified files, brutal utilitarian design.

## Development Commands

```bash
# Development server (runs on port 3030)
npm run dev

# Production build
npm run build

# Start production server
npm run start

# Lint code
npm run lint

# Validate all markdown posts (frontmatter, format, tags)
npm run validate-posts
```

## Architecture Overview

### Next.js 16 App Router Structure

```
app/
├── @breadcrumbs/          # Parallel route for breadcrumb navigation
│   ├── default.tsx        # Auto-generated breadcrumbs
│   ├── blog/[...slug]/    # Post-specific breadcrumbs with titles
│   ├── tags/[tag]/        # Tag-specific breadcrumbs
│   └── about/             # Static breadcrumbs
├── blog/
│   ├── page.tsx           # Blog listing with all posts
│   └── [...slug]/         # Dynamic post routes (supports nested paths)
│       ├── page.tsx       # Post rendering with SSG
│       └── not-found.tsx  # Custom 404 for missing posts
├── about/page.tsx
├── layout.tsx             # Root layout with metadata, fonts, breadcrumbs slot
└── page.tsx               # Landing page (hero + featured posts)
```

**Key Architectural Patterns:**

1. **Parallel Routes:** `@breadcrumbs` slot renders dynamic navigation based on current route without prop drilling
2. **Catch-all Routes:** `[...slug]` supports nested blog posts (e.g., `/blog/tech/article-name`)
3. **Static Generation:** `generateStaticParams()` pre-renders all blog posts at build time
4. **Server Components by Default:** All components are RSC unless marked with `'use client'`

### Markdown System

```
content/blog/               # Markdown files (supports nested directories)
├── example.md
└── tech/
    └── article.md

lib/
├── markdown.ts            # Core markdown utilities
│   ├── getPostBySlug()    # Read single post with path sanitization
│   ├── getAllPosts()      # Get all posts, sorted by date, recursive
│   ├── getRelatedPosts()  # Find similar posts by tags
│   └── validateFrontmatter()
├── types/frontmatter.ts   # TypeScript interfaces for Post, FrontMatter
└── utils.ts               # formatDate(), formatRelativeDate(), generateExcerpt()
```

**Frontmatter Schema:**

```yaml
---
title: string # Required
description: string # Required
date: 'YYYY-MM-DD' # Required, ISO format
author: string # Required
tags: [string, string?, string?] # Max 3 tags
image?: string # Optional hero image
draft?: boolean # Exclude from listings if true
---
```

**Security:** Path sanitization prevents directory traversal attacks. All file reads use `path.resolve()` and validate paths stay within `content/blog/`.

### Components Organization

```
components/
├── blog/
│   └── MarkdownRenderer.tsx    # Client component for rendering markdown
│                               # Custom components: images (Next Image),
│                               # links (external vs internal), code blocks
├── layout/
│   ├── Breadcrumbs.tsx         # Client component, uses usePathname()
│   └── BreadcrumbsSchema.tsx   # Schema.org structured data for SEO
└── [future components]
```

## Coding Standards for Next.js 16

### File Naming Conventions

**Files and Directories:**

- Use **kebab-case** for all file names: `user-profile.tsx`, `blog-post.tsx`
- Special Next.js files: `page.tsx`, `layout.tsx`, `not-found.tsx`, `loading.tsx`

**Component Names (inside files):**

- Use **PascalCase**: `export function UserProfile()`, `export default BlogPost`

**Variables, Functions, Props:**

- Use **camelCase**: `const userSettings = {}`, `function handleSubmit() {}`
- Hooks: `useTheme`, `useMarkdown`

**Constants:**

- Use **SCREAMING_SNAKE_CASE**: `const API_BASE_URL = "..."`

**Why kebab-case for files?**

- Cross-platform compatibility (Windows vs Unix)
- URL-friendly (file names often map to routes)
- Easier to parse and read

### Theme Management & Reusability

**Recommended Pattern:** Use `next-themes` library for dark/light mode

```typescript
// Root layout.tsx
import { ThemeProvider } from 'next-themes'

export default function RootLayout({ children }) {
  return (
    <html suppressHydrationWarning>
      <body>
        <ThemeProvider
          attribute="class"
          defaultTheme="dark"
          enableSystem={false}
          storageKey="blog-theme"
        >
          {children}
        </ThemeProvider>
      </body>
    </html>
  )
}
```

**Client Component for Toggle:**

```typescript
// components/theme-toggle.tsx
'use client'
import { useTheme } from 'next-themes'
import { useEffect, useState } from 'react'

export function ThemeToggle() {
  const { theme, setTheme } = useTheme()
  const [mounted, setMounted] = useState(false)

  // Prevent hydration mismatch
  useEffect(() => setMounted(true), [])
  if (!mounted) return <div>...</div>

  return <button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
    Toggle
  </button>
}
```

**Tailwind Configuration:**

```javascript
// tailwind.config.js
module.exports = {
  darkMode: 'class', // Use 'class' strategy for next-themes
  theme: {
    extend: {
      colors: {
        // Define custom colors for consistency
        'dark-primary': '#18181b',
        accent: { DEFAULT: '#164e63', hover: '#155e75' },
      },
    },
  },
}
```

**CSS Variables Pattern:**

```css
/* globals.css */
:root {
  --bg-primary: 255 255 255;
  --text-primary: 15 23 42;
}

.dark {
  --bg-primary: 24 24 27;
  --text-primary: 241 245 249;
}

/* Use in components */
.card {
  @apply bg-[rgb(var(--bg-primary))] text-[rgb(var(--text-primary))];
}
```

### Provider Pattern Best Practices

1. **Server Component Boundary:** Keep `layout.tsx` as Server Component, wrap only `children` with Client Provider
2. **Avoid Hydration Mismatches:** Always use `suppressHydrationWarning` on `<html>` tag
3. **Client-Only Rendering:** Use `useEffect` + `mounted` state for theme-dependent UI
4. **Context Consumption:** Only components using `useTheme()` need `'use client'` directive
5. **No Prop Drilling:** Context makes theme accessible anywhere without passing props

### Next.js 16 Specific Patterns

**Async Server Components:**

```typescript
// app/blog/page.tsx
export default async function BlogPage() {
  const posts = await getAllPosts()  // Server-side data fetching
  return <div>{posts.map(...)}</div>
}
```

**Static Generation with Dynamic Routes:**

```typescript
// app/blog/[...slug]/page.tsx
export async function generateStaticParams() {
  const posts = await getAllPosts()
  return posts.map(post => ({ slug: post.slug.split('/') }))
}

export async function generateMetadata({ params }) {
  const post = getPostBySlug(params.slug.join('/'))
  return { title: post.frontmatter.title, ... }
}
```

**Parallel Routes for Layout Composition:**

```typescript
// app/layout.tsx
export default function RootLayout({
  children,
  breadcrumbs,  // From @breadcrumbs parallel route
}: {
  children: React.ReactNode
  breadcrumbs: React.ReactNode
}) {
  return <>
    {breadcrumbs}
    {children}
  </>
}
```

## Project-Specific Patterns

### Markdown Processing

- **Always validate paths:** Use `sanitizePath()` to prevent directory traversal
- **Draft support:** Posts with `draft: true` are excluded from `getAllPosts()`
- **Recursive directories:** Blog posts can be organized in subdirectories (`content/blog/tech/post.md`)
- **Reading time:** Auto-calculated at 200 words/minute
- **Date handling:** Use Romanian locale (`ro-RO`) for date formatting

### SEO & Metadata

- **Every page exports `metadata`:** Use Next.js 16's `Metadata` type
- **Dynamic metadata:** Use `generateMetadata()` for blog posts
- **Structured data:** Include Schema.org `BreadcrumbList` and `BlogPosting`
- **OpenGraph images:** Reference `post.frontmatter.image` for social sharing

### Styling Guidelines

**Color Palette:**

- Backgrounds: `zinc-900`, `slate-900`, `slate-800`
- Accents: `cyan-900`, `emerald-900`, `teal-900`
- Text: `slate-100`, `slate-300`, `slate-500`
- Borders: `border-2`, `border-4` (thick, sharp)

**Design Tokens:**

- **NO rounded corners:** Use `rounded-none` or omit (default is sharp)
- **Monospace fonts:** Apply `font-mono` for terminal aesthetic
- **Uppercase labels:** Use `uppercase tracking-wider` for headers
- **Border-heavy design:** Thick borders (`border-4`) over shadows
- **Classification labels:** Add metadata like "FILE#001", "DOCUMENT LEVEL-1"

**Typography:**

- Primary font: `JetBrains Mono` (monospace)
- Headings: `font-mono font-bold uppercase`
- Body: `font-mono text-sm`
- Code blocks: Sharp borders, dark background, no syntax highlighting (for terminal feel)

## Available Subagents

Use these specialized agents via `/spec-implementation-and-review` command:

- `nextjs-specialist` - Next.js 15/16, App Router, SSG, API routes
- `ui-implementer` - UI implementation with shadcn/ui, Tailwind
- `ui-css-specialist` - CSS layouts, styling, responsive design
- `react-frontend-expert` - React components, hooks, state management
- `nodejs-typescript-engineer` - TypeScript, Node.js backend

## Common Pitfalls

1. **Hydration Mismatches with Themes:** Always use `suppressHydrationWarning` on `<html>` and check `mounted` state before rendering theme-dependent UI
2. **Image Paths:** Use `/` prefix for public assets (`/blog/image.jpg` not `blog/image.jpg`)
3. **Dynamic Routes:** Remember to return `slug` as array in `generateStaticParams()` for catch-all routes
4. **Client Components:** Minimize `'use client'` usage - only add when using hooks, event handlers, or browser APIs
5. **Path Security:** Always use `sanitizePath()` when reading markdown files
6. **Date Formats:** Use `YYYY-MM-DD` in frontmatter, convert to Romanian locale for display
7. **Port Configuration:** Dev server runs on port **3030** (not default 3000)

## Type Safety

- All utilities in `lib/` are fully typed
- Frontmatter structure enforced via `FrontMatter` interface
- Use `Post` type for blog post objects
- Avoid `any` - use `unknown` if type is truly unknown, then narrow

## Performance Notes

- **SSG by default:** All blog posts pre-rendered at build time
- **Image optimization:** Use Next.js `<Image>` component
- **Font optimization:** Google Fonts loaded via `next/font`
- **No client-side data fetching:** Markdown loaded server-side only
- **Static exports:** Pages are fully static HTML (no server required for hosting)
