|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +Guidance for Claude when working in this repo. Keep it tight — update as conventions evolve. |
| 4 | + |
| 5 | +## What this is |
| 6 | + |
| 7 | +`marcusoft.net` — Marcus Hammarberg's personal blog. Jekyll site, live at <https://www.marcusoft.net>. Running since 2006. Tagline: *Learning by sharing since 2006.* There are 1000+ posts in [_posts/](_posts/); treat them as the source of truth for tone, conventions, and linking style. |
| 8 | + |
| 9 | +## Repo layout |
| 10 | + |
| 11 | +- [_posts/](_posts/) — published posts, one file per post |
| 12 | +- [_draft/](_draft/) — work-in-progress posts, not yet published |
| 13 | +- [_pages/](_pages/) — static pages (about, contact, archive, tags, talks, search, wordcloud) |
| 14 | +- [_layouts/](_layouts/), [_includes/](_includes/) — Jekyll templates |
| 15 | +- [assets/](assets/), [img/](img/), [fonts/](fonts/) — site assets; post images go in [img/](img/) |
| 16 | +- [scripts/](scripts/) — tooling (spellcheck, lint, scaffolding, wordcloud). See [README.md](README.md) for usage. |
| 17 | +- [.scripts/](.scripts/) — lower-level helpers (heading fixers) |
| 18 | +- [data/](data/) — generated data (wordclouds) |
| 19 | +- [_config.yml](_config.yml) — Jekyll config. Permalink format: `/:year/:month/:title.html`. |
| 20 | +- [.markdownlint.json](.markdownlint.json) — linting rules (MD013, MD024, MD033, MD059 disabled) |
| 21 | + |
| 22 | +## Posts — the important part |
| 23 | + |
| 24 | +### Filename |
| 25 | + |
| 26 | +`_posts/YYYY-MM-DD-kebab-case-title.md`. Date is the publish date. Filename title is lowercase with hyphens — no apostrophes, no punctuation. |
| 27 | + |
| 28 | +### Front matter |
| 29 | + |
| 30 | +```yaml |
| 31 | +--- |
| 32 | +layout: post |
| 33 | +title: "The post title in quotes" |
| 34 | +author: "Marcus Hammarberg" |
| 35 | +date: YYYY-MM-DD 04:00:00 |
| 36 | +tags: |
| 37 | + - Tag One |
| 38 | + - Tag Two |
| 39 | +--- |
| 40 | +``` |
| 41 | + |
| 42 | +Common tags seen in recent posts: `AI`, `Agile`, `Lean`, `Flow`, `Programming`, `Life of a consultant`. Match existing tags — don't invent new variants (e.g. don't add `agile` when `Agile` already exists). Grep [_posts/](_posts/) before adding a new tag. |
| 43 | + |
| 44 | +### Structure |
| 45 | + |
| 46 | +- Open with a hook — an anecdote, a question, a quote. Not a summary. |
| 47 | +- Put `<!-- excerpt-end -->` after the intro (usually 2–5 short paragraphs in). Everything before it shows on the index page. |
| 48 | +- Break the body with `## H2` sections. `###` for sub-sections. |
| 49 | +- Close with a short summary or a callback to the opening. |
| 50 | +- Images live in [img/](img/) and are referenced as `/img/filename.ext`. |
| 51 | +- Link generously — to prior marcusoft.net posts, to books, to the people Marcus learned from. This is a hypertext blog, not an island. |
| 52 | + |
| 53 | +### Scaffolding a new post |
| 54 | + |
| 55 | +```bash |
| 56 | +bash scripts/scaffold_post.sh "The post title" |
| 57 | +``` |
| 58 | + |
| 59 | +Creates the file with correct front matter and opens it in VS Code. |
| 60 | + |
| 61 | +## Voice — Marcus's style, not generic blog-voice |
| 62 | + |
| 63 | +Read a few recent posts before writing ([2026-03-02-navigating-uncertainty-ai-edition.md](_posts/2026-03-02-navigating-uncertainty-ai-edition.md), [2026-01-12-make-the-change-easy.md](_posts/2026-01-12-make-the-change-easy.md), [2025-12-17-on-yak-shaving.md](_posts/2025-12-17-on-yak-shaving.md), [2025-11-27-ai-and-lead-times.md](_posts/2025-11-27-ai-and-lead-times.md) are good recent samples). The voice is: |
| 64 | + |
| 65 | +- **First-person, conversational.** "I", "you", "we". Contractions. Sentence fragments when they land. |
| 66 | +- **Personal anecdote first, principle second.** A post about flow starts with Marcus waiting on a PR approval, not with a definition of flow. |
| 67 | +- **Warm self-deprecation.** "I'm old", "feeble mind", "Marcus makes numbers up to prove a point". Small asides in parentheses are normal. |
| 68 | +- **Credit generously.** Name the people you learned from (Kent Beck, Dan North, Woody Zuill, Gojko Adzic, Birgitta Böckeler, colleagues by first name). Link to their work. |
| 69 | +- **Quotes in blockquotes.** Use `>` for quotes that carry the post — Kent Beck's "make the change easy", Woody Zuill's "we often don't discover the work we need to do until we are doing the work". |
| 70 | +- **Emphasis is sparing.** *Italics* and **bold** for one-word emphasis or a pivotal phrase, not every sentence. ALL CAPS for a beat, occasionally. |
| 71 | +- **Swedish context is welcome.** Umain, Avega, Aptitud, Salvation Army in Indonesia, School of Applied Technology — these are real parts of the story, not noise. |
| 72 | +- **Ends with usefulness.** A summary, a three-bullet takeaway, or a "be curious, be humble, be kind" kind of close. |
| 73 | + |
| 74 | +Do NOT write in a flat, AI-polished voice. Do NOT use emojis unless Marcus has used them in the piece already. Do NOT hedge everything — Marcus has opinions. |
| 75 | + |
| 76 | +## When editing posts |
| 77 | + |
| 78 | +- Preserve Marcus's voice — fix typos and clumsy phrasing, don't rewrite. If you're tempted to restructure, surface the suggestion instead of just doing it. |
| 79 | +- Never silently change meaning. If a claim seems off, ask. |
| 80 | +- Match the surrounding style for lists, headings, links. Look at the file, not generic Markdown norms. |
| 81 | +- Respect the pre-commit hooks: spellcheck and markdown-lint must pass. See [scripts/git-hooks/pre-commit](scripts/git-hooks/pre-commit). |
| 82 | + |
| 83 | +## Commands |
| 84 | + |
| 85 | +```bash |
| 86 | +# Build locally |
| 87 | +bash scripts/build_locally.sh |
| 88 | + |
| 89 | +# Spellcheck |
| 90 | +bash scripts/check-spelling.sh _posts |
| 91 | +bash scripts/check-spelling.sh _pages |
| 92 | + |
| 93 | +# Lint markdown (--fix auto-applies safe fixes) |
| 94 | +bash scripts/markdown_lint.sh _posts --fix |
| 95 | +bash scripts/markdown_lint.sh _pages --fix |
| 96 | + |
| 97 | +# Word clouds (run before committing when posts change significantly) |
| 98 | +bash scripts/create_wordcloud_all.sh |
| 99 | +``` |
| 100 | + |
| 101 | +The pre-commit hook in [scripts/git-hooks/pre-commit](scripts/git-hooks/pre-commit) runs spellcheck, lint, and regenerates wordcloud data. |
| 102 | + |
| 103 | +The spellchecker pulls custom words from `$HOME/Library/Application Support/Code/User/settings.json`. If a legitimate word is flagged, add it there, not to the post. |
| 104 | + |
| 105 | +## Memory / log |
| 106 | + |
| 107 | +See [memory.md](memory.md) for the rolling log of work done in this repo. Update it at the end of non-trivial sessions: what changed, why, anything a future session should know. |
| 108 | + |
| 109 | +## Don't |
| 110 | + |
| 111 | +- Don't create new top-level docs unless asked. Edit existing files. |
| 112 | +- Don't add "modernization" refactors to the Jekyll setup — it works, it's been working for years, leave it alone unless Marcus asks. |
| 113 | +- Don't reformat old posts en masse. They're a 20-year archive; respect the history. |
| 114 | +- Don't push or open PRs unless explicitly asked. This is Marcus's personal blog — he ships it. |
0 commit comments