# AGENTS.md

This file provides guidelines for AI agents operating in this repository.

## Project Overview

This is a bilingual personal portfolio site built with **Astro 5**, **React 19**, and **Tailwind CSS 4**.

Current project capabilities from codebase:
- EN/ZH localized site with Astro i18n routing (`en` default, `zh` under `/zh`)
- Portfolio pages: home, projects, services, now, hire, about
- Blog system with posts, tag pages, and category pages in both locales
- React interactive islands for header/theme switch, typewriter effect, back-to-top, comments, and animations
- Waline comment integration (`@waline/client`) and Umami analytics script in production
- SEO/sitemap integration via `@astrojs/sitemap`

## Package Manager Rule (Mandatory)

Use **pnpm only** for dependency and script commands.

- Always use `pnpm` commands in documentation, scripts, and instructions
- Do not use `npm`, `yarn`, or `bun` commands in this repo
- If existing text shows `npm run ...`, replace with `pnpm ...`

Examples:

```bash
pnpm install
pnpm dev
pnpm build
pnpm preview
```

## Build Commands

```bash
# Install dependencies
pnpm install

# Development server
pnpm dev

# Build for production
pnpm build

# Preview production build locally
pnpm preview
```

No lint or test commands are configured. Run `pnpm build` to verify changes.

## Code Style Guidelines

### General Principles
- Write concise, self-documenting code
- Avoid unnecessary comments (only explain complex logic)
- Follow existing patterns in the codebase
- Prioritize readability over cleverness

### Imports
- Use `@/` alias for src imports (configured in `tsconfig.json`)
- Order imports: React → libraries → components → utilities
- Use named exports for components and utilities

```typescript
// Good
import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";

// Avoid
import utils from '@/lib/utils';
import { useState, useEffect } from 'react';
```

### TypeScript
- Use TypeScript for all new files (`.ts`, `.tsx`)
- Extend Astro strict TypeScript config
- Use explicit types for component props
- Avoid `any`, use `unknown` or specific types

```typescript
// Good
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>,
  VariantProps<typeof buttonVariants> {
  asChild?: boolean;
}

// Avoid
const handleClick = (e: any) => { ... }
```

### Components

**Astro Components (`.astro`)**:
- Use frontmatter fence `---` at top
- Separate imports, props, and logic
- Use `client:only="react"` for React components needing browser APIs
- Use `client:load` for interactive components that should hydrate on load
- Static content should not have client directives

**React Components (`.tsx`)**:
- Use `React.forwardRef` for components that need refs
- Use class-variance-authority (CVA) for component variants where applicable
- Use Radix UI primitives when available
- Prefer named exports (unless file already follows a default-export pattern)

### Styling (Tailwind CSS)
- Use Tailwind utility classes as the primary styling approach
- Use `cn()` utility to merge classes with conditional logic
- Avoid inline style objects unless strictly necessary
- Dark mode styles should use `dark:` variants and existing tokens

### i18n (Internationalization)
- All UI text must be in `src/i18n/translations.ts` (and related i18n helpers)
- Use translation helpers (`useTranslations(lang)`)
- Avoid hardcoded strings in `.astro` and `.tsx` when user-facing text is localized
- Keep EN/ZH content parity for shared pages/components

### Naming Conventions
- **Components**: PascalCase (e.g., `GlassHeader`)
- **Files**: kebab-case for Astro routes, PascalCase for React components
- **Variables/functions**: camelCase
- **Constants**: SCREAMING_SNAKE_CASE
- **Types/Interfaces**: PascalCase, with `Props` suffix for component props

### Error Handling
- Use TypeScript types to prevent runtime errors
- Handle null/undefined explicitly
- Prefer optional chaining (`?.`) and nullish coalescing (`??`)
- Avoid broad `try/catch` unless handling known async boundaries

## Astro-Specific Conventions

- Pages use file-based routing under `src/pages/`
- English routes are root-level; Chinese routes are under `src/pages/zh/`
- Blog content uses markdown posts in:
  - `src/pages/blog/posts/`
  - `src/pages/zh/blog/posts/`
- Layouts are in `src/layouts/`
- Reusable UI/components are in `src/components/`
- Data source modules are in `src/lib/data/`

## Project Structure

```text
src/
├── components/      # UI components (React & Astro)
│   ├── blog/        # Blog-specific components (meta, lists, comments)
│   ├── layout/      # Layout helper components (TOC, blog nav)
│   ├── markdown/    # Markdown rendering components
│   └── ui/          # Reusable UI primitives
├── layouts/         # Shared page layouts
├── pages/           # Routes (including blog and locale routes)
│   ├── blog/
│   └── zh/
├── lib/
│   ├── data/        # Personal info, projects, services
│   └── utils.ts
├── i18n/            # Locale constants, translation maps, helpers
├── styles/          # Global and integration styles
├── types/           # Type definitions
└── utils/           # Utility functions for blog and helpers
```

## Important Notes

- This is a bilingual site (EN/ZH); maintain both locales
- Default language is English (`defaultLang = 'en'`)
- Use `Astro.currentLocale` to detect language context
- Keep `services` semantics as capabilities/skill offerings
- Components depending on `window`, `document`, or `localStorage` must use proper client directives
- Preserve existing integrations: MDX, sitemap i18n, Waline comments, and analytics behavior
