Skip to content

Repository files navigation

Technical Blog

A Jekyll-powered blog for GitHub Pages with client-side search, tag navigation, and Obsidian knowledge graph integration.

Features

  • Client-side search — Lunr.js full-text search across all articles
  • Tag system — filterable tag index, clickable tag chips on every article
  • Knowledge graph — D3.js force-directed graph showing article connections
  • Obsidian compatible — repo doubles as an Obsidian vault with [[wiki-links]] and backlinks
  • Zero-database — no server-side code, no comments, no external services

Local Development

Prerequisites

  • Ruby 3.x (ruby --version)
  • Python 3.x (python3 --version)

Setup

# Install Jekyll and dependencies
gem install jekyll kramdown-parser-gfm webrick

# Ruby 3.4+ may also need these
gem install base64 bigdecimal csv erb ostruct logger

Build and Serve

# Generate backlinks and graph data
python3 _scripts/obsidian_bridge.py

# Build and serve locally
jekyll serve

Site will be available at http://localhost:4000.

Build Only (no server)

python3 _scripts/obsidian_bridge.py
jekyll build

Output goes to _site/.

Adding Articles

Manual

  1. Create a .md file in _articles/ with front-matter:
---
title: "Your Title"
date: 2026-04-13
tags:
  - topic
categories:
  - Category
---
  1. Write content in standard markdown
  2. Use [[other-article]] for cross-references (converted at build time)
  3. git push — GitHub Actions builds and deploys

Import Script

# Single file (adds front-matter if missing)
python3 _scripts/import_article.py path/to/note.md

# Bulk import from a structured directory (maps subdirs to categories/tags)
python3 _scripts/migrate_cheatsheets.py path/to/notes/

Deployment

Deployed automatically via GitHub Actions on push to main.

Required setting: In your GitHub repo, go to Settings > Pages and set the source to "GitHub Actions" (not "Deploy from branch").

The pipeline runs:

  1. obsidian_bridge.py — converts wiki-links, generates backlinks + graph data
  2. Jekyll build — renders markdown to HTML
  3. build-search-index.js — builds Lunr.js search index
  4. Deploy to GitHub Pages

Maintenance

Updating the design

All design tokens (colors, fonts, spacing, breakpoints) are CSS custom properties in :root in assets/css/main.css. Syntax highlighting colors are in assets/css/syntax.css.

Regenerating data files

_data/backlinks.json and _data/graph.json are generated by the obsidian bridge script. They are checked in as seed files but overwritten at build time. To regenerate locally:

python3 _scripts/obsidian_bridge.py

Warning: This modifies _articles/*.md in-place (converts wiki-links to standard links). In CI, it runs on the checkout copy — your repo source is never modified.

Liquid escaping

Articles containing {{ }} syntax (Blade, Handlebars, Go templates) must be wrapped with {% raw %} / {% endraw %} after the front-matter. See ARTICLE_REFERENCE.md for details.

Build scripts

Script Purpose When it runs
_scripts/obsidian_bridge.py Wiki-link conversion, backlinks, graph data CI step 1 + local dev
_scripts/build-search-index.js Lunr.js pre-built search index CI step 3 (after Jekyll build)
_scripts/import_article.py Import a single note with auto front-matter Manual
_scripts/migrate_cheatsheets.py Bulk import from a structured directory Manual

Project Structure

_articles/       Blog articles (Jekyll collection, also Obsidian vault)
_layouts/        HTML templates (default, home, article)
_includes/       Reusable partials (nav, head, footer, tag-chips, backlinks)
_data/           Generated JSON (backlinks, graph) — overwritten at build time
_scripts/        Build and migration scripts (excluded from site output)
_templates/      Article templates (excluded from site output)
assets/css/      Stylesheets (main.css, syntax.css)
assets/js/       Client-side JS (search, tag-filter, graph)
.github/         GitHub Actions workflow

About

My blog

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages