CLAUDE.md — project context for LLM assistants

This file gives AI assistants the context needed to work in this repository without reading every file first. Read this before writing code, editing content, or generating blog posts.


What this repo is

A personal website and blog for Patrick Morgan, a freelance technical writer based in Richmond, VA. The site is at patrickwritesgood.com.

Tech stack: Jekyll (static site generator) · Minima theme · GitHub repo · Netlify hosting · Squarespace DNS · Formspree contact form

Do not change the tech stack, theme, or hosting setup unless explicitly asked.


Directory structure

_config.yml           # Site title, URL, permalink format, plugins
_drafts/              # Unpublished posts (never deployed)
  new-post-template.md  # Starter template — copy this for new posts
_includes/            # Reusable Liquid snippets (see below)
_posts/               # Published blog posts (YYYY-MM-DD-slug.md)
assets/
  images/             # All site images (use .webp)
  main.scss           # All custom styles (Minima overrides + components)
blog/
  index.html          # Blog listing page at /blog/
index.md              # Home / landing page
about.md
services.md
contact.md
faq.md
README.md             # Developer and content reference

Rules and constraints

  1. Never push to main directly. All changes go to a feature branch; Netlify deploys main to production.
  2. Never add images that are not .webp. Convert first if needed.
  3. Do not modify _config.yml or netlify.toml unless the task explicitly requires it.
  4. Do not modify Gemfile or Gemfile.lock unless adding a Jekyll plugin that was explicitly requested.
  5. Markdown is not processed inside Liquid tag attributes. Use plain text or inline HTML for body, left, right, etc. parameters.
  6. Permalinks are /blog/:slug/ (set in _config.yml). Do not change this.
  7. Keep CSS in assets/main.scss. Do not create additional stylesheets.

Available includes (quick reference)

Full documentation for each is in README.md. The table below is a fast lookup for which include to reach for.

Include Use it for
card.html Service offering or feature highlight with title, body, and optional SVG icon
figure.html Single image with optional caption and alignment
pullquote.html Pull a key sentence out of body text for visual emphasis
testimonial.html Client quote with name, title, and headshot
callout.html Tip, warning, note, or example box
cta.html Call-to-action button or inline link
gallery.html 2–4 images side by side
two-column.html Two blocks of content side by side (text + image, etc.)
bio-card.html Person introduction with photo, name, role, and bio

Generating a new blog post

Step 1 — name the file

_posts/YYYY-MM-DD-slug-here.md

Use today’s date. The slug should be lowercase, hyphen-separated, and descriptive (not a copy of the title). Example: 2026-03-16-why-plain-language-matters.md.

Step 2 — front matter

---
layout: post
title: "Title in Title Case"
date: YYYY-MM-DD
image: /assets/images/descriptive-name.webp
excerpt: "One or two sentences. Shown on the blog listing page."
---
  • image is displayed as a thumbnail on /blog/. If no image exists yet, use a placeholder path and note it needs a real image.
  • excerpt should be a punchy summary — not a repeat of the first sentence, but a reason to click.

Step 3 — post structure

Follow this general structure:

[Opening paragraph — the lede. Slightly larger font, styled by CSS. Hook the reader here.]

### Section heading

[Body. Short-to-medium paragraphs. One idea per paragraph.]

[Use includes for visual rhythm — a pullquote every 400-600 words, a figure or gallery where relevant.]

---

[Closing paragraph or reflection]

---

*[One-line sign-off with a link to /contact or a related post.]*

Use ### headings inside posts, not ##. ## is for major page sections. Posts are part of a page that already has ##-level context from the layout.


Patrick’s voice and writing style

Study _posts/2025-07-29-ryne-sandberg-taught-me-to-try.md as the primary example of how Patrick writes.

Voice characteristics:

  • Personal and specific. Anchored in real memories, real places, real people. Not abstract.
  • Connects the personal to the professional (or universal). A baseball memory becomes a reflection on effort and dignity at work. A sports figure’s death becomes a meditation on why we try.
  • Direct but not blunt. Sentences are complete and confident. He doesn’t hedge with “perhaps” or “it seems like.” He also doesn’t over-explain.
  • Emotionally honest without being sentimental. He describes crying on a sidewalk in Inwood. He doesn’t dress it up.
  • Parenthetical asides. He uses parentheticals for self-aware commentary, like an aside to the reader — (my childhood wasn't terrible; my recall was and continues to be). Use these sparingly.
  • Section headings that read like story beats, not topics. Examples: “Moment 1: Green and Cubbie Blue”, “Some Moments Come Too Soon”, “One Last Moment”. Headings should feel like chapter titles, not outline labels.
  • Professional topics include: technical writing, documentation, plain language, content strategy, AI and the writing profession, client communication.

Tone calibration:

  • Informal but intelligent — not academic, not bro-y
  • Dry humor is fine; puns are not his thing
  • He swears occasionally (mild; goddamn appears once in the Sandberg post)
  • Political when it matters to him — see the Postscript in the Sandberg post — but it’s always tethered to something personal, never a lecture

What to avoid:

  • Listicles with no connective tissue
  • “In conclusion” or similar transitions
  • Hollow motivational language (“unlock your potential”, “level up”)
  • Rhetorical questions as section intros
  • Bullet points in the prose body (callouts and postscripts are fine)

Using pullquotes

Pull quotes are Patrick’s primary visual tool for breaking up long posts. Use pullquote.html instead of native Markdown > blockquotes in posts.

For short quotes, pass directly:

{% include pullquote.html
   quote="Respect the game you play."
%}

For quotes longer than one sentence or quotes containing special characters (apostrophes, quotes), use a capture block:

{% capture my_quote %}"The reason I am here, they tell me, is that I played the game a certain way."{% endcapture %}
{% include pullquote.html quote=my_quote %}

Using figures and galleries

Images in posts almost always get a caption. Use figure.html instead of bare Markdown images.

{% include figure.html
   src="/assets/images/photo.webp"
   alt="Descriptive alt text"
   caption="Caption text. Can include HTML links."
%}

For multiple related images (event photos, before/after, etc.), use gallery.html:

{% include gallery.html
   img1="/assets/images/photo1.webp|Alt text|Optional caption"
   img2="/assets/images/photo2.webp|Alt text"
%}

Commit message convention

Write commit messages as imperative sentences. First line is a short summary (72 chars max). Be specific.

Add post: why plain language builds trust

Add post: [title]            # new blog post
Update post: [slug]          # edit existing post
Add [page]: [what changed]   # changes to a static page
Fix [component]: [what]      # bug or style fix