|
| 1 | +# CLAUDE.md - AI Assistant Guide for thiloho.github.io |
| 2 | + |
| 3 | +This document provides comprehensive guidance for AI assistants working on this codebase. It covers the project structure, development workflows, and key conventions to follow. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +This is the source code for **thilohohlt.com**, a personal website built with the Astro web framework. The repository also includes Nix configuration files for self-hosted services and server deployment. |
| 8 | + |
| 9 | +**Live Site**: https://thilohohlt.com |
| 10 | +**Tech Stack**: Astro 5.14.6, Tailwind CSS 4.1.14, TypeScript, Markdown |
| 11 | +**Deployment**: GitHub Pages (automated via GitHub Actions) |
| 12 | + |
| 13 | +## Directory Structure |
| 14 | + |
| 15 | +``` |
| 16 | +thiloho.github.io/ |
| 17 | +├── .github/ |
| 18 | +│ └── workflows/ |
| 19 | +│ └── deploy.yml # GitHub Actions deployment workflow |
| 20 | +├── public/ # Static assets (served as-is) |
| 21 | +│ ├── fonts/ # Custom font files (Styrene, Tiempos) |
| 22 | +│ ├── favicon.ico |
| 23 | +│ ├── CNAME # Custom domain configuration |
| 24 | +│ └── site.webmanifest |
| 25 | +├── server/ # NixOS server configuration |
| 26 | +│ ├── default.nix |
| 27 | +│ └── hardware-configuration.nix |
| 28 | +├── src/ |
| 29 | +│ ├── components/ # Reusable Astro components |
| 30 | +│ │ ├── Button.astro |
| 31 | +│ │ ├── Date.astro |
| 32 | +│ │ ├── Footer.astro |
| 33 | +│ │ ├── Head.astro |
| 34 | +│ │ ├── Header.astro |
| 35 | +│ │ ├── Icon.astro |
| 36 | +│ │ ├── Nav.astro |
| 37 | +│ │ ├── TableOfContents.astro |
| 38 | +│ │ └── Track.astro |
| 39 | +│ ├── content/ # Content collections |
| 40 | +│ │ ├── blog/ # Blog post markdown files |
| 41 | +│ │ │ ├── custom-email-domain/ |
| 42 | +│ │ │ ├── e2e-testing-spring-boot-applications/ |
| 43 | +│ │ │ ├── nixos-with-ext4-and-luks/ |
| 44 | +│ │ │ └── privacy-focused-operating-systems/ |
| 45 | +│ │ └── tracks.json # Music tracks data |
| 46 | +│ ├── layouts/ |
| 47 | +│ │ └── PageLayout.astro # Main page layout |
| 48 | +│ ├── pages/ # Routes (file-based routing) |
| 49 | +│ │ ├── blog/ |
| 50 | +│ │ │ ├── [slug].astro # Dynamic blog post pages |
| 51 | +│ │ │ └── index.astro # Blog listing page |
| 52 | +│ │ ├── 404.astro |
| 53 | +│ │ ├── index.astro # Homepage |
| 54 | +│ │ ├── legal-disclosure.astro |
| 55 | +│ │ ├── robots.txt.ts |
| 56 | +│ │ ├── rss.xml.ts # RSS feed |
| 57 | +│ │ ├── services.astro |
| 58 | +│ │ └── tracks.astro |
| 59 | +│ ├── styles/ |
| 60 | +│ │ └── global.css # Global styles and font definitions |
| 61 | +│ └── content.config.ts # Content collections schema |
| 62 | +├── astro.config.ts # Astro configuration |
| 63 | +├── flake.nix # Nix flake configuration |
| 64 | +├── flake.lock # Nix flake lock file |
| 65 | +├── package.json # Node.js dependencies and scripts |
| 66 | +├── package-lock.json |
| 67 | +├── tsconfig.json # TypeScript configuration |
| 68 | +└── .prettierrc # Prettier configuration |
| 69 | +``` |
| 70 | + |
| 71 | +## Tech Stack Details |
| 72 | + |
| 73 | +### Core Framework |
| 74 | +- **Astro 5.14.6**: Static site generator with component islands architecture |
| 75 | +- **TypeScript**: Strict mode enabled (`extends: "astro/tsconfigs/strict"`) |
| 76 | +- **Node.js**: ES Modules (`"type": "module"`) |
| 77 | + |
| 78 | +### Styling |
| 79 | +- **Tailwind CSS 4.1.14**: Utility-first CSS framework |
| 80 | +- **@tailwindcss/typography**: Typography plugin for prose content |
| 81 | +- **Custom Fonts**: |
| 82 | + - **Styrene A**: Sans-serif font for headings (weights: 100-900) |
| 83 | + - **Styrene B**: Monospace font for code (weights: 100-900) |
| 84 | + - **Tiempos Text**: Serif font for body text (weights: 400-700) |
| 85 | + - **Tiempos Fine**: Serif variant (weights: 300-900) |
| 86 | + - **Tiempos Headline**: Serif variant for headlines (weights: 300-900) |
| 87 | + |
| 88 | +### Markdown Processing |
| 89 | +- **markdown-it**: Markdown parser |
| 90 | +- **rehype-slug**: Automatically add IDs to headings |
| 91 | +- **rehype-autolink-headings**: Make headings linkable (wrap behavior) |
| 92 | +- **Custom rehype plugin**: `rehypeWrapTables` wraps tables in scrollable divs |
| 93 | +- **Syntax highlighting**: GitHub Dark theme via Shiki |
| 94 | + |
| 95 | +### Content Management |
| 96 | +- **Content Collections**: Defined in `src/content.config.ts` |
| 97 | + - **blog**: Markdown files with frontmatter (title, description, pubDate, modDate) |
| 98 | + - **tracks**: JSON file with music track data (id, title, youtubeLink, artist, album) |
| 99 | + |
| 100 | +### Integrations |
| 101 | +- **@astrojs/sitemap**: Automatic sitemap generation |
| 102 | +- **@astrojs/rss**: RSS feed support |
| 103 | +- **sanitize-html**: HTML sanitization |
| 104 | + |
| 105 | +### Development Tools |
| 106 | +- **Prettier**: Code formatting with plugins for Astro and Tailwind |
| 107 | +- **Nix**: Development environment and server deployment |
| 108 | + |
| 109 | +## Development Workflows |
| 110 | + |
| 111 | +### Essential Commands |
| 112 | + |
| 113 | +```bash |
| 114 | +# Development |
| 115 | +npm run dev # Start Astro dev server (http://localhost:4321) |
| 116 | +npm run build # Build for production |
| 117 | +npm run preview # Preview production build |
| 118 | +npm run format # Format code with Prettier |
| 119 | + |
| 120 | +# Nix (if using Nix) |
| 121 | +nix develop # Enter dev shell (includes nixd, nixfmt) |
| 122 | +nix run .#eval-server # Validate NixOS configuration |
| 123 | +nix run .#deploy-server # Deploy to remote NixOS server |
| 124 | +``` |
| 125 | + |
| 126 | +### Starting Development |
| 127 | +1. Install dependencies: `npm install` |
| 128 | +2. Start dev server: `npm run dev` |
| 129 | +3. Open browser to `http://localhost:4321` |
| 130 | + |
| 131 | +### Building for Production |
| 132 | +1. Run build: `npm run build` |
| 133 | +2. Output is in `dist/` directory |
| 134 | +3. Preview with: `npm run preview` |
| 135 | + |
| 136 | +## Content Management |
| 137 | + |
| 138 | +### Creating Blog Posts |
| 139 | + |
| 140 | +Blog posts are stored in `src/content/blog/` with each post in its own directory containing a `index.md` file. |
| 141 | + |
| 142 | +**Required frontmatter structure**: |
| 143 | +```markdown |
| 144 | +--- |
| 145 | +title: "Your Post Title" |
| 146 | +description: "A brief description of the post" |
| 147 | +pubDate: "2025-01-04" |
| 148 | +modDate: "2025-04-27" # Optional |
| 149 | +--- |
| 150 | + |
| 151 | +## Your Content Here |
| 152 | + |
| 153 | +Write your blog post content using Markdown... |
| 154 | +``` |
| 155 | + |
| 156 | +**Blog post conventions**: |
| 157 | +- Each post lives in its own directory: `src/content/blog/post-slug/index.md` |
| 158 | +- Use kebab-case for directory names (e.g., `nixos-with-ext4-and-luks`) |
| 159 | +- Include high-quality images in the same directory as the post |
| 160 | +- Dates in `YYYY-MM-DD` format |
| 161 | +- `modDate` is optional (use when updating existing posts) |
| 162 | + |
| 163 | +### Adding Music Tracks |
| 164 | + |
| 165 | +Edit `src/content/tracks.json` following this schema: |
| 166 | +```json |
| 167 | +{ |
| 168 | + "id": 1, |
| 169 | + "title": "Track Title", |
| 170 | + "youtubeLink": "https://youtube.com/...", |
| 171 | + "artist": "Artist Name", |
| 172 | + "album": "Album Name" |
| 173 | +} |
| 174 | +``` |
| 175 | + |
| 176 | +## Code Conventions |
| 177 | + |
| 178 | +### TypeScript |
| 179 | +- Use strict TypeScript configuration |
| 180 | +- Define types explicitly where needed |
| 181 | +- Leverage Astro's built-in type system |
| 182 | + |
| 183 | +### Astro Components |
| 184 | +- Use `.astro` file extension |
| 185 | +- Component names should be PascalCase (e.g., `TableOfContents.astro`) |
| 186 | +- Place reusable components in `src/components/` |
| 187 | +- Use layouts for page templates (`src/layouts/`) |
| 188 | + |
| 189 | +### Styling |
| 190 | +- Use Tailwind utility classes for styling |
| 191 | +- Custom styles go in `src/styles/global.css` |
| 192 | +- Follow the custom variant pattern: `@custom-variant dark (&:where(.dark, .dark *))` |
| 193 | +- Apply responsive design with Tailwind's breakpoint prefixes |
| 194 | + |
| 195 | +### Formatting |
| 196 | +- Always run `npm run format` before committing |
| 197 | +- Prettier automatically formats: |
| 198 | + - Astro files (via `prettier-plugin-astro`) |
| 199 | + - Tailwind classes (via `prettier-plugin-tailwindcss`) |
| 200 | +- Configuration is in `.prettierrc` |
| 201 | + |
| 202 | +### File Naming |
| 203 | +- Components: PascalCase (e.g., `Header.astro`) |
| 204 | +- Pages: kebab-case or descriptive names (e.g., `index.astro`, `legal-disclosure.astro`) |
| 205 | +- Content directories: kebab-case (e.g., `nixos-with-ext4-and-luks`) |
| 206 | +- Configuration files: standard names (e.g., `astro.config.ts`) |
| 207 | + |
| 208 | +## Deployment |
| 209 | + |
| 210 | +### GitHub Pages |
| 211 | +- **Automatic deployment** on push to `main` branch |
| 212 | +- Workflow file: `.github/workflows/deploy.yml` |
| 213 | +- Uses official Astro GitHub Action (`withastro/action@v3`) |
| 214 | +- Custom domain: thilohohlt.com (configured via `public/CNAME`) |
| 215 | + |
| 216 | +### Deployment Process |
| 217 | +1. Push to `main` branch |
| 218 | +2. GitHub Actions builds the site |
| 219 | +3. Astro generates static files |
| 220 | +4. Deploy to GitHub Pages |
| 221 | +5. Site available at https://thilohohlt.com |
| 222 | + |
| 223 | +### Build Configuration |
| 224 | +- Site URL: `https://thilohohlt.com` (defined in `astro.config.ts`) |
| 225 | +- Prefetch: All links are prefetched (`prefetchAll: true`) |
| 226 | +- Output: Static HTML/CSS/JS in `dist/` |
| 227 | + |
| 228 | +## NixOS Server Configuration |
| 229 | + |
| 230 | +This repository includes Nix configuration for self-hosted services listed at https://thilohohlt.com/services. |
| 231 | + |
| 232 | +### Nix Files |
| 233 | +- `flake.nix`: Main Nix flake configuration |
| 234 | +- `flake.lock`: Dependency lock file |
| 235 | +- `server/default.nix`: NixOS system configuration |
| 236 | +- `server/hardware-configuration.nix`: Hardware-specific settings |
| 237 | + |
| 238 | +### Nix Workflows |
| 239 | +```bash |
| 240 | +# Enter development shell (provides nixd, nixfmt) |
| 241 | +nix develop |
| 242 | + |
| 243 | +# Validate server configuration |
| 244 | +nix run .#eval-server |
| 245 | + |
| 246 | +# Deploy to remote server |
| 247 | +nix run .#deploy-server |
| 248 | +# This will: |
| 249 | +# 1. Evaluate the configuration |
| 250 | +# 2. Connect to the remote server (91.98.171.83) |
| 251 | +# 3. Build and switch to new configuration |
| 252 | +``` |
| 253 | + |
| 254 | +### IDE Support for Nix |
| 255 | +For NixOS option completions, use the `jnoortheen.nix-ide` VSCode extension with these settings: |
| 256 | +```json |
| 257 | +{ |
| 258 | + "nix.enableLanguageServer": true, |
| 259 | + "nix.serverPath": "nil", |
| 260 | + "nix.serverSettings": { |
| 261 | + "nixd": { |
| 262 | + "formatting": { |
| 263 | + "command": ["nixfmt"] |
| 264 | + } |
| 265 | + } |
| 266 | + } |
| 267 | +} |
| 268 | +``` |
| 269 | + |
| 270 | +## Key Features to Preserve |
| 271 | + |
| 272 | +### Custom Rehype Plugins |
| 273 | +The `rehypeWrapTables` plugin wraps tables in scrollable divs for responsive design: |
| 274 | +```typescript |
| 275 | +const rehypeWrapTables = () => { |
| 276 | + // Wraps tables in div.overflow-x-auto.max-w-full |
| 277 | + // Ensures tables are scrollable on mobile |
| 278 | +} |
| 279 | +``` |
| 280 | + |
| 281 | +### Markdown Configuration |
| 282 | +- Syntax highlighting: GitHub Dark theme |
| 283 | +- Auto-generated heading IDs (via rehype-slug) |
| 284 | +- Clickable headings that wrap content (via rehype-autolink-headings) |
| 285 | +- Tables wrapped for horizontal scrolling |
| 286 | + |
| 287 | +### Font Loading |
| 288 | +- All fonts use `font-display: swap` for performance |
| 289 | +- Fonts are self-hosted in `/public/fonts/` |
| 290 | +- Font families defined in `src/styles/global.css` |
| 291 | + |
| 292 | +## Important Notes for AI Assistants |
| 293 | + |
| 294 | +### When Making Changes |
| 295 | + |
| 296 | +1. **Always read files before editing**: Use the Read tool before making changes to understand existing code structure |
| 297 | +2. **Preserve existing conventions**: Don't introduce new patterns unless necessary |
| 298 | +3. **Test locally**: Encourage running `npm run dev` to test changes |
| 299 | +4. **Format before committing**: Run `npm run format` to ensure consistent code style |
| 300 | +5. **Respect content structure**: Blog posts must have proper frontmatter and directory structure |
| 301 | +6. **Don't over-engineer**: Keep solutions simple and focused on the requested changes |
| 302 | + |
| 303 | +### Common Tasks |
| 304 | + |
| 305 | +**Adding a new blog post**: |
| 306 | +1. Create directory in `src/content/blog/` with kebab-case name |
| 307 | +2. Add `index.md` with proper frontmatter |
| 308 | +3. Write content using Markdown |
| 309 | +4. Test with `npm run dev` |
| 310 | + |
| 311 | +**Modifying a component**: |
| 312 | +1. Read the component file first |
| 313 | +2. Understand its usage across the site |
| 314 | +3. Make targeted changes |
| 315 | +4. Preserve existing styling patterns |
| 316 | +5. Format with Prettier |
| 317 | + |
| 318 | +**Updating styles**: |
| 319 | +1. Check `src/styles/global.css` for existing patterns |
| 320 | +2. Use Tailwind utilities when possible |
| 321 | +3. Add custom CSS only when necessary |
| 322 | +4. Maintain dark mode support via custom variant |
| 323 | + |
| 324 | +**Working with NixOS configuration**: |
| 325 | +1. Changes to server config go in `server/` directory |
| 326 | +2. Always validate with `nix run .#eval-server` before deploying |
| 327 | +3. Be cautious with production server changes |
| 328 | +4. Test locally when possible |
| 329 | + |
| 330 | +### Things to Avoid |
| 331 | + |
| 332 | +- ❌ Don't create documentation files unless explicitly requested |
| 333 | +- ❌ Don't add unnecessary comments or docstrings |
| 334 | +- ❌ Don't refactor code that isn't related to the task |
| 335 | +- ❌ Don't add dependencies without good reason |
| 336 | +- ❌ Don't modify font files or licenses in `/public/fonts/` |
| 337 | +- ❌ Don't change the deployment workflow without understanding implications |
| 338 | +- ❌ Don't edit generated files in `.astro/` or `dist/` |
| 339 | + |
| 340 | +## Troubleshooting |
| 341 | + |
| 342 | +### Build Fails |
| 343 | +- Check `astro.config.ts` for syntax errors |
| 344 | +- Verify all blog posts have required frontmatter |
| 345 | +- Ensure TypeScript types are correct |
| 346 | +- Run `npm install` to update dependencies |
| 347 | + |
| 348 | +### Dev Server Issues |
| 349 | +- Port 4321 might be in use (kill the process or use `--port` flag) |
| 350 | +- Clear `.astro/` directory and rebuild: `rm -rf .astro && npm run dev` |
| 351 | +- Check for TypeScript errors in components |
| 352 | + |
| 353 | +### Styling Problems |
| 354 | +- Run `npm run format` to fix Tailwind class ordering |
| 355 | +- Check global.css for font loading issues |
| 356 | +- Verify Tailwind plugin is loaded in Vite config |
| 357 | + |
| 358 | +### Content Not Appearing |
| 359 | +- Verify content collection schema in `src/content.config.ts` |
| 360 | +- Check frontmatter matches schema requirements |
| 361 | +- Ensure file paths are correct |
| 362 | +- Restart dev server after adding new content files |
| 363 | + |
| 364 | +## Resources |
| 365 | + |
| 366 | +- **Astro Docs**: https://docs.astro.build/ |
| 367 | +- **Tailwind CSS Docs**: https://tailwindcss.com/docs |
| 368 | +- **Nix Manual**: https://nixos.org/manual/nix/stable/ |
| 369 | +- **Site Repository**: https://github.com/thiloho/thiloho.github.io (inferred) |
| 370 | + |
| 371 | +## Version Info |
| 372 | + |
| 373 | +Last updated: 2025-12-07 |
| 374 | +Astro version: 5.14.6 |
| 375 | +Tailwind version: 4.1.14 |
| 376 | +Node.js: ES Modules |
0 commit comments