Skip to content

joshuapsteele/joshuapsteele.github.io

Repository files navigation

Joshua P. Steele's Personal Website

Hugo Code License: MIT Content License: CC BY-NC-SA 4.0 Deploy Hugo site to Pages

This is the source code for my personal website and blog, built with Hugo and deployed via GitHub Pages.

Live Site: joshuapsteele.com

Colophon: joshuapsteele.com/colophon - Detailed information about how this site is built

Tech Stack

  • Static Site Generator: Hugo 0.147.3 (Extended)
  • Theme: PaperMod
  • Deployment: GitHub Pages with GitHub Actions
  • Search: Fuse.js
  • Node: 18+ (local) / 20 (CI)

Features

  • 📝 Blog with 310+ posts organized by categories and tags
  • 📧 "Steele Notes" email newsletter via Buttondown
  • 🔍 Full-text search functionality
  • 📱 Responsive design with dark mode support
  • 📊 RSS and JSON feeds
  • 🏷️ Taxonomy management system
  • 💬 Comment system integration (Disqus)
  • 📈 Analytics integration (Google Analytics, Tinylytics)
  • ⚡ Optimized build with minification and caching
  • 🌐 IndieWeb Integration:
    • Microformats2 markup (h-card, h-entry, h-feed)
    • Webmention support for receiving interactions
    • Reply context display for reply posts
    • IndieAuth for domain-based authentication
    • WebFinger for Fediverse discovery
    • rel="me" identity verification
    • POSSE workflow (Publish Own Site, Syndicate Everywhere)

Quick Start

Prerequisites

Installation

# Clone the repository with submodules
git clone --recurse-submodules https://github.com/joshuapsteele/joshuapsteele.github.io.git
cd joshuapsteele.github.io

# If you forgot --recurse-submodules, initialize them:
git submodule update --init --recursive

# Install dependencies (if any)
npm install

Development

# Start local development server with drafts
npm run dev
# Site will be available at http://localhost:1313

# Build for production
npm run build

# Build without minification (faster)
npm run build:fast

# Build with template performance metrics
npm run build:stats

# Clean generated files
npm run clean

Project Structure

.
├── content/
│   ├── blog/          # Blog posts (310+ markdown files)
│   ├── pages/         # Static pages (about, contact, cv, now, uses, etc.)
│   └── search.md      # Search page
├── layouts/           # Custom Hugo layouts and overrides
│   ├── shortcodes/    # Custom shortcodes (audio, callout, figure, gallery)
│   ├── partials/      # Partial templates (webmentions, analytics, etc.)
│   └── _default/      # Default layouts (h-entry, h-feed markup)
├── static/            # Static assets (images, PDFs, favicons)
├── assets/            # Processed assets (CSS extensions)
├── scripts/           # Maintenance and automation scripts
│   ├── data/          # Configuration files and audit outputs
│   ├── *.py           # Python scripts for auditing and content management
│   └── *.sh           # Shell scripts for deployment and utilities
├── templates/         # Obsidian blog post templates
├── themes/            # PaperMod theme (git submodule)
├── docs/              # Additional documentation and audit reports
├── public/            # Generated site (git-ignored, never edit)
├── hugo.yaml          # Main site configuration
├── CLAUDE.md          # AI assistant guidance
└── .github/
    └── workflows/
        └── hugo.yml   # GitHub Actions deployment workflow

Content Management

Creating a New Blog Post

# Create a new post file in content/blog/
# Use kebab-case naming: my-new-post.md

Example front matter:

---
title: "My New Post"
date: 2025-11-14
tags: ["hugo", "blogging"]
categories: ["Tech"]
description: "A brief description of the post"
draft: false
---

Your content here...

Customizing the Theme

  • CSS: Edit assets/css/extended/custom.css (do not edit theme files directly)
  • Layouts: Create overrides in layouts/ mirroring theme paths
  • Shortcodes: Add custom shortcodes in layouts/shortcodes/

IndieWeb Features

This site is part of the IndieWeb, a community effort to keep the web independent and user-controlled.

Identity & Discovery

  • h-card: Machine-readable identity information on the homepage
  • rel="me": Verified links to other profiles (Micro.blog, Mastodon)
  • WebFinger: Fediverse discovery at /.well-known/webfinger
  • IndieAuth: Sign in with your domain at https://joshuapsteele.com

Content Markup

  • h-entry: Blog posts marked up with microformats2 for machine readability
  • h-feed: Blog list pages formatted as feeds for IndieWeb readers
  • Semantic classes: p-name, e-content, dt-published, p-author, p-category

Social Interactions

  • Webmentions: Receive likes, replies, and mentions from across the web
    • Powered by webmention.io
    • JavaScript-based display of webmentions and Micro.blog conversations on each post
    • Grouped by type: likes, reposts, replies, mentions
  • Outgoing Webmentions: Recent reply posts are checked during deploy and notify the original post when it advertises a Webmention endpoint
  • Syndication links: The deploy fetches Micro.blog's public JSON feed and renders known Mastodon, Threads, and Micro.blog discussion links on canonical posts

Reply Posts

Create reply posts by adding in_reply_to to your front matter:

---
title: "My Reply"
date: 2025-12-09
in_reply_to: "https://example.com/original-post"
---

The site will automatically:

  • Display a reply context card showing the original post
  • Mark up the post with u-in-reply-to for proper webmention threading
  • Attempt to fetch and show the original author, title, and excerpt
  • Include the reply link in JSON Feed output and attempt an outgoing Webmention during deploy

IndieWeb Webring

This site is part of the IndieWeb Webring - a collection of IndieWeb sites linked together. Find the webring navigation in the footer.

POSSE Workflow

Posts are published on this site first, then syndicated to:

scripts/fetch_syndication_links.py maps Micro.blog's _microblog.syndication URLs back to canonical joshuapsteele.com paths and writes data/syndication.json. GitHub Actions runs it before Hugo builds, and a scheduled deploy refreshes those links after Micro.blog finishes asynchronous cross-posting.

Deployment

The site automatically deploys to GitHub Pages when changes are pushed to the main branch via GitHub Actions.

Manual Deployment

# Using the deploy script (commits all changes and pushes to main)
npm run deploy
# or with a custom commit message:
./deploy.sh "Your commit message"

Important: Always test locally with npm run dev and npm run build before deploying!

Maintenance Tools

The scripts/ directory contains various automation tools for maintaining and analyzing the site. All scripts should be run from the repository root directory.

Shell Scripts

  • deploy.sh - Commits all changes with timestamp (or custom message) and pushes to main branch
    ./scripts/deploy.sh "Optional commit message"
  • review_changes.sh - Review staged git changes before committing
  • apply-high-traffic-tags.sh - Apply tags to high-traffic posts
  • rename_blog_files.sh - Rename dated blog posts to remove date prefixes ⚠️ Review before running
  • cleanup_images.sh - Remove legacy/external images ⚠️ DANGEROUS: Review carefully before running

Python Audit & Analysis Scripts

Content Auditing:

  • audit-frontmatter.py - Analyze front matter for missing fields and inconsistencies

    python3 scripts/audit-frontmatter.py

    Outputs: scripts/data/audit-frontmatter.json

  • check-internal-links.py - Check for broken internal links

    python3 scripts/check-internal-links.py

    Outputs: scripts/data/audit-internal-links.json

  • check-external-links.py - Check for broken external links (may take time)

    python3 scripts/check-external-links.py

    Outputs: scripts/data/audit-external-links.json

Content Management:

Taxonomy & Categorization:

Analytics:

Taxonomy Configuration

The site uses a taxonomy consolidation system with configuration files in scripts/data/:

  • taxonomy_map.yaml - Master configuration defining category/tag consolidation rules
  • taxonomy_map.suggested.yaml - AI-generated suggestions (review before using)
  • taxonomy_map.generated.yaml - Generated mapping results from processing

Best Practices for Scripts

  • Always run audit scripts before bulk changes to understand current state
  • Review git diff after running cleanup/modification scripts
  • Test with npm run dev and npm run build after script-based changes
  • Back up important configuration files before running destructive scripts

Configuration

Main configuration is in hugo.yaml. Key settings include:

  • Profile Mode: Custom homepage with profile buttons
  • Navigation: Top menu and footer customization
  • Social: Mastodon, Threads, GitHub, LinkedIn, RSS
  • Search: Fuse.js configuration
  • Feeds: RSS and JSON output formats
  • Build: Image optimization, caching, minification

Documentation

  • CLAUDE.md - Comprehensive guide for AI assistants working with this codebase
  • AGENTS.md - Repository guidelines and conventions
  • Audit Reports - Various AUDIT-*.md files with site analysis

Contributing

This is a personal website, but if you notice any issues or have suggestions:

  1. Open an issue describing the problem or suggestion
  2. If you'd like to contribute a fix, fork the repo and submit a pull request

License

This repository uses a dual-license structure:

Code and Configuration (MIT License)

The code, scripts, layouts, configuration files, and other technical implementations in this repository are licensed under the MIT License - see LICENSE-CODE file for details.

This includes but is not limited to:

  • Hugo configuration (hugo.yaml)
  • Layout templates and partials (layouts/)
  • Custom shortcodes
  • Build scripts and automation tools
  • CSS and JavaScript files
  • GitHub Actions workflows

Content (CC BY-NC-SA 4.0)

All original written content, including blog posts, articles, and pages in the content/ directory, is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License - see LICENSE-CONTENT file for details.

This means:

  • ✅ You can share and adapt the content with attribution
  • ❌ You cannot use it for commercial purposes
  • 🔄 Derivative works must use the same license
  • 📝 You must provide proper attribution and indicate changes

In summary: Feel free to learn from and use the site's code and configuration, but please don't republish my writing without permission.

Contact

Acknowledgments

About

No description, website, or topics provided.

Resources

License

MIT, Unknown licenses found

Licenses found

MIT
LICENSE-CODE
Unknown
LICENSE-CONTENT

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors