Shawn Mix

AGENTS.md — Shawn Mix Personal Site

Personal website for Shawn Mix — blog, digital garden (Obsidian notes), resume, and links hub. Built on a customized Jekyll Garden theme.

Commands

# Install dependencies
bundle install

# Run local dev server
export PATH="/opt/homebrew/opt/[email protected]/bin:$PATH"
bundle exec jekyll serve

# Build static site
bundle exec jekyll build

macOS ships with Ruby 2.6. Always use Homebrew Ruby 3.2 at /opt/homebrew/opt/[email protected]/bin/ for Jekyll 4.


Architecture

Single Layout Pattern

All pages share one layout: _layouts/Post.html. It branches using Liquid conditionals on page.permalink and page.content-type:

Condition Page type
permalink: / Homepage — renders pages/index.md via Content.html
permalink: /notes Notes index — search + feed
permalink: /blog Blog index — post listing
content-type: notes Individual note — back button + backlinks
content-type: post Blog post — back button + date + read time
content-type: static Static page (about, resume, etc.)

Key Files

File Purpose
_config.yml Site config, feature toggles; menu is empty (nav is via landing page cards)
_layouts/Post.html Universal layout; theme attribute set here
_includes/Nav.html Top nav — square logo left, theme toggle right; all theme JS lives here
_includes/Footer.html Empty spacer — no copyright, no credits
_includes/Feed.html Notes feed list (feed-container wrapper)
_includes/Backlinks.html Backlinks grid on note/post pages
assets/css/style.css All styles — plain CSS, no Sass
pages/index.md Landing page — name, bio, 2×2 card grid
pages/about.md About page
pages/resume.md Resume (placeholder, specialized layout planned)
pages/notes.md Notes index
pages/blog.md Blog index
_notes/ Digital garden notes (Obsidian-compatible, [[wiki links]] supported)
_posts/ Blog posts — filename must be YYYY-MM-DD-title.md

Collections


CSS Variable System

All values live in :root (light) and [data-theme="dark"] (dark) in style.css. Never use hardcoded values — always reference or add a variable.

Spacing

Variable Value
--space-xs 0.4rem
--space-sm 0.8rem
--space-md 1.2rem
--space-lg 2rem
--space-xl 3rem
--back-button-offset 8rem

Type Scale

Variable Value Usage
--scale-xs 0.8rem Small labels
--scale-sm 0.933rem Back button, captions
--scale-meta 0.875rem Post metadata (date, read time)
--scale-base 1rem Body text
--scale-lg 1.2rem Subheadings

Font Weights

Variable Value
--weight-light 300
--weight-medium 400
--weight-bold 600

Font: Inter (Google Fonts), loaded at weights 300/400/600. Loaded via @import in style.css only — no separate <link> tag in the layout.

Line Heights

Variable Value Usage
--line-height 1.5 Default — headings, code, search results
--line-height-relaxed 1.6 Blockquotes, list items
--line-height-loose 1.7 Body paragraphs

Colors — Catppuccin

Variable Dark (Mocha) Light (Latte)
--bg #181825 Mantle #eff1f5 Base
--bg2 #1e1e2e Base #e6e9ef Mantle
--text #cdd6f4 Text #4c4f69 Text
--title #ffffff White #1e1e2e Dark
--brand #45475a Surface 1 #9ca0b0 Surface 1
--border #313244 Surface 0 #ccd0da Surface 0

Accent hover color (not a variable — used inline): rgba(137, 180, 250, 0.22) — Catppuccin Blue at low opacity.


Design Conventions

Hover Behavior

Element Hover effect
Landing page cards rgba(137, 180, 250, 0.22) blue tint + border stays visible
Backlinks grid items Same blue tint
Notes/blog feed list items None — no highlight
Back button Opacity 0.7 → 1

CSS ::after on a[href^="http"] — theme-aware SVG stroke (#4c4f69 light / #cdd6f4 dark). Suppressed on: nav, footer, search, feed wrappers. On card grid: suppressed on <a> wrapper, applied to h4::after so the arrow appears beside the title, not after the description.

Back Buttons

Blog Post Metadata

Rendered beneath <h1> on post pages:

 &middot;  min read

Adding Content

New blog post

File: _posts/YYYY-MM-DD-title.md

---
title: "Post Title"
date: YYYY-MM-DD
feed: show
---

New note (digital garden)

File: _notes/Public/Note Title.md

---
title: "Note Title"
feed: show
date: YYYY-MM-DD
---

New static page

File: pages/slug.md

---
title: "Page Title"
layout: Post
content-type: "static"
permalink: /slug
---

Notes Publishing Pipeline

Notes in _notes/Public/ are not edited directly. They are synced automatically from the lifeOS Obsidian vault (iCloud) via a Python script. The Obsidian vault is the single source of truth.

To publish a note from Obsidian: Add publish: true to the note’s frontmatter. The sync runs every 20 minutes automatically, or can be triggered on-demand via QuickAdd inside Obsidian.

To un-publish a note: Set publish: false. The next sync will delete the file from this repo.

Full pipeline documentation: SOP - Notes Publishing Pipeline in the Obsidian vault at 3 Resources/SOPs/.

Sync script (source of truth): lifeOS/3 Resources/scripts/sync_to_jekyll.py

Do not manually edit files in _notes/Public/ — changes will be overwritten on the next sync.

Sync Wrapper (for re-creation)

If the launchd wrapper at ~/scripts/run-jekyll-sync.sh is lost, recreate it with:

#!/usr/bin/env bash
export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:$PATH"

SYNC_SCRIPT="/Users/shawnmix/Library/Mobile Documents/iCloud~md~obsidian/Documents/lifeOS/3 Resources/scripts/sync_to_jekyll.py"

if [[ ! -f "$SYNC_SCRIPT" ]]; then
    brctl download "$SYNC_SCRIPT" 2>/dev/null || true
    sleep 3
    if [[ ! -f "$SYNC_SCRIPT" ]]; then
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: sync_to_jekyll.py not found" >&2
        exit 1
    fi
fi

exec python3 "$SYNC_SCRIPT" --scheduled "$@"

Then: chmod +x ~/scripts/run-jekyll-sync.sh && launchctl load ~/Library/LaunchAgents/com.shawnmix.jekyll-sync.plist


Future Work


References