diff --git a/.claude/commands/new-post.md b/.claude/commands/new-post.md
new file mode 100644
index 0000000..b4f4382
--- /dev/null
+++ b/.claude/commands/new-post.md
@@ -0,0 +1,33 @@
+Create a new blog post MDX file for this Next.js + Contentlayer2 blog.
+
+The user will provide a title (or ask them for one if not given). Then:
+
+1. Convert the title to a kebab-case filename: `data/blog/kebab-case-title.mdx`
+2. Use today's date in `YYYY-MM-DD` format
+3. Ask the user for a one-paragraph summary if they haven't provided one
+4. Create the file with this exact frontmatter structure:
+
+```mdx
+---
+title: 'Title Here'
+date: 'YYYY-MM-DD'
+tags: []
+draft: true
+summary: ''
+layout: DaveLayout
+images: []
+authors: ['default']
+---
+
+Write your introduction here.
+```
+
+Set `draft: true` so it doesn't publish until the user is ready.
+Leave `tags: []` empty — the user will add tags as they write.
+
+After creating the file, tell the user:
+
+- The file path created
+- To run `yarn dev` to preview it at `http://localhost:3000/blog/[slug]`
+- To change `draft: false` when ready to publish
+- **Before publishing:** add at least one image to `images: []` — posts without an image fall back to the generic site banner for social sharing. Store images at `public/static/images/posts/YYYY/post-slug-name/` and reference as `/static/images/posts/YYYY/post-slug-name/image.png`.
diff --git a/.claude/settings.local.json b/.claude/settings.local.json
new file mode 100644
index 0000000..c5a9c62
--- /dev/null
+++ b/.claude/settings.local.json
@@ -0,0 +1,7 @@
+{
+ "permissions": {
+ "additionalDirectories": [
+ "c:\\Dave\\Projects\\DaveGoosem.github.io\\.claude"
+ ]
+ }
+}
diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644
index 0000000..28c1cda
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,73 @@
+# DaveGoosem.com — Claude Code Context
+
+## Stack
+
+- **Framework**: Next.js 14 (App Router), TypeScript
+- **Content**: Contentlayer2 — MDX files in `data/blog/` and `data/authors/`
+- **Styles**: Tailwind CSS 3 (class-based dark mode, Space Grotesk font)
+- **Deployment**: Vercel
+- **Package manager**: `yarn` — never use `npm install` or `npm run`
+- **Comments**: Giscus (GitHub Discussions), configured via env vars
+- **Search**: kbar (local `public/search.json`, regenerated on build)
+- **Analytics**: Google Analytics via Pliny
+
+## Key Commands
+
+```bash
+yarn dev # start dev server
+yarn build # production build + postbuild (RSS, search index)
+yarn lint # ESLint with auto-fix
+```
+
+## Path Aliases (tsconfig.json)
+
+| Alias | Resolves to |
+| ------------------------ | ------------------------- |
+| `@/components/*` | `components/*` |
+| `@/data/*` | `data/*` |
+| `@/layouts/*` | `layouts/*` |
+| `@/css/*` | `css/*` |
+| `contentlayer/generated` | `.contentlayer/generated` |
+
+## Key Directories
+
+| Path | Purpose |
+| ----------------------- | -------------------------------------- |
+| `app/` | Next.js App Router pages |
+| `components/` | Shared React components |
+| `layouts/` | Blog post layout templates |
+| `data/blog/` | MDX blog posts (41 posts) |
+| `data/authors/` | Author MDX profiles |
+| `data/siteMetadata.js` | Site-wide config (title, URL, socials) |
+| `public/static/images/` | Static image assets |
+| `scripts/` | postbuild.mjs (RSS + search index) |
+
+## SEO & Structured Data
+
+The following are already implemented — do not duplicate or replace them:
+
+- **Canonical URLs** — set in `generateMetadata()` in `app/blog/[...slug]/page.tsx` via `post.canonicalUrl ?? computed URL`
+- **`BlogPosting` JSON-LD** — generated by Contentlayer in `contentlayer.config.ts` (includes `publisher`, `mainEntityOfPage`, `author`). Injected in `app/blog/[...slug]/page.tsx`
+- **`BreadcrumbList` JSON-LD** — injected alongside BlogPosting in `app/blog/[...slug]/page.tsx`
+- **`WebSite` JSON-LD** — injected in `app/layout.tsx` (covers all pages)
+- **Publisher logo** — uses `DaveGoosem.com_Logo_Black.png` (not the white variant) so it is legible on white backgrounds as Google requires
+- **Sitemap** — `app/sitemap.ts`, auto-generated, excludes drafts
+- **Robots** — `app/robots.ts`, auto-generated
+
+## Constraints
+
+- Do not add API routes — this is a static/SSG blog with no backend
+- Do not add a database or server-side state
+- Contentlayer2 auto-generates TypeScript types on `yarn build` / `yarn dev` — do not edit `.contentlayer/` manually
+- ESLint uses flat config (`eslint.config.mjs`) — not `.eslintrc`
+- External links require `target="_blank"` and `rel="noopener noreferrer"` (enforced by ESLint)
+
+## Gotchas
+
+**Contentlayer scans all of `data/`** — any plain `.md` file placed inside `data/` (e.g. a `CLAUDE.md`) must be added to `contentDirExclude` in `contentlayer.config.ts` → `makeSource()`, otherwise Contentlayer warns and skips it at startup.
+
+**Content Security Policy** — `next.config.js` contains a hand-written CSP string. If you add any external script, font, frame, or image source (e.g. a new analytics provider, embed, or CDN), add its hostname to the appropriate CSP directive in that file or the browser will silently block it.
+
+**Remote images** — `next/image` only proxies domains listed in `next.config.js` → `images.remotePatterns`. Currently only `picsum.photos` is allowed. Add new domains there before using external image URLs in posts or components.
+
+**Bundle analysis** — run `ANALYZE=true yarn build` to open the webpack bundle visualiser. Useful before committing large new dependencies.
diff --git a/app/CLAUDE.md b/app/CLAUDE.md
new file mode 100644
index 0000000..d443274
--- /dev/null
+++ b/app/CLAUDE.md
@@ -0,0 +1,43 @@
+# App Router — Claude Code Context
+
+## Route Structure
+
+| Route | File | Notes |
+| ------------------- | ------------------------------- | ---------------------------------------- |
+| `/` | `app/page.tsx` | Home (recent posts via `Main.tsx`) |
+| `/blog` | `app/blog/page.tsx` | Post listing |
+| `/blog/[...slug]` | `app/blog/[...slug]/page.tsx` | Individual post — slug from MDX filename |
+| `/blog/page/[page]` | `app/blog/page/[page]/page.tsx` | Paginated listing |
+| `/tags` | `app/tags/page.tsx` | All tags |
+| `/tags/[tag]` | `app/tags/[tag]/page.tsx` | Posts by tag |
+| `/about` | `app/about/page.tsx` | About page |
+| `/projects` | `app/projects/page.tsx` | Projects page |
+
+## Blog Post Rendering
+
+Posts flow: MDX file → Contentlayer2 (generates typed object) → `app/blog/[...slug]/page.tsx` → layout component (e.g. `DaveLayout`).
+
+## SEO & Metadata
+
+**For static pages** (`/about`, `/projects`, `/tags`, etc.) — use `genPageMetadata()` from `app/seo.tsx`:
+
+```ts
+import { genPageMetadata } from 'app/seo'
+export const metadata = genPageMetadata({ title: 'Page Title', description: '...' })
+```
+
+**For blog posts** — metadata is generated dynamically in `app/blog/[...slug]/page.tsx` via `generateMetadata()`. It reads from the post's Contentlayer fields directly — do not duplicate it elsewhere.
+
+**Do not write raw `` tags** — always go through the Next.js Metadata API or `genPageMetadata()`.
+
+**Structured data (JSON-LD)** — blog posts render two `