diff --git a/.gitignore b/.gitignore index 10e6c59..edcc957 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,6 @@ src/utils/.env .specstory/** .specstory/ .cursorindexingignore + +# AGENTS.md symlink +AGENTS.md diff --git a/CLAUDE.md b/CLAUDE.md index 21d3b6c..167e205 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,93 +1,108 @@ -``` # CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Development Commands -### Build the project +### Core Development ```bash -npm run build +pnpm dev # Run development server +pnpm build # Build the project +pnpm preview # Build and preview with Wrangler +pnpm deploy # Build and deploy to Cloudflare Pages ``` -### Run development server +### Utilities ```bash -npm run dev -``` +pnpm commit # Auto-generate commit message for staged files +pnpm notepad # Quick note-taking utility -### Lint the codebase -```bash -npm run lint -``` - -### Run tests -```bash -npm run test -``` - -### Build and preview a specific page -```bash -npm run build:page -``` - -### Preview the blog section -```bash -npm run preview:blog +# Image conversion to AVIF format +pnpm run convert:avif:all # Convert all images +pnpm run convert:avif:jpeg # Convert JPEG only +pnpm run convert:avif:png # Convert PNG only ``` ## High-Level Architecture -The website follows a clean separation of concerns with three distinct layers: +This is an Astro-based portfolio and blog site deployed on Cloudflare Pages. The architecture follows a content-driven approach with three distinct layers: -1. **Content Layer** - Markdown/MDX files containing structured content located in `src/content/**` -2. **Component Layer** - Reusable UI components built with Astro, organized by purpose and functionality -3. **Layout & Structure Layer** - Page templates that orchestrate component composition across different sections +### 1. Content Layer (`src/content/**`) +Content is managed via Astro's Content Collections API with schema validation defined in `src/content.config.ts`: -### Content Structure -- All content is stored in Markdown/MDX format within the `src/content/**` directory -- Organized into logical groups: - - `sections/*` - About, Experience, Skills, Featured Project - - `pages/contact.mdx` - Contact form data - - `blog/*.mdx` - Blog posts with structured metadata and frontmatter +- **`blog/`** - Blog posts as MDX files + - Schema: title, description, pubDate, heroImage (optional), featured (boolean), category, tags + - Posts are sorted by pubDate (newest first) -### Component Structure -The component architecture follows a consistent pattern with different types of components: +- **`sections/`** - Homepage section content (hero, experience, skills, featured-project) + - Each section has a custom schema for its specific data needs + - Experience entries include systemId, status, dates, company, role, achievements, links + - Skills entries include domain, tools, proficiency -**Core Components**: Reusable elements like `BlogCard`, `FormattedDate`, and `Navigation` +- **`pages/`** - Page-specific content (contact form configuration) + - Includes form labels, social links, subject options -**Section Components**: Page-specific sections like `Experience`, `Skills`, and `FeaturedProject` +### 2. Component Layer +Components are organized by purpose: -**Layout Components**: Base templates that provide shared styling and structure (e.g., `BaseLayout`, `BlogPost`) +- **Core UI**: `BlogCard`, `FormattedDate`, `Navigation`, `Footer`, `GridOverlay` +- **Blog-specific**: `BlogFilters`, `ReadingProgress`, `TableOfContents`, `PostNavigation`, `RelatedPosts` +- **Section components**: `Hero`, `Experience`, `Skills`, `FeaturedProject` -### Component Relationships +### 3. Page & Layout Layer +- **Layouts**: `BaseLayout` (shared structure), `BlogPost` (blog template) +- **Routes**: Static routes in `src/pages/` with dynamic blog routes via `[...slug].astro` -**Blog Section Flow**: The blog page (`src/pages/blog/index.astro`) fetches all blog posts via `getCollection()` and organizes content into three distinct sections: -- Featured post (first with `featured: true`) -- Editor's picks (next 3 posts after featured) -- Latest posts (all posts for filtering) +## Data Flow Patterns -**Content Rendering Pattern**: All components use a consistent data model where properties are passed through props. For example, `BlogCard` receives title, description, pubDate, and heroImage as parameters. +### Blog Index (`src/pages/blog/index.astro`) +1. Fetches all posts via `getCollection('blog')` +2. Sorts by pubDate (newest first) +3. Identifies featured post (first with `featured: true` or fallback to latest) +4. Renders featured hero + filterable grid of all posts +5. Extracts unique categories for filter UI -### Data Flow Architecture +### Individual Blog Posts (`src/pages/blog/[...slug].astro`) +1. Uses `getStaticPaths()` to generate all blog post routes +2. For each post, calculates: + - Previous/next posts (by date) + - Related posts (matching category or shared tags, limited to 3) + - Reading time (based on word count, 200 wpm) +3. Passes everything to `BlogPost` layout which handles headings, navigation, related posts + +### Content Collections +All content follows the schema validation pattern: ``` -Content Files → Astro Content API → Page Components → UI Components → Final Render +MDX file → src/content.config.ts schema → getCollection() → Component props ``` -- **Content Collection**: Configured in `src/content.config.ts` with schema validation for frontmatter -- **Data Fetching**: Uses Astro's content API to load and transform data from Markdown/MDX files -- **Component Composition**: Pages assemble components based on fetched data, creating dynamic and responsive layouts +## Key Technical Patterns -### Design System Elements -- **Styling System**: Consistent use of classes like `.animate-on-scroll`, `.stagger-*`, and `.border-white/[0.1]` -- **Navigation**: Responsive mobile menu with smooth transitions -- **Accessibility**: Proper ARIA attributes, keyboard navigation support -- **Performance**: Optimized image loading and lazy rendering (using AVIF/WebP formats) +### Image Handling +- Assets in `src/assets/` are processed by Astro (use relative paths in frontmatter) +- Static files in `public/media/` are served as-is (use absolute paths like `/media/file.mp4`) +- AVIF conversion utility available for optimization -### Technical Features -- **AI Integration**: Blog post highlights AI/ML usage in technical workflow -- **Interactive Elements**: Form dropdowns, modal responses for contact form -- **Animation System**: Scroll-triggered animations with staggered effects -- **Responsive Design**: Mobile-first approach with viewport-specific classes and media queries +### Styling +- Tailwind CSS v4 via Vite plugin +- Custom animation classes: `.animate-on-scroll`, `.slide-up`, `.stagger-*`, `.fade-in` +- Monospace font used for technical labels and metadata -The architecture is highly maintainable with clear separation of content from presentation. The use of Astro's data API and component system enables dynamic content generation while maintaining a consistent visual language throughout the site. -``` \ No newline at end of file +### Deployment +- Cloudflare Pages adapter configured in `astro.config.mjs` +- Image service set to "compile" mode +- Platform proxy enabled for development + +## Blog Post Creation Workflow + +1. Create `.mdx` file in `src/content/blog/` (filename becomes URL slug) +2. Add required frontmatter: title, description, pubDate +3. Optionally add: heroImage, featured, category, tags +4. Write content using Markdown/MDX with embedded JSX/HTML +5. Images can reference `src/assets/` (relative) or `public/media/` (absolute) + +## Utility Scripts + +- **`src/utils/convert-to-avif.js`** - Converts images to AVIF format with quality options +- **`src/utils/git-commit.js`** - Auto-generates commit messages from staged changes +- **`src/utils/notepad.js`** - Quick note-taking utility