My homepage at myl7.org, built with Hugo and the Blowfish theme.
- Blog posts and pages rendered with Hugo
- Post screenshot pipeline: capture, crop, and split into pages for sharing
Clone the repository and initialize the theme submodule:
git clone --recurse-submodules https://github.com/myl7/homepage.git
cd homepageStart the development server:
hugo serverThe site will be available at http://localhost:1313/.
Build for production:
hugoOutput goes to the public/ directory.
Vercel's default Hugo version is too old to recognize the hugo.toml config file.
Instead of erroring, it silently builds an empty site.
Set the HUGO_VERSION environment variable in your Vercel project settings to a newer version (e.g., 0.157.0).
Create a new post:
hugo new content posts/my-post/index.mdEdit the generated file under content/posts/my-post/index.md.
Three scripts under scripts/ form a pipeline to capture post screenshots and split them into sharable pages.
Install dependencies first:
uv sync --dev
uv run playwright install chromiumCapture a post as a full-page screenshot. Outputs PNG to stdout by default.
# Capture from production site
scripts/capture_post.py coding-tips-1 > screenshot.png
# Capture from local dev server
scripts/capture_post.py coding-tips-1 --local > screenshot.png
# Save to a file directly
scripts/capture_post.py coding-tips-1 -o screenshots/coding-tips-1.png
# Custom viewport and scale
scripts/capture_post.py coding-tips-1 --width 440 --scale 3Options:
| Flag | Default | Description |
|---|---|---|
slug |
(required) | Post slug, e.g. coding-tips-1 |
-o, --output |
stdout | Output file path |
--base-url |
https://myl7.org |
Base URL |
--local |
off | Use http://localhost:1313 |
--width |
440 | Viewport width in px |
--scale |
3 | Device scale factor |
--wait |
2.0 | Seconds to wait after page load |
--no-scroll |
off | Skip scrolling for lazy content |
Crop header and footer from a screenshot. Reads PNG from stdin, writes cropped PNG to stdout.
# Crop with default margins
scripts/crop_post.py < screenshot.png > cropped.png
# Custom crop amounts
scripts/crop_post.py --top 200 --bottom 150 < screenshot.png > cropped.pngOptions:
| Flag | Default | Description |
|---|---|---|
--top |
140 | Pixels to crop from top |
--bottom |
1080 | Pixels to crop from bottom |
Split a long screenshot into 3:4 aspect ratio pages. Reads PNG from stdin, writes numbered page files to the output directory.
# Split with defaults (pages saved to screenshots/)
scripts/split_post.py < cropped.png
# Custom name and output directory
scripts/split_post.py --name coding-tips-1 --output-dir screenshots < cropped.png
# Custom padding and ratio
scripts/split_post.py --padding 60 --ratio 3:4 < cropped.pngOptions:
| Flag | Default | Description |
|---|---|---|
--name |
page |
Output file name stem |
--output-dir |
screenshots |
Output directory (created if needed) |
--padding |
80 | Padding at split edges in px |
--ratio |
3:4 |
Page aspect ratio as W:H |
--search |
0.15 | Search range for clean splits as ratio of page height |
Chain all three scripts together:
scripts/capture_post.py coding-tips-1 --local \
| scripts/crop_post.py \
| scripts/split_post.py --name coding-tips-1This captures a post, crops the browser chrome, and splits the result into screenshots/coding-tips-1_01.png, screenshots/coding-tips-1_02.png, etc.
See the Blowfish documentation for all available theme parameters.
Copyright (C) 2026 Yulong Ming i@myl7.org.
Code licensed under Apache License, Version 2.0.
Text content in ./content licensed under CC BY 4.0 License.