Skip to content

Latest commit

 

History

History
95 lines (70 loc) · 5 KB

File metadata and controls

95 lines (70 loc) · 5 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Overview

Static personal website hosted on GitHub Pages at sebastianelsner.de. No build step, no framework, no package manager — plain HTML + a single CSS file, deployed directly from the master branch.

Design system

All pages use the engineering notebook aesthetic defined in css/notebook.css:

  • Type: JetBrains Mono for structural / CV / metadata; EB Garamond italic for the music section disruption and for blog post body (long-form readability).
  • Palette: warm paper (--paper), ink, amber accent, oxblood reserved for the music section. Full dark-mode variant via prefers-color-scheme: dark.
  • Fonts: served from fonts.bunny.net (GDPR-compliant Google Fonts mirror).
  • Disruption rule: the music section is the only place that breaks from mono. Any new "fun" or personal section should follow the same pattern (paper-deep background, serif italic headline, oxblood accent).

Adding a blog post

  1. Duplicate blog/hello-world.html and rename to a slug (e.g. blog/my-post.html).

  2. Update the head — change these and leave the rest alone:

    • <title>
    • <meta name="description"> (target 110–160 chars)
    • <meta property="og:title"> (target 50–60 chars)
    • <meta property="og:description">
    • <meta property="og:url">
    • og:type=article, og:site_name, twitter:card, the Bunny font links, the favicon links, and the Umami snippet are already correct from the duplicate — don't touch.
  3. Update the body:

    • <h1> and .post-meta date.
    • For posts with a magazine-style subtitle, drop a <p class="dek">subtitle</p> between the <h1> and .post-meta (italic EB Garamond — see ai-and-my-taxes.html).
    • Content lives inside <div class="body">…</div>. Available tags: <p>, <h2> (serif italic oxblood), <h3> (small mono uppercase), <code>, <pre>, <ul>, <a>, <strong>, <em>, <sup>, plus <p class="tldr"><strong>TL;DR</strong> …</p> for the lede.
  4. Add to blog/index.html at the top of the writing list (newest first; the listing keeps every post):

    <a class="post" href="my-post.html">
        <div class="when">Month DD, YYYY</div>
        <div class="body">
            <h3>Post Title</h3>
            <p>One-line teaser.</p>
        </div>
        <div class="arrow" aria-hidden="true"></div>
    </a>
  5. Add the same teaser at the top of <section class="writing"> in the root index.html, and remove the oldest one so the home shows the latest 3 only.

  6. Generate the per-post OG card and point the post at it:

    bin/og-card "Post Title" my-post "Month DD, YYYY"

    That writes assets/img/og-my-post.png (1200×630). Then update the post's head:

    <meta property="og:image" content="https://sebastianelsner.de/assets/img/og-my-post.png" />
    <meta property="og:image:alt" content="Post Title — Sebastian Elsner, Month DD, YYYY" />

    The script needs inkscape on PATH and nothing else.

  7. Verify locally before pushing — open the new post in a browser, check the dek/body styling and the OG card render at /assets/img/og-my-post.png.

OG cards

  • Site-level pages (root index.html, blog/index.html) use assets/img/og.png — the brand card (name, manifesto, pillars).

  • Each blog post has its own assets/img/og-<slug>.png generated by bin/og-card. Title centred, auto-wrapped up to 3 lines (32 chars/line).

  • All cards render at 2× (2400×1260) so platform downscalers (LinkedIn, Slack, etc.) keep the mono text crisp after their JPEG re-encoding. The og:image:width / og:image:height meta on every page reflects this.

  • Brand card source lives at bin/og-brand.svg. To regenerate after editing:

    inkscape bin/og-brand.svg --export-type=png \
        --export-filename=assets/img/og.png \
        --export-width=2400 --export-height=1260
  • Per-post template lives inside bin/og-card (Python heredoc) — edit there if the design needs to change for all posts at once.

Page structure conventions

  • Root pages link css/notebook.css and assets/img/favicon.ico. Blog pages use ../css/notebook.css and ../assets/img/favicon.ico.
  • Every page must include the Bunny font preconnect + stylesheet link (JetBrains Mono + EB Garamond).
  • Every page must include the Umami snippet just before </head>.
  • Decorative glyphs (##, , , , _) carry aria-hidden="true".
  • Section headings use <h2 class="name"> inside <div class="sec-h">. Don't downgrade to <span> — heading hierarchy matters.

Analytics

Every page includes:

<!-- Umami analytics -->
<script defer src="https://cloud.umami.is/script.js" data-website-id="73702148-36e0-4a0b-889e-6e1c29e062c0"></script>

No templating layer, so this snippet must be present on every new HTML page. Duplicating an existing post carries it over automatically; pages created from scratch must add it manually.