Personal blog at really.lol. A static Astro site on Cloudflare Pages, with a Bun CLI for content management.
site/ # Astro static site, deployed to CF Pages
cli/ # CLI tool (Bun): content creation, media management, library sync
No CMS and no database. Content lives in markdown files (Astro content collections) and JSON fixtures committed to the repo.
bun install
bun run dev # Astro dev server on :4321
bun run build # Build static site
bun run preview # Preview the built site
bun run deploy # Build and deploy to CF Pages
bun run test # Run testsPushing to main also triggers a CF Pages build.
Run via bun run cli or bun cli/src/index.ts.
cli create post --title "..." [--body "..." --tags a,b --subtitle "..."]
cli create photo <image-file> [--title "..." --location "..." --tags a,b]
cli create note --title "..."
cli create highlight --title "..." --link "..." [--body "> quote" --tags a,b]Run any of these without --title for interactive prompts. Files are written to site/src/content/<collection>/ as YYYY-MM-DD-slug.md.
Photo posts take their date from the image's EXIF capture date (DateTimeOriginal, falling back to DateTimeDigitized then the IFD0 DateTime). Images with no usable EXIF fall back to today's date and print a warning. --date always wins. The parser is pure TypeScript in cli/src/lib/exif.ts, so there is no exiftool dependency.
cli media upload <file> [--prefix img/post/slug]
cli media verify # Check content media refs exist in R2
cli media orphans # List R2 objects no content referencesMedia is stored in R2 and served from media.really.lol.
cli library sync books --shelf read|reading|toread
cli library sync films --list watched|towatch --from path/to/letterboxd-export.zip
cli library sync links--from accepts a Letterboxd export .zip, an extracted directory, or a single CSV (diary.csv for --list watched, watchlist.csv for --list towatch).
cli tags init # Scan untagged photos, build state file
cli tags describe # Generate descriptions via a local Ollama vision model
cli tags suggest # Suggest tags from those descriptions
cli tags review # Browser review UI on :4444
cli tags apply [--dry-run] # Write approved tags to the markdown filescli check links # Find broken internal links in the built site| Collection | Directory | Notes |
|---|---|---|
| blog | site/src/content/blog/ |
Posts, media reviews (media-log tag), link roundups |
| note | site/src/content/note/ |
Microblog entries |
| photo | site/src/content/photo/ |
Photo posts with location and tags |
| highlight | site/src/content/highlight/ |
Blockquote excerpts from articles and books |
Library data lives as committed JSON in site/src/data/: books-*.json, films-*.json, links.json, and config.json for tag mappings.
bun testUnit tests sit alongside the code in cli/src/**/__tests__/.
cli library sync books shells out to the cover CLI to fetch data from Hardcover.
git clone https://github.com/jackreid/cover.git
cd cover
go build -o cover # then put the binary on your PATHGet an API key from your hardcover.app account settings and set HARDCOVER_API_KEY.
| Variable | Used for |
|---|---|
R2_ACCOUNT_ID, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY |
R2 access from the CLI |
R2_BUCKET |
R2 bucket name (default media-really-lol) |
RAINDROP_ACCESS_TOKEN |
Raindrop API for link sync |
HARDCOVER_API_KEY |
Hardcover API, via the cover CLI |
- Language: English (GB)
- Pagination: 40 items per page
- Update
/uses