docs: refresh AGENTS and add Claude instructions
This commit is contained in:
162
AGENTS.md
162
AGENTS.md
@@ -4,22 +4,50 @@ This file provides guidelines for AI agents operating in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
A modern personal portfolio website built with **Astro 5**, **React 19**, and **Tailwind CSS 4**. Features glassmorphism design, animations via Framer Motion, and full i18n support (EN/ZH).
|
||||
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
|
||||
npm run dev
|
||||
pnpm dev
|
||||
|
||||
# Build for production
|
||||
npm run build
|
||||
pnpm build
|
||||
|
||||
# Preview production build locally
|
||||
npm run preview
|
||||
pnpm preview
|
||||
```
|
||||
|
||||
No lint or test commands are configured. Run `npm run build` to verify changes.
|
||||
No lint or test commands are configured. Run `pnpm build` to verify changes.
|
||||
|
||||
## Code Style Guidelines
|
||||
|
||||
@@ -30,7 +58,7 @@ No lint or test commands are configured. Run `npm run build` to verify changes.
|
||||
- Prioritize readability over cleverness
|
||||
|
||||
### Imports
|
||||
- Use `@/` alias for src imports (configured in tsconfig.json)
|
||||
- Use `@/` alias for src imports (configured in `tsconfig.json`)
|
||||
- Order imports: React → libraries → components → utilities
|
||||
- Use named exports for components and utilities
|
||||
|
||||
@@ -47,8 +75,8 @@ import { useState, useEffect } from 'react';
|
||||
```
|
||||
|
||||
### TypeScript
|
||||
- Use TypeScript for all new files (.ts, .tsx)
|
||||
- Extend Astro's strict TypeScript config
|
||||
- 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
|
||||
|
||||
@@ -60,109 +88,87 @@ interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
}
|
||||
|
||||
// Avoid
|
||||
interface ButtonProps { ... } // too verbose
|
||||
const handleClick = (e: any) => { ... } // no type
|
||||
const handleClick = (e: any) => { ... }
|
||||
```
|
||||
|
||||
### Components
|
||||
|
||||
**Astro Components (.astro)**:
|
||||
**Astro Components (`.astro`)**:
|
||||
- Use frontmatter fence `---` at top
|
||||
- Separate imports, props, and logic
|
||||
- Use `client:only="react"` for React components that need browser APIs
|
||||
- Use `client:load` for interactive components
|
||||
- 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)**:
|
||||
**React Components (`.tsx`)**:
|
||||
- Use `React.forwardRef` for components that need refs
|
||||
- Use class-variance-authority (CVA) for component variants
|
||||
- Use class-variance-authority (CVA) for component variants where applicable
|
||||
- Use Radix UI primitives when available
|
||||
- Export components as named exports
|
||||
- Prefer named exports (unless file already follows a default-export pattern)
|
||||
|
||||
### Styling (Tailwind CSS)
|
||||
- Use Tailwind utility classes exclusively
|
||||
- Use Tailwind utility classes as the primary styling approach
|
||||
- Use `cn()` utility to merge classes with conditional logic
|
||||
- Avoid custom CSS; use Tailwind equivalents
|
||||
- Dark mode: prefix colors with `dark:` modifier
|
||||
|
||||
```tsx
|
||||
// Good
|
||||
<div className={cn(
|
||||
"base-classes",
|
||||
variant === "primary" && "primary-classes",
|
||||
className
|
||||
)} />
|
||||
|
||||
// Avoid
|
||||
<div style={{ display: 'flex', padding: '16px' }}>
|
||||
```
|
||||
- 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`
|
||||
- Use `useTranslations(lang)` hook for text
|
||||
- Avoid hardcoded strings in .astro and .tsx files
|
||||
- Structure translations by section (nav, hero, about, etc.)
|
||||
|
||||
```typescript
|
||||
// translations.ts
|
||||
export const translations = {
|
||||
en: { hero: { greeting: 'Hello, I'm' } },
|
||||
zh: { hero: { greeting: '你好,我是' } }
|
||||
}
|
||||
|
||||
// In component
|
||||
const t = useTranslations(lang);
|
||||
<h1>{t('hero.greeting')} {name}</h1>
|
||||
```
|
||||
- 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., `Button`, `GlassHeader`)
|
||||
- **Files**: kebab-case for Astro pages, PascalCase for React components
|
||||
- **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
|
||||
- **Types/Interfaces**: PascalCase, with `Props` suffix for component props
|
||||
|
||||
### Error Handling
|
||||
- Use TypeScript types to prevent runtime errors
|
||||
- Handle null/undefined cases explicitly
|
||||
- Use optional chaining `?.` and nullish coalescing `??`
|
||||
- No try-catch unless handling specific async errors
|
||||
- Handle null/undefined explicitly
|
||||
- Prefer optional chaining (`?.`) and nullish coalescing (`??`)
|
||||
- Avoid broad `try/catch` unless handling known async boundaries
|
||||
|
||||
### Astro-Specific
|
||||
- Pages use file-based routing (`src/pages/**/*.astro`)
|
||||
- Dynamic routes: `[slug].astro`, `[category].astro`
|
||||
- Layouts in `src/layouts/`
|
||||
- Components in `src/components/`
|
||||
- Use Content Collections for blog posts (MDX in `src/pages/blog/posts/`)
|
||||
## 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
|
||||
│ ├── layout/ # Layout components
|
||||
│ ├── blog/ # Blog-specific components (meta, lists, comments)
|
||||
│ ├── layout/ # Layout helper components (TOC, blog nav)
|
||||
│ ├── markdown/ # Markdown rendering components
|
||||
│ └── ui/ # Reusable UI primitives
|
||||
├── layouts/ # Page layouts (Layout.astro, BlogLayout, etc.)
|
||||
├── pages/ # Routes (auto-routed by filename)
|
||||
│ ├── blog/ # Blog pages & posts
|
||||
│ └── zh/ # Chinese locale pages
|
||||
├── lib/ # Data & utilities
|
||||
│ └── data/ # Static data (personal-info, projects, services)
|
||||
├── styles/ # Global CSS
|
||||
├── i18n/ # Internationalization
|
||||
│ └── translations.ts
|
||||
├── types/ # TypeScript type definitions
|
||||
└── utils/ # Utility functions
|
||||
├── 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'`)
|
||||
- Chinese pages are under `/zh/` prefix
|
||||
- Use `Astro.currentLocale` to detect current language
|
||||
- The `services` section shows skills/capabilities, not literal services
|
||||
- Include `client:only="react"` for components using browser APIs (localStorage, window, etc.)
|
||||
- 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
|
||||
|
||||
Reference in New Issue
Block a user