diff --git a/AGENTS.md b/AGENTS.md index 505e39b..87aa558 100644 --- a/AGENTS.md +++ b/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, } // 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 -
- -// Avoid -
-``` +- 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); -

{t('hero.greeting')} {name}

-``` +- 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 diff --git a/Claude.md b/Claude.md new file mode 100644 index 0000000..d07d4b7 --- /dev/null +++ b/Claude.md @@ -0,0 +1,7 @@ +# Claude.md + +Please follow [`AGENTS.md`](./AGENTS.md) as the canonical agent-instruction source of truth. + +Key requirement reminder: +- Use `pnpm` as the package manager (`pnpm install`, `pnpm dev`, `pnpm build`, `pnpm preview`) +- Do not use `npm`, `yarn`, or `bun` commands in this repository