Theme Documentation
Theme Documentation
A comprehensive guide to understanding and customizing the mrogers.london Jekyll theme.
Overview
This is a custom Jekyll theme built specifically for GitHub Pages deployment. The theme features a modular SCSS architecture designed for maintainability and easy customization.
Design Philosophy:
- Warm, reading-focused aesthetic with a carefully chosen color palette
- Modular SCSS structure for clean separation of concerns
- Responsive design that prioritizes content readability
Visual Design:
- Primary color: Terracotta (#C45533)
- Secondary color: Sage (#7A9E7E)
- Accent color: Warm gold (#D4A853)
- Background: Warm cream (#FAF8F5)
- Typography: Newsreader (serif) for body text, Rethink Sans for UI elements
Architecture
Directory Structure
mrogers-london/
├── _sass/ # Modular SCSS partials
│ ├── _variables.scss # Design tokens (colors, fonts, spacing)
│ ├── _base.scss # HTML element resets and defaults
│ ├── _typography.scss # Font styles and headings
│ ├── _layout.scss # Page structure, header, footer
│ └── _components.scss # Reusable UI components
├── assets/css/
│ └── main.scss # Main entry point (imports partials)
├── _layouts/ # Page templates
│ ├── default.html # Base template
│ ├── page.html # Static pages
│ ├── post.html # Blog posts
│ └── home.html # Homepage
├── _includes/ # Reusable components
│ ├── head.html # HTML head section
│ ├── header.html # Site header
│ ├── footer.html # Site footer
│ └── post-meta.html # Post metadata
└── assets/images/ # Image assets
SCSS Structure
Modular System
Each SCSS file has a single responsibility, making the codebase easier to maintain and customize. The files are imported in a specific order in assets/css/main.scss.
File Breakdown
_variables.scss - Design Tokens
- Color palette:
$color-primary,$color-secondary,$color-tertiary,$color-background,$color-text,$color-border,$color-muted - Typography:
$font-serif(Newsreader),$font-sans(Rethink Sans),$font-mono - Spacing scale:
$spacing-xs,$spacing-sm,$spacing-md,$spacing-lg,$spacing-xl,$spacing-2xl - Font sizes and weights
- Breakpoints for responsive design
- Content width constraints
_base.scss - Reset and Base Styles
- Box-sizing reset
- Margin resets for consistency
- HTML and body base styles
- Image defaults
- Link styles
- List styling
- Horizontal rules
- Text selection color
_typography.scss - Text Styles
- Heading styles (h1-h6)
- Font sizes and weights
- Line heights
- Text utilities
_layout.scss - Page Structure
- Page content wrapper
- Site header and navigation
- Site footer and social links
- Homepage-specific styles
- Post page layout
- Static page layout
- Responsive container widths
_components.scss - Reusable Components
- Avatar styles
- Type badges (category pills)
- Post list items
- Post metadata
- Newsletter signup
- Other UI components
Import Chain
The assets/css/main.scss file imports all partials in the correct order:
- Google Fonts (external)
- Variables (must be first for use in other files)
- Base styles
- Typography
- Layout
- Components
- Additional custom styles
Customization Guide
Changing Colors
Edit the color variables in _sass/_variables.scss:
// Example: Change primary color from terracotta to blue
$color-primary: #3B82F6; // Change from #C45533
All links, highlights, and accent colors will update automatically throughout the site.
Color Variables:
$color-background- Page background color$color-text- Main text color$color-primary- Links and highlights$color-secondary- Secondary accent (currently sage)$color-tertiary- Tertiary accent (currently warm gold)$color-border- Borders and dividers$color-muted- Muted/secondary text
Modifying Fonts
Step 1: Update the Google Fonts import in assets/css/main.scss:
@import url('https://fonts.googleapis.com/css2?family=Your-Font:wght@400;600&display=swap');
Step 2: Update font variables in _sass/_variables.scss:
$font-serif: 'Your-Serif-Font', Georgia, serif;
$font-sans: 'Your-Sans-Font', -apple-system, sans-serif;
$font-mono: 'Your-Mono-Font', Monaco, monospace;
Current Fonts:
- Serif (body text): Newsreader
- Sans-serif (UI): Rethink Sans
- Monospace (code): SF Mono fallback chain
Adjusting Spacing
Edit the spacing scale in _sass/_variables.scss:
$spacing-xs: 0.5rem; // 8px
$spacing-sm: 0.75rem; // 12px
$spacing-md: 1rem; // 16px
$spacing-lg: 1.5rem; // 24px
$spacing-xl: 2rem; // 32px
$spacing-2xl: 3rem; // 48px
Spacing variables are used throughout the theme for consistent vertical rhythm and component spacing.
Changing Layout Width
Adjust content width constraints in _sass/_variables.scss:
$content-max-width: 680px; // Main content column width
$page-max-width: 1200px; // Full page width
Adding New Components
Add new components to _sass/_components.scss following the existing patterns:
.my-component {
padding: $spacing-md;
background-color: $color-background;
border: 1px solid $color-border;
border-radius: 4px;
&:hover {
background-color: rgba($color-primary, 0.05);
}
}
Best Practices:
- Use variables for colors and spacing (never hardcode values)
- Follow the existing naming conventions
- Keep selectors flat and simple
- Use BEM-style naming for clarity
- Add comments for complex styles
Responsive Design
The theme uses responsive breakpoints defined in _variables.scss:
$breakpoint-sm: 576px;
$breakpoint-md: 768px;
$breakpoint-lg: 1024px;
Use media queries with these breakpoints:
.my-element {
font-size: 1rem;
@media (min-width: $breakpoint-md) {
font-size: 1.125rem;
}
}
Layout System
Layout Hierarchy
The theme uses a hierarchical layout system:
default.html (base)
├── page.html (static pages)
├── post.html (blog posts)
└── home.html (homepage)
When to Use Each Layout
default.html - Base Template
- Contains the HTML skeleton
- Includes header, footer, and content wrapper
- Used as the foundation for all other layouts
- Not typically assigned directly to pages
page.html - Static Pages
- Extends
default.html - Used for: About page, Archives, etc.
- Simple content container without post metadata
post.html - Blog Posts
- Extends
default.html - Includes post metadata (date, category, reading time)
- Adds post-specific styling and structure
- Automatically assigned to files in
_posts/
home.html - Homepage
- Custom layout with hero section
- Displays avatar, title, tagline
- Lists recent blog posts
- Only used for
index.md
Customizing Layouts
Layouts are found in _layouts/ and can be edited directly. They use Jekyll’s Liquid templating language.
Common Liquid Variables:
- `<article class="page">
Beehiiv Integration Setup Guide
Beehiiv Integration Setup Guide
This document outlines all the work required to complete the Beehiiv cross-posting integration.
Current Status
✅ COMPLETED:
- Beehiiv subscribe form integrated on GitHub Pages site
- RSS feed removed from site
- Sync script created (
scripts/sync_to_beehiiv.py) - GitHub Actions workflow created (
.github/workflows/beehiiv-sync.yml) - Dependencies file created (
scripts/requirements.txt) - Documentation created (
scripts/README.md)
⏳ PENDING: API access and configuration (see below)
Required Work
1. Request Beehiiv Enterprise API Access
Status: ⏳ NOT STARTED
Action Required:
- Log into your Beehiiv dashboard
- Navigate to Help page or click the Chatbot Assistant
- Send message requesting Enterprise API access:
Hi, I'd like to request access to the Beehiiv Send API / Create Post endpoint. I want to programmatically cross-post content from my Jekyll blog to Beehiiv. - Wait for response from Beehiiv support
- Once approved, obtain:
- API key
- Publication ID
Resources:
Expected Timeline: Days to weeks (depends on Beehiiv support response time)
Blockers: Cannot proceed with remaining steps until API access is granted
2. Verify API Endpoint and Payload Structure
Status: ⏳ BLOCKED (waiting for API access)
Action Required:
Once you have API access, verify these details in the sync script:
File: scripts/sync_to_beehiiv.py
Search for # TODO: comments and verify:
a) API Base URL (Line ~36)
# TODO: Verify API endpoint URL with Beehiiv documentation once you have API access
API_BASE_URL = 'https://api.beehiiv.com/v2'
- Check: Is
https://api.beehiiv.com/v2the correct base URL? - Reference: Beehiiv API documentation
b) Request Payload Field Names (Lines ~212-237)
# TODO: Verify these field names match actual Beehiiv API specification
payload = {
"title": post_data['title'],
"status": "confirmed",
"platform": "both",
"content": {
"html": html_content
}
}
Verify these field names are correct:
title- Post titlestatus- Publication status (“confirmed” for immediate publish)platform- Where to publish (“both” for email + web)content.html- HTML content structuresubtitle- Excerpt/subtitle field namecontent_tags- Tags field nameweb_url_override- Canonical URL field namesend_at- Publish date field name and format
c) Response Structure (Line ~250)
# TODO: Verify response structure with actual API - adjust path to post ID if needed
post_id = result.get('id') or result.get('data', {}).get('id')
- Check: Where is the post ID in the API response?
- Adjust code if the post ID is at a different path
d) Date Format (Line ~236)
# TODO: Verify date format expected by Beehiiv (ISO 8601 assumed)
payload["send_at"] = post_data['date']
- Check: Does Beehiiv expect ISO 8601 format? (e.g., “2025-04-13T10:00:00Z”)
- Adjust if different format needed
Testing Method:
- Make a test API call with
curlor Postman - Verify request/response structure
- Update script if needed
- Run local test (see Testing section below)
3. Configure GitHub Secrets
Status: ⏳ BLOCKED (waiting for API access)
Action Required:
- Go to your GitHub repository:
https://github.com/m-01101101/mrogers-london - Navigate to: Settings → Secrets and variables → Actions
- Click New repository secret
- Add two secrets:
Secret 1: BEEHIIV_API_KEY
- Name:
BEEHIIV_API_KEY - Value: Your API key from Beehiiv (obtained in step 1)
Secret 2: BEEHIIV_PUBLICATION_ID
- Name:
BEEHIIV_PUBLICATION_ID - Value: Your publication ID from Beehiiv
How to find Publication ID:
- Check Beehiiv dashboard URL (may be in the URL)
- Check API documentation
- Contact Beehiiv support if unclear
Documentation:
4. Local Testing (Before Deployment)
Status: ⏳ BLOCKED (waiting for API access and secrets)
Action Required:
Test the sync script locally before deploying to GitHub Actions:
# Navigate to repo directory
cd /Users/michael/m-01101101/mrogers-london
# Set environment variables
export BEEHIIV_API_KEY="your_actual_api_key_here"
export BEEHIIV_PUBLICATION_ID="your_actual_publication_id_here"
# Install dependencies
pip install -r scripts/requirements.txt
# Run sync script
python scripts/sync_to_beehiiv.py
Expected Outcome:
- Script finds 5 posts in
_posts/ - Each post is converted to HTML
- Posts are created on Beehiiv via API
- State file
.beehiiv_sync_state.jsonis created - No errors in output
If errors occur:
- Check API endpoint URL
- Verify payload field names
- Check response parsing logic
- Review error messages for hints
- Update script as needed
Validation:
- Script runs without errors
- 5 posts created on Beehiiv
- Posts have correct titles, dates, content
- Images load correctly (absolute URLs to mrogers.london)
- State file created with all posts tracked
5. Initial Backfill via GitHub Actions
Status: ⏳ BLOCKED (waiting for local testing to pass)
Action Required:
Once local testing succeeds, trigger the GitHub Actions workflow:
Method 1: Manual Trigger
- Go to GitHub repo → Actions tab
- Select “Sync to Beehiiv” workflow
- Click “Run workflow”
- Select branch:
main - Click “Run workflow” button
Method 2: Automatic Trigger
- Make any commit to
_posts/directory - Push to main branch
- Workflow triggers automatically
Validation:
- Workflow runs successfully (green checkmark)
- No errors in workflow logs
- All 5 posts appear on Beehiiv
- State file (
.beehiiv_sync_state.json) committed to repo - State file contains all 5 posts
If workflow fails:
- Check workflow logs in GitHub Actions
- Verify GitHub Secrets are set correctly
- Check for API errors in logs
- Debug and re-run
6. Enable “Remove Indexing” on Beehiiv
Status: ⏳ BLOCKED (waiting for successful backfill)
Action Required:
After posts are successfully syncing to Beehiiv:
- Log into Beehiiv dashboard
- Navigate to: Settings → Publication Settings
- Find setting: “Remove Indexing” or “Disable Indexing”
- Toggle it ON
Why: This prevents Google from indexing your Beehiiv site, avoiding duplicate content SEO issues. Your primary site (mrogers.london) remains the SEO-indexed version.
Important: Only do this AFTER you verify posts are syncing correctly. If you enable this too early, you won’t be able to check if posts appear on Beehiiv web.
Validation:
- Setting enabled in Beehiiv
- Beehiiv posts still accessible to subscribers (not publicly indexed)
- mrogers.london remains Google-indexed
Reference:
7. Test End-to-End Workflow
Status: ⏳ BLOCKED (waiting for all above steps)
Action Required:
Create a test post to verify the full workflow:
# Create a test post
cat > _posts/2025-12-28-test-post.md <<'EOF'
---
title: "Test Post - Delete Me"
date: 2025-12-28
type: essay
excerpt: "This is a test post to verify Beehiiv integration."
tags: [test]
---
This is a test post to verify that:
- Markdown converts to HTML
- Images work correctly: 
- Cross-posting works automatically
You can delete this post after verification.
EOF
# Commit and push
git add _posts/2025-12-28-test-post.md
git commit -m "Test: Beehiiv integration"
git push origin main
Expected Behavior:
- GitHub Actions workflow triggers automatically
- Script detects new post
- Post created on Beehiiv (web + email)
- State file updated and committed
- Post appears on both mrogers.london and Beehiiv
Validation Checklist:
- Post appears on mrogers.london
- Post appears on Beehiiv web
- Email sent to subscribers (check your inbox)
- Images load correctly in Beehiiv
- Canonical URL links back to mrogers.london
- State file updated in repo
- Workflow completed successfully (green checkmark)
Clean Up: After successful test, delete the test post:
git rm _posts/2025-12-28-test-post.md
git commit -m "Remove test post"
git push origin main
Quick Reference: All TODO Items in Code
Search for # TODO: in these files:
scripts/sync_to_beehiiv.py
- Line ~27: Set
BEEHIIV_API_KEYandBEEHIIV_PUBLICATION_IDin GitHub Secrets - Line ~35: Verify API base URL
- Line ~212: Verify request payload field names
- Line ~224: Verify optional field names (subtitle, tags, canonical URL)
- Line ~236: Verify date format
- Line ~250: Verify response structure (post ID location)
Troubleshooting
API Access Issues
Problem: Beehiiv hasn’t responded to API access request
Solution:
- Follow up with support after 3-5 business days
- Check spam folder for email response
- Try reaching out via different channel (email vs. chat)
Authentication Errors
Problem: Authentication failed. Check BEEHIIV_API_KEY
Solutions:
- Verify API key is correctly copied (no extra spaces)
- Check GitHub Secret name matches exactly:
BEEHIIV_API_KEY - Confirm you have Enterprise API access (not just regular account)
Field Name Errors
Problem: Validation error or Unknown field from API
Solutions:
- Review Beehiiv API documentation for correct field names
- Update payload structure in
sync_to_beehiiv.py - Test with minimal payload first, then add optional fields
Posts Not Appearing
Problem: Script runs without errors but posts don’t appear on Beehiiv
Possible Causes:
- Posts created as drafts instead of published (check
statusfield) - Posts scheduled for future date (check
send_atfield) - Posts on Beehiiv but not visible due to permissions
Solutions:
- Check Beehiiv dashboard for draft posts
- Verify
status: "confirmed"in payload - Check
send_atis not in the future
Timeline Estimate
| Task | Time Required | Depends On |
|---|---|---|
| 1. Request API access | 1 hour work, days/weeks wait | - |
| 2. Verify API details | 1-2 hours | Task 1 |
| 3. Configure GitHub Secrets | 10 minutes | Task 1 |
| 4. Local testing | 30-60 minutes | Tasks 2, 3 |
| 5. Initial backfill | 15 minutes | Task 4 |
| 6. Enable “Remove Indexing” | 5 minutes | Task 5 |
| 7. End-to-end testing | 30 minutes | Tasks 1-6 |
Total Active Work: 3-5 hours Total Calendar Time: Days to weeks (waiting for API access)
Support Resources
Beehiiv Documentation:
- API Getting Started: https://developers.beehiiv.com/welcome/getting-started
- Create Post: https://developers.beehiiv.com/api-reference/posts/create
- Send API Guide: https://beehiivhelp.zendesk.com/hc/en-us/articles/36759164012439
GitHub Documentation:
- Actions: https://docs.github.com/en/actions
- Secrets: https://docs.github.com/en/actions/security-guides/encrypted-secrets
Project Documentation:
- Script README:
scripts/README.md - Plan Document:
.claude/plans/nested-greeting-wirth.md
Getting Help:
- Beehiiv API issues → Contact Beehiiv support
- Script errors → Check script logs, review TODOs
- GitHub Actions issues → Check workflow logs
Success Criteria
You’ll know the integration is complete when:
✅ All 5 existing posts cross-posted to Beehiiv ✅ New posts automatically sync within 5 minutes of push ✅ Images display correctly in Beehiiv ✅ No duplicate content SEO issues (“Remove Indexing” enabled) ✅ State file tracks all synced posts ✅ Zero manual work required for publishing
Next Steps
Start here:
- Request Beehiiv Enterprise API access (Task #1 above)
- Wait for approval
- Return to this document and continue with Task #2
Track your progress: Check off items as you complete them.
</div> </article> ` - Page/post content
Theme Documentation- Page/post title- `` - Post date
- `` - Post category
Michael Rogers- Site title from_config.yml
Using Includes
Reusable components are in _includes/ and can be included in layouts:
<header class="site-header">
<div class="wrapper">
<a class="site-title" href="/">Michael Rogers</a>
<nav class="site-nav">
<a href="/about/">About</a>
</nav>
</div>
</header>
<div class="post-meta">
<time datetime="">
</time>
</div>
<footer class="site-footer">
<div class="wrapper">
<p class="tagline">Individuals surprise. Populations rhyme.</p>
<div class="social-links">
<!-- X/Twitter -->
<a href="https://x.com/_mrogers" aria-label="X (Twitter)" target="_blank" rel="noopener noreferrer">
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/>
</svg>
</a>
<!-- LinkedIn -->
<a href="https://linkedin.com/in/mrogerslondon" aria-label="LinkedIn" target="_blank" rel="noopener noreferrer">
<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
<path d="M19 3a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h14m-.5 15.5v-5.3a3.26 3.26 0 0 0-3.26-3.26c-.85 0-1.84.52-2.32 1.3v-1.11h-2.79v8.37h2.79v-4.93c0-.77.62-1.4 1.39-1.4a1.4 1.4 0 0 1 1.4 1.4v4.93h2.79M6.88 8.56a1.68 1.68 0 0 0 1.68-1.68c0-.93-.75-1.69-1.68-1.69a1.69 1.69 0 0 0-1.69 1.69c0 .93.76 1.68 1.69 1.68m1.39 9.94v-8.37H5.5v8.37h2.77z"/>
</svg>
</a>
</div>
</div>
</footer>
Development Workflow
Local Development
1. Install dependencies:
bundle install
2. Start the Jekyll server:
bundle exec jekyll serve
3. Visit the site:
Open http://localhost:4000 in your browser
Making Style Changes
- Edit SCSS files in the
_sass/directory - Jekyll watches for changes and rebuilds automatically (usually takes 1-2 seconds)
- Refresh your browser to see the updates
- No need to restart the server for style changes
Hot Reload:
- SCSS changes: Automatic rebuild
- Layout/include changes: Automatic rebuild
- Config changes: Requires server restart
Testing Changes
Before committing style changes:
- Test responsive breakpoints - Resize browser to test mobile, tablet, desktop views
- Test all page types - Check homepage, blog posts, static pages
- Verify typography - Ensure headings, paragraphs, lists render correctly
- Check components - Test avatars, badges, navigation, footer
- Test color contrast - Ensure text is readable on all backgrounds
Deployment
The site deploys automatically via GitHub Pages:
- Commit your changes:
git add . git commit -m "Update theme styles" - Push to the main branch:
git push origin main -
GitHub Pages builds and deploys automatically (usually takes 1-2 minutes)
- Visit https://mrogers.london to see your changes live
Note: The site uses the github-pages gem to ensure local development matches GitHub’s build environment exactly.
Asset Organization
Images
Storage Location: assets/images/
Organization:
- Post-specific images:
assets/images/[post-slug]/image.jpg - Site-wide images:
assets/images/(avatar, logo, etc.)
Naming Conventions:
- Use lowercase filenames
- Use hyphens for spaces (e.g.,
my-post-hero.jpg) - Be descriptive:
financial-markets-chart.jpgnotimage1.jpg
Optimization:
- Compress images before committing
- Recommended max width: 1200px for blog post images
- Use appropriate formats: JPG for photos, PNG for graphics with transparency
- Consider WebP with JPG/PNG fallbacks for better performance
Referencing in Posts:

CSS Assets
Location: assets/css/main.scss
This is the only CSS file that should exist in assets/css/. All other styles should be added to the modular partials in _sass/.
Never:
- Add inline styles in HTML
- Create additional CSS files in
assets/css/ - Use
<style>tags in layouts
Always:
- Edit SCSS partials in
_sass/ - Use variables for colors and spacing
- Follow the modular structure
Troubleshooting
Common Issues
Issue: Styles not updating
- Solution: Hard refresh your browser (Cmd+Shift+R on Mac, Ctrl+Shift+R on Windows)
- Check that Jekyll rebuild completed without errors
- Verify you edited the correct SCSS file
Issue: Broken layout after changes
- Solution: Check the terminal for Jekyll build errors
- Validate your SCSS syntax
- Ensure you didn’t accidentally delete required CSS classes
Issue: Fonts not loading
- Solution: Check the Google Fonts import URL in
assets/css/main.scss - Verify font names match exactly in the import and variables
- Check browser console for font loading errors
Issue: Local site doesn’t match production
- Solution: Ensure you’re using
bundle exec jekyll serve(not justjekyll serve) - Update gems:
bundle update - Check that
_config.ymlsettings match
Getting Help
If you encounter issues:
- Check Jekyll build output for specific error messages
- Validate your SCSS syntax
- Review recent changes in git:
git diff - Check browser console for JavaScript/CSS errors