# Agent Guidelines

This file provides guidance to any coding agent (e.g., Claude Code, Codex) when working with code in this repository. Replace `AgentName` with the active agent's name and use its uppercase tag for commit prefixes (for example, Codex → `[CODEX]`, Claude → `[CLAUDE]`).

## Project Overview

AIA Taiwan English official website - a multilingual web application built with Laravel 12, Inertia.js, React 19, and TailwindCSS 4. The project uses a hybrid architecture combining a Laravel backend with React frontend components, alongside a separate Storybook design system.

## Communication Preferences

**Language**: Please respond in Traditional Chinese (Taiwan, zh-TW) during conversations, unless:
- Code comments or documentation should be in English
- Git commit messages should be in English
- Technical terms can use English when more precise
- User explicitly requests English responses

**Examples**:
- ✅ "我已經完成了 NewsController 的實作，現在來建立對應的 Resource..."
- ✅ "發現了 N+1 查詢問題，讓我使用 `with()` 來優化..."
- ❌ "I have completed the NewsController implementation..."

## Repository Structure

```
official-en-aia/
├── laravel/          # Main Laravel application (primary development)
│   ├── app/          # Controllers, Models, Resources, Middleware
│   ├── resources/
│   │   ├── js/       # React/TypeScript components, pages, layouts
│   │   └── docs/     # Project documentation (IMPORTANT: read these first)
│   └── routes/       # Web routes, API routes
├── storybook/        # Design system component documentation
├── web/              # Legacy frontend build (vendor assets)
├── design-token/     # Design token generation
└── utils/            # Data generation scripts
```

## Essential Documentation

Before starting any work, read the following documents:

### 🌟 ClaudeCode Documentation (Recommended)

Located in `laravel/resources/docs/ClaudeCode/`:

1. **README.md** - Quick overview of the revised strategy ⭐ START HERE
2. **architecture-plan-revised.md** - Vendor collaboration strategy (explains why we bridge vendor JS instead of rewriting)
3. **REFACTOR-PLAN-REVISED.md** - Actionable refactoring plan (8-12 hours vs original 40-50 hours)

### 📚 Project Documentation

Located in `laravel/resources/docs/`:

1. **laravel-structure.md** - Technical implementation patterns (Controllers, Resources, Models, Routes, TypeScript types)
2. **site-structure.md** - Page/route/component mapping and completion status
3. **data-structure.md** - Database schema and field definitions
4. **test.md** - Development/testing/deployment workflow
5. **structure-frontend.md** - Storybook to React component mapping

### 🗄️ Archive (Superseded)

- ~~architecture-plan.md~~ - Original plan (too idealistic, use -revised version)
- ~~code-audit-report.md~~ - Code issues (context only, see revised plan for solutions)

## Docker Environment

This project runs in a Docker environment. Key details:

- PHP execution: Always use `docker exec php8.2 bash -c "cd /data/www/official-en-aia/laravel && <command>"`
- Container path: `/data/www/official-en-aia/laravel/`
- Host path: `/root/liveserver2024/data/www/official-en-aia/laravel/`
- Services: apache2, php8.2, mysql8 (see `/root/liveserver2024/docker-compose.yml`)

## Common Commands

### Development

```bash
# Install dependencies
cd /root/liveserver2024/data/www/official-en-aia/laravel
composer install
npm install

# Development server (runs all services: Laravel, queue, logs, Vite)
cd /root/liveserver2024/data/www/official-en-aia/laravel
composer dev

# Frontend development only
cd /root/liveserver2024/data/www/official-en-aia/laravel
npm run dev
```

### Build and Deploy

```bash
# Build frontend assets
cd /root/liveserver2024/data/www/official-en-aia/laravel
npm run build

# Clear response cache (REQUIRED after build to see changes)
docker exec php8.2 bash -c "cd /data/www/official-en-aia/laravel && php artisan responsecache:clear"

# Complete deployment (build + clear cache)
cd /root/liveserver2024/data/www/official-en-aia/laravel && \
npm run build && \
docker exec php8.2 bash -c "cd /data/www/official-en-aia/laravel && php artisan responsecache:clear"

# Clear all caches
docker exec php8.2 bash -c "cd /data/www/official-en-aia/laravel && php artisan optimize:clear"
```

### Testing and Debugging

```bash
# Run tests
cd /root/liveserver2024/data/www/official-en-aia/laravel
composer test

# Type checking
npm run types

# Linting
npm run lint

# Format check
npm run format:check

# Laravel Tinker (for testing Models/Resources)
docker exec -it php8.2 bash -c "cd /data/www/official-en-aia/laravel && php artisan tinker"

# View logs
docker exec php8.2 bash -c "tail -f /data/www/official-en-aia/laravel/storage/logs/laravel.log"
```

### Artisan Commands

```bash
# Route list
docker exec php8.2 bash -c "cd /data/www/official-en-aia/laravel && php artisan route:list"

# Migration
docker exec php8.2 bash -c "cd /data/www/official-en-aia/laravel && php artisan migrate"

# Create Filament admin user
docker exec php8.2 bash -c "cd /data/www/official-en-aia/laravel && php artisan make:filament-user"
```

### Storybook Development

```bash
cd /root/liveserver2024/data/www/official-en-aia/storybook
npm install
npm run storybook  # Runs on port 6026
```

### Design Token Updates

```bash
# After exporting token files from Figma:
cd /root/liveserver2024/data/www/official-en-aia/design-token
npm run transform

# Generate color/icon tokens
cd /root/liveserver2024/data/www/official-en-aia
npm run token:color
npm run token:icon
npm run storybook:icon
```

## Architecture Patterns

### Data Flow

```
Database → Model → Controller → Resource → Inertia::render() → React Component
```

### Key Principles

1. **Controllers** handle queries using Eloquent Query Builder
2. **Resources** format data (image paths, date formatting, array transformations)
3. **Inertia** bridges backend props to frontend
4. **React** components receive TypeScript-typed props

### Example Implementation

**Controller** (`app/Http/Controllers/NewsController.php`):
```php
public function index(Request $request): Response
{
    $posts = Post::query()
        ->where('status', 'publish')
        ->when($request->type, fn($q, $type) => $q->where('post_type', $type))
        ->with('categories')  // Eager load to avoid N+1
        ->orderBy('published_at', 'desc')
        ->paginate(12);

    return Inertia::render('news', [
        'posts' => PostResource::collection($posts),
        'filters' => $request->only(['type', 'category']),
    ]);
}
```

**Resource** (`app/Http/Resources/PostResource.php`):
```php
public function toArray(Request $request): array
{
    return [
        'id' => $this->id,
        'title' => $this->title,
        'slug' => $this->slug,
        'image_url' => $this->image_url
            ? asset('uploads/' . $this->image_url)
            : null,
        'categories' => CategoryResource::collection($this->whenLoaded('categories')),
        'published_at' => $this->published_at?->format('Y-m-d H:i:s'),
    ];
}
```

**TypeScript Type** (`resources/js/types/index.d.ts`):
```typescript
type Post = {
    id: number;
    title: string;
    slug: string;
    image_url: string | null;
    categories: Category[];
    published_at: string;
};
```

### Route Model Binding

Use slug-based route model binding for cleaner URLs:
```php
Route::get('/news/{post:slug}', [NewsController::class, 'show'])->name('news.show');
```

## Response Cache System

This project uses Spatie Laravel Response Cache with custom implementations to work with Inertia.js:

### Custom Classes
- `App\Support\CustomCacheProfile` - Defines what to cache (excludes /admin/*, /api/*)
- `App\Support\CustomCacheHasher` - Cache key generation (ignores cookies)
- `App\Http\Middleware\RemoveInertiaNoCache` - Removes no-cache headers

### Important Notes
- Cache is enabled on most public routes via `CacheResponse` middleware
- After frontend builds, ALWAYS clear cache: `php artisan responsecache:clear`
- Cache applies to public content only, never user-specific pages
- See extensive documentation in `routes/web.php` (lines 1-289)

## Component Architecture

### Dual Component System

Components exist in two places:
1. **Storybook** (`storybook/stories/`) - Design system (HTML/JS)
2. **Laravel** (`laravel/resources/js/`) - React implementation

Mapping documented in `laravel/resources/docs/structure-frontend.md`.

### Component Locations

- AIA-specific components: `resources/js/components/aia/`
- Shadcn UI components: `resources/js/components/ui/`
- Layouts: `resources/js/layouts/aia/`
- Pages: `resources/js/pages/`

### Vendor Integration

Complex interactions (carousel, modal, form validation) use JavaScript from `@vendor-web` (built from `web/` directory).

## Database Models

### Key Models
- `Post` - News and events (polymorphic: post_type = 'news' | 'event')
- `Category` - Taxonomy for posts (many-to-many via `category_post`)
- `Member` - Team members (member_type = 'board' | 'executive')

### Common Scopes
```php
Post::published()->ofType('news')->ordered()->get();
Member::published()->ofType('board')->ordered()->get();
```

### Relationships
```php
// Post has many categories
$post->categories  // BelongsToMany

// Use eager loading to avoid N+1
Post::with('categories')->get();
```

## Git Workflow

Current branch: `feature-frontend`
Main branch: `main`

Recent work involves implementing frontend pages, controllers, and Inertia integration.

### ⚠️ IMPORTANT: Git Commit Policy

When performing git commits, `AgentName` MUST follow these security and quality rules:

**Git Commit Requirements:**
1. **Commit Message Prefix**: ALL commit messages must start with `[AGENT_TAG]` (uppercase agent name; e.g., Codex → `[CODEX]`)
2. **Selective Staging**: Only stage files modified in the current task/change
3. **Security Validation**: Before committing, verify NO sensitive data is included:
   - ❌ API keys, tokens, secrets
   - ❌ Absolute file paths (e.g., `/home/username/projects/...`, `/var/www/...`, `C:\Users\...`)
   - ❌ Private domain names or internal URLs
   - ❌ `.env` variable values (only structure/keys are OK)
   - ❌ Database credentials or passwords
   - ❌ Personal information or email addresses (except git config)
4. **Git User Configuration**:
   - Use `--author="AgentName <email>"` parameter when committing
   - DO NOT modify `.git/config` with `git config user.name`
   - Preserve user's existing git configuration
5. **Use the `/safe-commit` skill** for safe, automated commits (see Commit Skill section below)

**Prohibited Git Operations (User Must Execute Manually):**
- `git push` - Never push to remote automatically
- `git pull` / `git fetch` - Never sync from remote automatically
- `git merge` / `git rebase` - Never perform branch operations
- `git reset --hard` / `git clean -fd` - Never destructive operations
- `git branch -D` / `git tag -d` - Never delete branches/tags

**Example Safe Commit Flow:**
```bash
# 1. Get current user email for author field
USER_EMAIL=$(git config user.email)

# 2. Stage only changed files for this task
git add laravel/app/Http/Controllers/NewsController.php
git add laravel/resources/js/pages/news.tsx

# 3. Verify no sensitive data
git diff --cached | grep -iE '(api_key|secret|password|token|/(root|home|var)/)'

# 4. Commit with [AGENT_TAG] tag in description and --author parameter
git commit --author="AgentName <$USER_EMAIL>" -m "feat(news): [AGENT_TAG] implement news listing page with filters

- Add NewsController with pagination and filtering
- Create React news page component with TypeScript types
- Add PostResource for data formatting

Co-Authored-By: AgentName <noreply@example.com>"
```

**When to Use Manual vs Skill:**
- Use `/safe-commit` skill for routine commits (recommended for safety)
- Manual commit may be needed for complex multi-step operations
- Skill uses `--author` parameter to avoid modifying `.git/config`

## Technology Stack

- **Backend**: Laravel 12.0, PHP 8.2
- **Frontend**: React 19, Inertia.js 2.0, TypeScript 5.7
- **Styling**: TailwindCSS 4, PostCSS
- **Build**: Vite 6
- **Admin**: Filament 3.2
- **Database**: MySQL 8.0 (or SQLite)
- **Cache**: Spatie Laravel Response Cache 7.7
- **Media**: Spatie Laravel Media Library 11.17

## Important Conventions

1. **Always use Resources** to format data before passing to Inertia
2. **Always eager load** relationships to avoid N+1 queries
3. **Image paths**: Store relative paths in DB (`2025/07/image.png`), use `asset('uploads/' . $path)` in Resource
4. **Date formatting**: Use `->format('Y-m-d H:i:s')` in Resources
5. **Multiline fields**: Convert `\r\n` to arrays in Resources (e.g., member positions)
6. **TypeScript types**: Define matching types for all Resource outputs
7. **Static pages**: Use closure routes (`fn() => Inertia::render('page')`) when no data needed
8. **Dynamic pages**: Use Controllers when querying data

## Testing URLs

- Test site: https://4aia.isobar.com.tw/
- Storybook: http://project.docs.isobar.tw/aia/aia-official-en
- Local admin: http://localhost/admin

## Troubleshooting

### Frontend changes not visible
1. Rebuild: `npm run build`
2. Clear response cache: `docker exec php8.2 bash -c "cd /data/www/official-en-aia/laravel && php artisan responsecache:clear"`
3. Hard refresh browser: Ctrl+Shift+R (Windows/Linux) or Cmd+Shift+R (Mac)

### N+1 Query Issues
Always use `with()` for relationships:
```php
// Bad
$posts = Post::all();
foreach ($posts as $post) {
    echo $post->categories->pluck('name');
}

// Good
$posts = Post::with('categories')->get();
```

### Image paths not working
1. Check DB has relative path: `2025/07/image.png`
2. Verify Resource uses: `asset('uploads/' . $this->image_url)`
3. Check directory permissions: `public/uploads/` should be 755

## Node Version

Project uses Volta for Node version management:
- Node: 20.19.0 (root package.json)
- Node: 20.12.2 (storybook, web packages)

## Additional Notes

- SSR is currently disabled in `config/inertia.php` (`'enabled' => false`)
- Filament admin panel available at `/admin` route
- All frontend work should reference Storybook design system first
- Database migrations use standard Laravel conventions
- Queue workers can be started with `php artisan queue:work` (via Docker)
