Files
blog/CLAUDE.md
Gabriel Vidal aacec8703e chore: drop the dead GitHub Pages workflow, add CLAUDE.md
`.github/workflows/main.yml` triggered on the `new-main` branch, which has not
been the publishing branch for a long time — the site is built and rsynced to
zipgo on raspy2 by `npm run deploy`. It was dead weight pointing at the wrong
deploy story, so remove it; there is no CI now.

Add a project CLAUDE.md. Its main rule: any post generated by Claude MUST carry
the AI-disclosure callout at the top of the body, with the exact block to paste;
plus the frontmatter/asset conventions, the tailwind-scans-markdown and
postbuild-search-index gotchas, and the verify-before-deploy steps.

Fix two stale README claims while here: posts live in src/content/blog (not
src/pages/blog) and drafts in src/drafts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 13:16:33 +02:00

4.6 KiB

CLAUDE.md — blog

Guidance for Claude Code working in this repo. See README.md for the human-facing version.

What this is

My personal website / blog, live at https://blog.dev.gabvdl.xyz. Astro 2 (based on the astro-ink theme): markdown/MDX posts, client-side Lunr search, tags, RSS, sitemap. Static build → dist/, served by zipgo on raspy2.

origin is the self-hosted Gitea (git.gabvdl.xyz/gabrielvidal/blog) — that is canonical. github is a secondary mirror of the old GabrielVidal1/gabrielvidal1.github.io repo; nothing depends on it. There is no CI: nothing publishes on push, only npm run deploy.

Writing a post

One file: src/content/blog/<YYYY-MM-DD>-<Title>.md (or .mdx). Frontmatter is validated by the zod schema in src/content/config.tstitle (≤100 chars), tags (required array), and optional description / techs / date / cover / project / links. Drafts are plain markdown in src/drafts/.

Images go in public/assets/posts/<PostName>/ and are referenced with raw HTML:

<img src="/assets/posts/<PostName>/shot.jpeg" alt="…" class="w-full rounded-lg shadow-lg">

⚠️ AI-generated posts MUST carry the disclaimer

Any post you generate gets an AI-disclosure callout as the first thing in the body, above the opening paragraph. This is not optional and not something to ask about — if you wrote the post, the callout ships with it. Only a post I wrote myself may omit it.

Paste this block verbatim at the top of the post body (adjust only the model name and, if the sourcing genuinely differs, the second sentence):

<aside class="not-prose my-8 flex items-start gap-4 rounded-lg border border-theme-primary/30 bg-theme-primary/5 p-5 dark:border-theme-dark-primary/40 dark:bg-theme-dark-primary/10">
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" class="mt-0.5 h-7 w-7 shrink-0 text-theme-primary dark:text-theme-dark-primary">
    <path d="M12 2v4"/>
    <rect x="3" y="6" width="18" height="14" rx="3"/>
    <circle cx="8.5" cy="12" r="1.4" fill="currentColor" stroke="none"/>
    <circle cx="15.5" cy="12" r="1.4" fill="currentColor" stroke="none"/>
    <path d="M9 16.5h6"/>
    <path d="M1.5 11v4M22.5 11v4"/>
  </svg>
  <div class="text-sm leading-relaxed">
    <p class="font-bold text-theme-primary dark:text-theme-dark-primary">AI-generated article</p>
    <p class="mt-1 text-gray-700 dark:text-gray-300">
      This post was written by <strong>Claude Opus 5</strong>, working from my own
      projects, tests, benchmarks, memories and past conversations. The
      measurements, code and screenshots come from my hardware and my repositories —
      the writing is the model's.
    </p>
  </div>
</aside>

2026-08-06-Trellis2-Strix-Halo.md is the reference example.

Alongside the callout: don't invent numbers. Benchmarks, timings and code snippets in a generated post must come from a real run or a real file — measure or read it, don't estimate and round.

Gotchas

  • Tailwind scans markdown. tailwind.config.cjs includes .md/.mdx in content on purpose. Before that, a class used only in a post was emitted only by luck (if some .astro file happened to use it too), so callouts and image classes silently rendered unstyled. Don't narrow that glob.
  • Dark mode is class-based. Every custom colour needs a dark: counterpart — use the theme tokens (theme-primary / theme-dark-primary), not raw palette colours, so the site's theme switcher keeps working.
  • The search index is a postbuild step (scripts/search/prepare-index.js), which runs after Astro copies public/dist/. It writes public/ and mirrors into dist/; that mirror is load-bearing. Without it every deploy ships a search index one post behind. scripts/deploy.sh refuses to deploy if dist/search-index.json is missing.
  • npm run deploy skips og-screenshot unlike the scaffolded homelab projects — this site has a curated public/og-image.png and a screenshot of the index would be strictly worse.

Verify before deploying

npm run build                    # must pass; check the post renders
npx astro preview                # or serve dist/ and look at the page
npm run deploy                   # build + zipgo deploy to raspy2

For a generated post, actually look at the rendered page (screenshot it) — check the callout, the images, tables and code blocks in both light and dark mode before deploying.