Microblog engine for snonux.foo
  • JavaScript 47.7%
  • CSS 29.6%
  • Go 21.4%
  • Go Template 1.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-08-02 19:19:39 +03:00
cmd/snonux Optimize VPN mirror sync and release v0.19.2 2026-08-02 18:50:47 +03:00
integrationtests Add splash screen choice to enter with or without background music (js0) 2026-07-05 10:40:25 +03:00
internal Reset persisted theme after publishing and release v0.19.3 2026-08-02 19:19:39 +03:00
.gitignore Ignore local build and Serena state 2026-04-11 23:03:45 +03:00
coverage.out processor: reject two markdown files claiming the same inbox image 2026-04-27 08:37:20 +03:00
go.mod add snonux static microblog generator 2026-04-09 20:44:58 +03:00
go.sum add snonux static microblog generator 2026-04-09 20:44:58 +03:00
LICENSE add stuff 2026-04-06 16:25:52 +03:00
Magefile.go Release v0.1.6 2026-04-11 23:02:09 +03:00
README.md Add WireGuard fallback for mirror sync 2026-08-02 18:42:02 +03:00

snonux — Static microblog generator

snonux is the static microblog engine behind snonux.foo. It processes source files from an input directory into a self-contained static site with paginated HTML pages, an Atom feed, and themed WebGL backgrounds.

Quick start

go build -o snonux ./cmd/snonux
./snonux --input ./inbox --output ./dist

Creating posts

Drop files into the input directory (./inbox by default). Each file becomes one post. Supported formats:

Plain text (.txt)

inbox/
  thoughts.txt

The text content is rendered as-is into a post.

Markdown (.md)

inbox/
  update.md

Standard Markdown is converted to HTML (GitHub Flavored Markdown supported). Raw HTML blocks are passed through.

Markdown with embedded images

Reference a local image from your Markdown file using standard ![alt](filename) syntax. Place the image file in the same input directory:

inbox/
  update.md
  screenshot.png

Where update.md contains:

Check out this screenshot!

![screenshot](screenshot.png)

Pretty neat, right?

The image file is automatically copied into the post's asset directory, and the <img> src is rewritten to the correct path. The image file is consumed together with the Markdown file and removed from the input directory after processing.

Note: The image filename in the Markdown must match the actual file in the inbox. Remote URLs (http://, https://) are left as-is and not downloaded.

Images (.png, .jpg, .gif)

inbox/
  photo.jpg

A standalone image file becomes its own post. Images wider than 1024px are downscaled and re-encoded as JPEG at 80% quality.

Audio (.mp3)

inbox/
  voice-note.mp3

An audio file becomes a post with an embedded HTML5 audio player.

After processing

All source files are removed from the input directory once they have been successfully processed into the output directory.

Command-line flags

--input DIR      Input directory for new source files (default: ./inbox)
--output DIR     Output directory for generated site (default: ./dist)
--base-url URL   Base URL for Atom feed links (default: https://snonux.foo)
--theme NAME     Visual theme, or "random" (default: random)
--sync           Rsync output to pi0/pi1 after generation (LAN, then WireGuard fallback)
--list-themes    Print available theme names and exit
--version        Print version and exit

Themes

Each run can use a different visual theme. Use --list-themes to see all available themes, or --theme random (the default) to pick one at random.

Output structure

dist/
  index.html                        # Page 1 (newest posts)
  page2.html                        # Page 2, etc.
  atom.xml                          # Atom feed (last 42 entries)
  favicon.ico
  posts/
    2026-04-16-120000/
      post.json                     # Post metadata and rendered HTML
      screenshot.png                # Asset (if any)
    ...

License

See LICENSE.

Third-party assets

The bundled web fonts listed below are self-hosted. Their theme stylesheets make no runtime requests to Google Fonts, gstatic, int10h, or any font CDN. Each bundled font file lives next to its theme stylesheet under internal/generator/templates/themes/<name>/, is committed to git, and is shipped to dist/themes/<name>/ together with a FONT_LICENSE.txt containing the source URL, version/date, and full attribution.

Bundled web fonts:

When adding a new bundled font:

  1. Download the actual file (.woff2 preferred, .woff accepted) into internal/generator/templates/themes/<name>/ and commit it.
  2. Add or update internal/generator/templates/themes/<name>/FONT_LICENSE.txt with attribution, license, source URL, and version/date.
  3. Add an @font-face block in that theme's theme.css using a relative url(...) to the bundled file.
  4. Add a bullet here pointing at the new FONT_LICENSE.txt.

The embed pipeline (internal/generator/templates/embed.go) automatically picks up *.woff, *.woff2, and FONT_LICENSE.txt inside any theme directory, and writeThemeAsset copies them out to dist/themes/<name>/ — no Go code changes needed for new fonts.