Agent Guidelines for Lindsay Brunner Website
This document provides context for AI assistants working on this Hugo static site project.
Project Overview
This is a personal website built with Hugo (v0.149.2+), deployed on Netlify. The site showcases thought leadership content and recipes with a custom dark theme design.
Critical Protected Elements ⚠️
NEVER modify these without explicit user permission:
-
Hero H1 Gradient (
layouts/index.html):- Must use
background-size: 80% 100%(not 100%) - Gradient:
linear-gradient(135deg, var(--color-red) 0%, var(--color-pink) 50%, var(--color-yellow) 100%) - Changing this breaks the visual match with the header logo
- Must use
-
Typography:
h1and.site-logomust usefont-family: 'Inter'(not Space Grotesk)- Required for gradient rendering consistency
-
Button Hover States:
- White text must be explicitly maintained for readability
- Don't change hover text colors on gradient buttons
Project Structure
content/
├── thoughts/ # Thought leadership posts
│ ├── _index.md # Section index
│ └── *.md # Individual posts
├── recipes/ # Recipe posts
│ ├── _index.md # Section index
│ └── recipe-*.md # Individual recipes
├── about/
│ └── index.md # About page
└── _index.md # Homepage content
layouts/
├── index.html # Homepage template
├── 404.html # Error page
├── _default/ # Default templates
├── thoughts/ # Thoughts section layouts
├── recipes/ # Recipes section layouts
└── partials/ # Reusable components
static/
├── css/ # Stylesheets (main.css, custom.css)
├── favicons/ # All favicon files
├── images/
│ └── social/ # Open Graph images
├── _headers # Netlify headers
└── _redirects # Netlify redirects
Writing Style and Voice
IMPORTANT: When creating or editing content, always follow the guidelines in CONTENT_STYLE_GUIDE.md. This document defines:
- Tone and voice (wry, plainspoken, pragmatic)
- Sentence structure and rhythm
- Style of argumentation
- Formatting rules (no em dashes, title case H1s, sentence case other headers)
- Content clarity principles
- How to write in Lindsay's voice
Key rules:
- ❌ Absolutely no em dashes (use parentheses, commas, or break sentences)
- Title case for H1s, sentence case for all other headers
- Avoid corporate/LinkedIn sludge
- Write for builders and practitioners as peers
- Lead with lived experience, not abstractions
Content Creation Patterns
Thoughts Posts
📋 For complete thoughts guidelines, see docs/thoughts-template.md
The template includes:
- Complete front matter template with all required and optional fields
- Content structure guidelines (flexible, unlike recipes)
- Formatting rules (headers, links, emphasis, etc.)
- OG image workflow (manual creation)
- Scheduling instructions
- Complete examples
Quick reference:
Required front matter fields:
title(string)date(YYYY-MM-DD format)description(string)subtitle(string)draft(true/false)
Optional fields:
slug(string)og_imageorsocial_image(path to image in/images/social/)
Permalink pattern: /thoughts/:year-:month-:day/:slug/
File naming for drafts:
- Prefix draft thoughts files with
draft-for easy identification (e.g.,draft-my-post.md) - The
slugfield in front matter determines the URL, so "draft" won't appear in production URLs - This naming convention only applies to thoughts posts, not recipes
Example:
---
title: "My Thought Title"
date: 2025-01-15
description: "A compelling description"
subtitle: "Brief subtitle for homepage"
draft: false
slug: "my-thought-title" # This determines the URL, not the filename
social_image: "/images/social/my-image.png"
---
Recipe Posts
📋 For complete recipe guidelines, see docs/recipe-template.md
The template includes:
- Complete front matter template with all required and optional fields
- Content structure guidelines (snapshot, ingredients, method, notes)
- Formatting rules (temperatures, measurements, section separators)
- OG image workflow
- Scheduling instructions
- Complete examples
Quick reference:
Required front matter fields:
title,date,description,subtitle,draft(same as thoughts)prepTime(ISO 8601 duration, e.g., "PT30M")cookTime(ISO 8601 duration, e.g., "PT45M")totalTime(ISO 8601 duration, e.g., "PT75M")recipeYield(string, e.g., "6-8 servings")recipeCategory(string, e.g., "Main Course")recipeCuisine(string, e.g., "Japanese-American")dietary(optional array) — see Dietary labels below. Used for filter chips and title icons.recipeIngredient(array of strings)recipeInstructions(array of strings)
Permalink pattern: /recipes/:year-:month-:day/:slug/
File naming: Use recipe- prefix (e.g., recipe-bachan-pulled-pork.md)
Section separators: Use --- (three dashes) as horizontal rules to separate major sections within recipe content. Do not use ⸻ (triple em dash) or other separator characters.
Dietary labels (optional): Labels apply to the base recipe only (main Ingredients and Method). Use exactly these values (lowercase, hyphenated). If a note or variation would change a classification, explicitly call that out in the note.
- dairy-free — Base recipe has no milk, cream, butter, cheese, or other dairy.
- vegetarian — Base recipe has no meat, poultry, or fish. Eggs and dairy allowed.
- vegan — Base recipe has no animal products (no meat, fish, eggs, dairy, honey, etc.).
- gluten-free — Base recipe has no wheat, barley, rye, or ingredients derived from them.
Temperature formatting:
- Always use degree symbols:
°Fand°C - Standard format:
200°F (93°C)(Fahrenheit first, Celsius in parentheses) - For ranges:
160–165°F (71–74°C) - Do not use slash format (
350°F / 175°C) — use parentheses instead
Volume and measurement formatting:
- Always capitalize abbreviations:
Tbsp,Tsp,Cup,Cups(nottbsp,tsp,cup,cups) - Acceptable abbreviations:
Tbsp/Tbsp(tablespoon) — always abbreviateTsp/Tsp(teaspoon) — always abbreviatecup/cups— can abbreviate in lists, spell out in narrative textoz(ounce) — always abbreviatelb(pound) — always abbreviateg(gram) — always abbreviateml(milliliter) — always abbreviatein(inch) — can abbreviate in measurements like1½-inch chunks
- Always spell out:
minutes/minute(notmin)hours/hour(nothr)seconds/second(notsec)
- Metric conversions: Optional but helpful. Include when it adds clarity:
1 cup (240 ml),2 Tbsp (30 g) - Fractions: Use Unicode fractions when available:
½,⅓,¼,¾; otherwise use1/2,1/3, etc.
Testing
Always run tests after making changes:
npm run build # Build the site first
npm run test:content # Run content validation tests
npm test # Run all tests (HTML, links, content, spell check, OG images, scheduling, search JSON, recipe template)
Available test commands:
npm run test:content- Content validation testsnpm run test:html- HTML validationnpm run test:links- Broken link detection (starts dev server, waits for ready, runs check, stops server)npm run test:spell- Spell check modified content files (git diff)npm run test:spell:all- Spell check all content filesnpm run test:og-images- OG image generation validationnpm run test:schedule- Scheduled posts workflow validationnpm run test:search-json- Recipe search JSON index validationnpm run test:recipe-template- Recipe template structure validationnpm test- Run all tests (includes pretest build step)
Test coverage includes:
- Front matter validation (thoughts & recipes)
- Dietary labels: only
dairy-free,vegetarian,vegan,gluten-freeallowed; no duplicates; labels apply to base recipe only (see docs) - No duplicate recipe page content (identical body in multiple files)
- Social image existence
- Static asset checks (CSS, favicons, default images)
- RSS feed structure
- Sitemap validation
- Homepage content structure
- About page validation
- 404 page validation
- Permalink structure
- Spell checking (content files)
- OG image generation and structure
- Scheduled posts workflow
- Recipe search JSON index structure and validity
- Recipe template compliance
- Recipe print functionality (print buttons, stylesheet, email links)
Configuration Details
Key config settings (config.toml):
- Site title: "LB"
- Base URL:
https://lindsaybrunner.com - Markup:
unsafe = true(allows raw HTML in content) - Default social image:
/images/social/default-og.png - Recent posts number: 4
Permalink patterns:
- Thoughts:
/thoughts/:year-:month-:day/:slug/ - Recipes:
/recipes/:year-:month-:day/:slug/
Output formats:
- HTML (default)
- RSS feed (
/index.xml) - RecipeSearch JSON (
/recipes/index.json) - JSON index for recipe search functionality
Brand Guidelines
See BRAND.md for complete brand guidelines. Key points:
Colors:
- Gradient: Red (#ff0037) → Pink (#ff1b8d) → Yellow (#ffdd00)
- Primary brand: Pink (#ff1b8d)
- Dark theme: Black background (#000000) with dark surfaces (#0f0f0f)
Typography:
- Primary: Space Grotesk (body, navigation, headers h2-h6)
- Protected: Inter (h1 and logo only)
- Mono: SF Mono / system monospace
Common Tasks
Adding a New Thought Post
- Create file in
content/thoughts/(lowercase, hyphens)- For drafts, use
draft-prefix:draft-my-post.md(helps with organization) - The
slugfield in front matter determines the URL, so "draft" won't appear in production URLs
- For drafts, use
- Use the complete template from
docs/thoughts-template.md - Add required front matter (see template for complete details)
- Optionally create and add social image to
static/images/social/(manual creation, unlike recipes) - Reference image in front matter:
social_image: "/images/social/my-image.png" - For diagram images in thoughts posts: If adding PNG diagram images (e.g., flowcharts, system diagrams) to thoughts post content, place them in
static/images/and ensure their backgrounds match the site's true black (#000000). Runnode scripts/fix-diagram-backgrounds.jsto automatically fix background colors. Add new diagram filenames to thediagramFilesarray in the script before running. Note: This script is specifically for diagrams in thoughts posts, not for other types of images or other page types. - Run
npm run build && npm run test:content
To schedule for future publication:
- Set
draft: trueand a futuredatein front matter - The GitHub Actions workflow will automatically publish when the date arrives
- Test locally with
npm run schedule-poststo see what would be published
Adding a New Recipe
- Create file
content/recipes/recipe-*.md - Use the complete template from
docs/recipe-template.md - Follow the content structure (description, snapshot, ingredients, method, notes)
- Generate and review OG image:
npm run generate:og-images- This generates SVG files in
static/images/social/working-files/for editing - After editing the SVG, convert to PNG:
npm run generate:png -- static/images/social/working-files/recipe-xxx-og.svg - The PNG will be saved in
static/images/social/for use as the OG image
- This generates SVG files in
- Add
social_imageto front matter:social_image: "/images/social/recipe-xxx-og.png" - Run
npm run build && npm run test:content
Print functionality:
- Recipe pages automatically include print icon button (top-right) and print/email buttons (bottom)
- Print stylesheet is automatically applied via
@media printrules instatic/css/custom.css - Print and email actions are tracked in Plausible Analytics
- No additional configuration needed - works out of the box for all recipes
To schedule for future publication:
- Set
draft: trueand a futuredatein front matter - Important: Scheduled recipes must have
social_imageset before the publish date, or they will be skipped - The GitHub Actions workflow will automatically publish when the date arrives
- Test locally with
npm run schedule-poststo see what would be published
Modifying Styles
- Main styles:
static/css/main.css - Custom overrides:
static/css/custom.css- Includes print stylesheet (
@media print) for recipe pages - Print styles hide navigation, use serif fonts, optimize for paper
- Includes print stylesheet (
- Use CSS custom properties from brand system
- Test responsive breakpoints: 768px, 480px
Updating Homepage
- Edit
content/_index.mdfor content - Edit
layouts/index.htmlfor structure - Recent Thoughts section shows 3 most recent (or placeholders if < 3)
Important Notes
- Drafts: Set
draft: trueto hide from production - Draft file naming (thoughts only): Prefix draft thoughts files with
draft-for easy identification (e.g.,draft-my-post.md). Theslugfield in front matter determines the URL, so "draft" won't appear in production URLs. - Dates: Use YYYY-MM-DD format (Hugo sorts by date)
- Social Images: Place in
static/images/social/, reference with leading slash - Raw HTML: Allowed in content (config has
unsafe = true) - Build: Always run
npm run buildbefore testing - Deployment: Automatic via Netlify on push to master
- Scheduled Posts: Posts with
draft: trueand future dates will auto-publish via GitHub Actions (runs twice daily at 13:00 and 14:00 UTC to cover both PDT and PST). See README.md for details. - Recipe Search JSON: A JSON index is automatically generated at
/recipes/index.jsonfor client-side recipe search functionality. The index includes recipe metadata and is validated by tests. - Recipe Print Functionality: Recipe pages include print icon button (top-right) and print/email buttons (bottom). Print stylesheet automatically optimizes layout for printing. Print and email actions are tracked in Plausible Analytics. See README.md for details.
- Spell Checking: Use
npm run test:spellto check modified content files, ornpm run test:spell:allto check all content files. Add valid words tocspell.jsonif needed. - Hugo Version Checking: Periodically check Hugo version and security status with
npm run check:hugo. This checks for known CVEs and available updates. Recommended: check monthly or when security advisories are published. - Dependency Security Checking: Run
npm run check:dependenciesto check all npm packages, Node.js version, and GitHub Actions for security vulnerabilities and updates. This runs automatically via GitHub Actions monthly and creates issues if problems are found.
References
- README.md: Setup, scripts, content management guide, scheduling posts
- docs/thoughts-template.md: Complete thoughts template with front matter, structure, and formatting guidelines
- docs/recipe-template.md: Complete recipe template with front matter, structure, and formatting guidelines
- docs/recipe-snapshot-template.md: Snapshot section format and field definitions
- BRAND.md: Complete brand guidelines and protected elements
- CONTENT_STYLE_GUIDE.md: Writing principles, tone, voice, and style guidelines
- config.toml: Hugo configuration
- tests/content-checks.js: Main test orchestrator (modular structure in
tests/content-checks/directory) - tests/spell-check.js: Spell checking script for content files
- tests/og-image-generation.test.js: OG image generation validation
- tests/schedule-posts.test.js: Scheduled posts workflow validation
- tests/recipe-search-json.test.js: Recipe search JSON index validation
- tests/recipe-template.test.js: Recipe template structure validation
- tests/dietary-labels.test.js: Dietary label validation (allowed values only; base recipe only)
- scripts/schedule-posts.js: Auto-publish scheduled posts script
- scripts/generate-og-images.js: Generate OG images for recipes
- scripts/generate-png-from-svg.js: Convert SVG to PNG for social media compatibility
- scripts/fix-diagram-backgrounds.js: Fix diagram image background colors to match site black (#000000). Processes PNG files listed in the
diagramFilesarray, replacing dark pixels with pure black to ensure seamless integration with the dark theme. Note: Currently only relevant for diagrams placed in thoughts posts, not other types of images or other page types. - scripts/check-hugo-version.js: Check Hugo version, security status, and available updates
- scripts/check-dependencies.js: Check all dependencies (npm packages, Node.js, GitHub Actions) for security issues and updates
- .github/workflows/security-check.yml: Monthly automated security and dependency check workflow
- .github/workflows/schedule-posts.yml: GitHub Actions workflow for scheduled publishing
- layouts/recipes/list.json: Template for recipe search JSON index
- layouts/recipes/single.html: Recipe page template with print functionality (print icon, print/email buttons)
- static/css/custom.css: Print stylesheet (
@media print) for optimized recipe printing
When in Doubt
- Check existing content files for patterns
- Run tests to verify changes
- Check BRAND.md for design constraints
- Check CONTENT_STYLE_GUIDE.md for writing style and voice guidelines
- Preserve existing conventions unless explicitly asked to change them