Skip to content

dvhthomas/blog

Repository files navigation

My Blog

Bits By Me uses the blog uses the hugo static site generator. Publishing articles is easy; working with Jupyter notebooks that become embedded GitHub gists is slightly more involved.

Prerequisites

The easiest way to start is to use a GitHub Codespace or run locally as a devcontainer in VS Code (see devcontainer.json for details).

If you must use locally then you need to install:

Required:

  • Go - I use asdf so asdf install golang latest works for me.
  • Hugo - brew install hugo
  • Task - go install github.com/go-task/task/v3/cmd/task@latest && asdf reshim.
  • D2 - curl -fsSL https://d2lang.com/install.sh | sh -s -- (required if using D2 diagrams)
  • Chrome or Chromium - Required for resume PDF generation. Usually already installed on macOS/Linux. On Ubuntu: sudo apt-get install chromium-browser

Author and publish

Write a new blog post by providing a TITLE and calling the task blog:

TITLE="some-factoid" task blog
...write write write...
git add .
git commit -m "my cool post"
git push origin master

Today I Learned posts work exactly the same way - provide a TITLE:

TITLE="something-i-learned" task til
# OR
TITLE="something-i-learned" task today-i-learned

Each post is put into a folder like blog/1971/01/01/my-post-title/index.md or til/1971/01/01/my-til-title/index.md. This gives you a spot to drop post-specific content next to the post itself. For example, if you want an image for a post you can drop it in that folder and reference it in the post thus:

Hosting

The blog itself is hosting on GitHub Pages. The DNS configuration is in Squarespace Domains accessible using my personal Google account.

Analytics

Analytics in bitsby.goatcounter.com.

Development Workflow

Start the dev server (recommended):

task                      # Renders D2 diagrams + starts Hugo dev server
# OR
go run blog.go --serve    # Same thing without Task

Visit http://localhost:1313 to preview. The server watches for changes and automatically:

  • Re-renders D2 diagrams when .d2 files change
  • Rebuilds Hugo when markdown/templates change
  • Reloads your browser

Build for production:

task build                           # Renders D2 + builds Hugo + generates resume PDF
# OR manually:
go run blog.go && hugo --gc --minify && go run blog.go  # D2 → Hugo → PDF

The build process:

  1. Renders D2 diagrams to SVG
  2. Builds Hugo site to public/
  3. Generates public/resume.pdf from public/resume/index.html

Look at the draft Tips post to see examples of how you can use various elements like diagrams, code, and tweets.

Content pre-processing

D2 Diagrams

The blog supports D2 diagrams - a modern declarative diagram language. D2 files in your page bundles are automatically rendered to SVG images during the build process.

Prerequisites

Install D2:

# Install D2 (required for rendering diagrams)
curl -fsSL https://d2lang.com/install.sh | sh -s --
# Or via Go:
go install oss.terrastruct.com/d2@latest

Using D2 diagrams in posts

  1. Create a D2 file in your page bundle directory:
# Example: content/blog/2025-10-17/my-post/diagram.d2
x -> y -> z: Simple flow
a -> b: {
  style.stroke: "#0d32b2"
  style.fill: "#c2d2e0"
}
  1. Reference it in your post using the d2 shortcode:
{{</* d2 src="diagram.d2" */>}}
  1. Optional: Add a caption:
{{</* d2 src="diagram.d2" */>}}
This diagram shows the data flow through our system.
{{</* /d2 */>}}

Site-wide configuration

You can set D2 rendering options for all diagrams in config.toml:

[params.d2]
    theme = "6"         # D2 theme: number (0-8) or name like "cool-classics"
    layout = "elk"      # Layout engine: "dagre", "elk", etc.
    sketch = true       # Enable hand-drawn style globally

Available themes: Run d2 --list-themes to see all available themes. Available layouts: Run d2 --list-layouts to see all available layout engines.

Note: These settings apply to all D2 diagrams site-wide. They're used during the render step before Hugo builds the site.

Shortcode usage

The shortcode is simple - just reference your D2 file:

{{</* d2 src="diagram.d2" */>}}

With a caption:

{{</* d2 src="diagram.d2" */>}}
This diagram shows the system architecture.
{{</* /d2 */>}}

The only parameter is:

  • src (required): Path to the .d2 file relative to your page bundle

How it works

Development mode (task):

  • Renders all D2 files once at startup
  • Starts Hugo dev server with the blog.go tool
  • Watches for changes to .d2 files and automatically re-renders them
  • Hugo detects the SVG changes and reloads the page

Build mode (task build):

  • Renders all D2 files before building
  • Generates static site in public/ directory

Generated files:

  • SVG files generated from .d2 files are not tracked in git (see .gitignore)
  • Only commit your .d2 source files
  • Generated SVGs are recreated during dev/build

Manual rendering

# Render all D2 diagrams
task render-d2

# Or use the Go tool directly
go run blog.go

# Watch D2 files only (no Hugo server)
go run blog.go --watch

# Verbose output
go run blog.go --verbose

Troubleshooting

Diagrams not appearing:

  • Ensure D2 is installed: d2 --version
  • Check that the .svg file was generated next to your .d2 file
  • Verify the src path in your shortcode matches the actual file name
  • Try manually running: task render-d2

Compress Images

Following this advice it's a good idea to compress images before adding to Git. Typical PNG results: 480KB → 70KB (85% reduction). JPEGs also shrink meaningfully at quality 80 with metadata stripped.

Prerequisites

Install the compression tools once:

# macOS
brew install pngquant oxipng jpegoptim

# Linux (Ubuntu/Debian)
sudo apt install pngquant jpegoptim
cargo install oxipng
Tool Purpose
pngquant Lossy PNG palette reduction (first PNG pass)
oxipng Lossless PNG re-encoding (second PNG pass)
jpegoptim JPEG quality capping + metadata stripping

Using the squish script

The squish script recursively finds PNG and JPEG images under a directory and compresses them:

# Preview what will be compressed (dry-run, safe)
./squish content/blog/2021/05/11

# Actually compress (creates -fs8.png / -squished.jpg siblings)
./squish content/blog/2021/05/11 --now

# Replace originals with the compressed versions (destructive, prompts to confirm)
./squish content/blog/2021/05/11 --clean

Features:

  • Recursively finds PNG, JPG, and JPEG files
  • Handles filenames with spaces
  • Shows before/after sizes and compression ratios
  • Safe by default (dry-run mode)
  • Intermediate -fs8.png and -squished.{jpg,jpeg} files are git-ignored

Output suffixes:

  • PNGs → name-fs8.png (via pngquant + oxipng)
  • JPEGs → name-squished.jpg / name-squished.jpeg (via jpegoptim, --max=80 --strip-all)

Workflow:

  1. Add images to your post directory
  2. Run ./squish <path> to preview
  3. Run ./squish <path> --now to compress
  4. Review the -fs8.png / -squished.* files
  5. Run ./squish <path> --clean to replace originals
  6. Commit the compressed images

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors