CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
A personal blog built with VitePress 2.0-alpha and Tailwind CSS v4. The site uses a fully custom theme with Vue 3 components, featuring a responsive layout with three distinct page types.
Site URL: https://ywh.sh
Architecture
Project Structure
.
├── .vitepress/
│ ├── cache/ # Build cache (git-ignored)
│ ├── dist/ # Production build output (git-ignored)
│ ├── theme/
│ │ ├── index.ts # Theme entry point
│ │ ├── Layout.vue # Main layout (conditional rendering)
│ │ ├── Header.vue # Profile image + site title
│ │ ├── Footer.vue # Copyright + email link
│ │ ├── Aside.vue # Navigation sidebar
│ │ ├── Article.vue # Blog post view
│ │ ├── Writing.vue # Post list (grouped by year)
│ │ ├── Page.vue # Static page view
│ │ ├── Pattern.vue # Decorative background SVG
│ │ ├── posts.data.ts # Content loader for blog posts
│ │ └── style.css # Tailwind imports + custom styles
│ └── config.ts # VitePress + Tailwind config
├── writing/ # Blog posts directory
│ ├── *.md # English blog posts
│ └── tw/ # Traditional Chinese translations
├── index.md # Home page (frontmatter: home: true)
├── writing.md # Writing list page (frontmatter: page: true)
└── package.jsonPage Types
The theme conditionally renders three different views based on frontmatter:
| Page Type | Frontmatter | Component | Description |
|---|---|---|---|
| Home | home: true | Page.vue | Introduction/about page |
| Writing List | page: true | Writing.vue | Blog posts grouped by year |
| Article | (default) | Article.vue | Individual blog post |
Theme Components
- Layout.vue: Main wrapper using flex layout, conditionally renders Page/Writing/Article based on frontmatter
- Header.vue: Gravatar profile image, site title, tagline with responsive grid
- Footer.vue: Copyright notice with email link
- Aside.vue: Navigation sidebar with active state detection (About, Writing links)
- Article.vue: Blog post renderer with prose styling and date display
- Writing.vue: Post list view, groups posts by year (newest first)
- Page.vue: Simple content wrapper for static pages
- Pattern.vue: Decorative gradient SVG background pattern
Content Loading
posts.data.ts uses VitePress createContentLoader() to:
- Scan
writing/*.mdfiles - Extract title, URL, date, excerpt from frontmatter
- Sort posts by date (newest first)
Key Integration Points
- Tailwind Integration: Via
@tailwindcss/viteplugin in.vitepress/config.ts - Theme Registration:
.vitepress/theme/index.tsexports custom Layout - Runtime API: Components use
useData()for site data anduseRoute()for navigation - Content Rendering: Uses VitePress
<Content />component in Article.vue and Page.vue
Development Commands
bash
npm run blog:dev # Start dev server with hot reload
npm run blog:build # Build for production
npm run blog:preview # Preview production buildTechnology Stack
- VitePress: v2.0.0-alpha.12
- Tailwind CSS: v4.1.15 (with @tailwindcss/typography)
- Vue 3: Provided by VitePress
- TypeScript: For config and components
Development Notes
Adding Blog Posts
- Create a new
.mdfile inwriting/directory - Add frontmatter:yaml
--- title: "Post Title" description: "SEO description" date: 2025-01-14 head: - - link - rel: canonical href: "https://ywh.sh/writing/post-slug" --- - Posts are automatically sorted by date in the writing list
Styling
- Primary Color: Emerald (emerald-500/600 for links and accents)
- Font: Inter (imported from fonts.bunny.net)
- Typography: Tailwind prose plugin with custom color overrides
- Responsive: Mobile-first with
md:breakpoints
SEO Configuration
The config includes:
- Canonical URLs for each page
- Open Graph meta tags (og:type, og:url, og:title, og:image)
- Twitter card support (@takeshiyu_hey)
- Sitemap generation for https://ywh.sh
Tailwind CSS v4
- Imported via
@import "tailwindcss"in style.css - Uses
@sourcedirective to scan all Vue/TS files - Custom prose color overrides for links, headings, code blocks