|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Project Overview |
| 6 | + |
| 7 | +This is a personal website/blog built with SvelteKit that supports IndieWeb protocols. The site is a static site generator that processes markdown content and deploys to GitHub Pages at tiim.ch. |
| 8 | + |
| 9 | +## Common Commands |
| 10 | + |
| 11 | +### Development |
| 12 | + |
| 13 | +```bash |
| 14 | +npm run dev # Start dev server (copies assets and runs vite dev) |
| 15 | +npm run build # Production build (copies assets and runs vite build) |
| 16 | +npm run preview # Preview production build |
| 17 | +``` |
| 18 | + |
| 19 | +### Code Quality |
| 20 | + |
| 21 | +```bash |
| 22 | +npm run lint # Run prettier check and eslint |
| 23 | +npm run format # Format code with prettier |
| 24 | +``` |
| 25 | + |
| 26 | +### Deployment |
| 27 | + |
| 28 | +- Main branch: `source` (development branch) |
| 29 | +- Deploy branch: `master` (GitHub Pages) |
| 30 | +- Deployment is automated via GitHub Actions on push to `source` branch |
| 31 | +- Manual deployment: `./deploy.sh` (lints, builds, and force-pushes to master) |
| 32 | + |
| 33 | +## Architecture |
| 34 | + |
| 35 | +### Content System |
| 36 | + |
| 37 | +The content system is the core of the site, loading and processing markdown files from the `content/` directory: |
| 38 | + |
| 39 | +- **Content loader** (`src/lib/content.js`): `getContent()` function loads all markdown content into memory at build time and caches it (except in dev mode). Returns a unified content object with: |
| 40 | + - `allBlogPosts`, `pages`, `projects`, `notes` - categorized content arrays |
| 41 | + - `contentMap` - slug-to-content lookup map |
| 42 | + - `tagsMap` - tag-to-posts mapping |
| 43 | + - `comments` - loaded from external API (comments.tiim.ch or localhost:8080 in dev) |
| 44 | + - `mf2` - microformats2 metadata from content/mf2.json |
| 45 | + - `queryContent(slug)` - helper to get content by slug |
| 46 | + |
| 47 | +- **Markdown processor** (`src/lib/markdown.js`): `process(fileName)` converts markdown files using a unified/remark/rehype pipeline: |
| 48 | + - Parses frontmatter (YAML) |
| 49 | + - Custom remark plugins: absoluteLink, hideWikilink, highlight |
| 50 | + - Custom rehype plugins: callout |
| 51 | + - Adds external link attributes (nofollow, noopener, noreferrer) |
| 52 | + - Generates microformats2 markup for IndieWeb post types (reply, like, repost, rsvp, photo, note) |
| 53 | + - Enforces date+time requirement for posts after 2023-01-29 |
| 54 | + |
| 55 | +### Content Structure |
| 56 | + |
| 57 | +Content is organized by type in `content/` folder: |
| 58 | + |
| 59 | +- `blog/` - Full blog posts/articles (sorted by date, type: "article") |
| 60 | +- `projects/` - Project descriptions (type: "article") |
| 61 | +- `pages/` - Standalone pages (e.g., uses, links) |
| 62 | +- `mf2/` - Short-form IndieWeb content: notes, replies, likes, reposts (auto-published, type determined by frontmatter) |
| 63 | +- `metadata/` - Special markdown for site components (footer, about) with mf2 variable substitution |
| 64 | +- `tags/` - Tag descriptions |
| 65 | +- `assets/` - Images (copied to static/assets/ on build) |
| 66 | + |
| 67 | +### Frontmatter Fields |
| 68 | + |
| 69 | +All content supports these frontmatter fields: |
| 70 | + |
| 71 | +- `uuid`, `title`, `published` (boolean, default false except mf2), `description`, `content_tags` (array) |
| 72 | +- `date` (required for published content, must include time after 2023-01-29), `modified` |
| 73 | +- `cover_image`, `links` (array of URLs shown at top) |
| 74 | +- IndieWeb: `in_reply_to`, `like_of`, `repost_of`, `rsvp`, `syndication`, `photos` |
| 75 | + |
| 76 | +### Routing |
| 77 | + |
| 78 | +SvelteKit file-based routing in `src/routes/`: |
| 79 | + |
| 80 | +- `/` - Homepage |
| 81 | +- `/blog/[slug]` - Blog posts from content/blog/ |
| 82 | +- `/projects/[slug]` - Projects from content/projects/ |
| 83 | +- `/pages/[page_slug]` - Pages from content/pages/ |
| 84 | +- `/mf2/[...slug]` - Notes from content/mf2/ (supports nested paths) |
| 85 | +- `/tags/[slug]` - Tag listing pages |
| 86 | +- `/blog/rss.xml` - RSS feed for blog |
| 87 | +- `/full-rss.xml` - Full RSS feed (all content) |
| 88 | + |
| 89 | +All routes use `+page.server.js` to load content via `getContent()` at build time. |
| 90 | + |
| 91 | +### Custom Markdown Plugins |
| 92 | + |
| 93 | +Located in `src/lib/markdown/`: |
| 94 | + |
| 95 | +- `remarkAbsoluteLink.js` - Converts relative markdown links to absolute URLs |
| 96 | +- `remarkHideWikilink.js` - Hides Obsidian-style wikilinks |
| 97 | +- `remarkHighlight.js` - Syntax highlighting |
| 98 | +- `rehypeCallout.js` - Custom callout/admonition blocks |
| 99 | +- `extractAbstract.js` - Extracts content summary |
| 100 | + |
| 101 | +### Configuration |
| 102 | + |
| 103 | +- **Vite aliases**: `$content` → `./content`, `@` → `src` |
| 104 | +- **SvelteKit adapter**: `@sveltejs/adapter-static` with prerendering |
| 105 | +- **Dev server**: Allows reading from `content/` directory |
| 106 | +- **SVG plugin**: Processes SVG imports with optimization |
| 107 | + |
| 108 | +### IndieWeb Integration |
| 109 | + |
| 110 | +The site implements IndieWeb standards: |
| 111 | + |
| 112 | +- Microformats2 markup automatically added based on frontmatter |
| 113 | +- Post type discovery algorithm (rsvp > reply > repost > like > photo > note) |
| 114 | +- External commenting system integration |
| 115 | +- Variable substitution in metadata files for h-card properties |
| 116 | + |
| 117 | +## Development Notes |
| 118 | + |
| 119 | +- Content is cached in production but reloaded on each request in dev mode |
| 120 | +- Comments are fetched from external API (separate commenting service) |
| 121 | +- Assets must be manually copied from content/assets/ to static/assets/ (automated in dev/build scripts) |
| 122 | +- Unpublished content is skipped in production but shown in dev mode |
| 123 | +- All markdown files support `%%comment%%` syntax for inline comments (stripped during processing) |
0 commit comments