README.md
167 lines · 6473 bytes
1# cleberg.net
2
3This repository holds the files for [cleberg.net](https://cleberg.net),
4a static-site with blog posts, personal links, and more.
5
6This site uses [orgo](https://gitbay.org/krz/orgo) to build the
7static site.
8
9## Site Structure
10
11I write content pages (e.g., blog posts) in org-mode and templates in
12HTML. orgo builds these files into a static site, and then I deploy
13them to a web server.
14
15The main site components are:
16
17- Org source files in `content/`, containing blog posts and pages.
18 That directory is the site's URL root: `content/blog/post.org`
19 publishes at `/blog/post.html`.
20- A configuration file (`content/orgo.toml`) that specifies the base
21 URL, navigation, templates, and the generated pages (home, blog and
22 garden indexes, tags, and the RSS feed).
23- HTML templates in `content/templates/`.
24- Assets such as images and style sheets, located in designated
25 subdirectories. `theme/static/` is published at `/`.
26- Utility scripts (e.g., `build.py`) to facilitate building and
27 deployment.
28
29## Dependencies
30
31The publishing system depends on:
32
33- [orgo](https://gitbay.org/krz/orgo), the static site
34 generator, installed with `cargo install --git
35 https://gitbay.org/krz/orgo`.
36- `rsync` for deployment.
37- [uv](https://github.com/astral-sh/uv) to run `build.py`.
38
39## Configuration
40
41You can customize site settings within the `content/orgo.toml` file.
42This file establishes key variables such as:
43
44- The base URL for links.
45- Which pages appear in the navigation, and in what order.
46- Per-directory template rules.
47- The collections that generate the indexes, tag pages, and feed.
48
49Users intending to modify site parameters should review and edit this
50file accordingly. The orgo documentation contains extensive details on
51configuration options and expected formats.
52
53## Setup Instructions
54
55To obtain a working copy of this repository, execute the following
56commands within a shell environment or Emacs shell interface:
57
58``` shell
59git clone https://gitbay.org/cmc/cleberg.net
60cd cleberg.net
61emacs -nw
62```
63
64For users employing Doom Emacs, open any repository Org file using
65`SPC f f` to access the content.
66
67## Building and Publishing the Site
68
69The `build.py` script wraps the build: it runs orgo, rewrites the footer's
70orgo version to match the orgo that ran, and then either deploys the result
71or serves it locally.
72
73Environment variables control what it does, and all default to off:
74
75- `BUILD=true` performs the build.
76- `DEPLOY=true` deploys in production, or starts a development server
77 on port 8000 otherwise.
78- `ENV=prod` selects production: image URLs are rewritten to be
79 root-relative (see Deployment below) and the `ruff` pass is skipped.
80 Anything else builds for development.
81- `DRY_RUN=true` turns a production deploy into a report. Production
82 only; ignored everywhere else.
83
84Exactly one combination writes to the server:
85
86| `ENV` | `BUILD` | `DEPLOY` | `DRY_RUN` | What happens | Output | Server |
87|--------|---------|----------|-----------|---------------------------------------|--------------|-------------------|
88| unset | `true` | — | — | Development build, `ruff` first | `.build-dev/`| Untouched |
89| unset | `true` | `true` | — | Development build, then serve on :8000| `.build-dev/`| Untouched |
90| `prod` | `true` | — | — | Production build and image rewrite | `.build/` | Untouched |
91| `prod` | — | `true` | `true` | Reports what a deploy would change | — | Read only |
92| `prod` | `true` | `true` | — | Production build, then deploy | `.build/` | **Overwritten** |
93
94``` shell
95# Development build:
96BUILD=true uv run build.py
97
98# Development build, then serve it on localhost:8000:
99BUILD=true DEPLOY=true uv run build.py
100
101# Production build, no deploy:
102ENV=prod BUILD=true uv run build.py
103
104# What would a deploy change? Connects, compares, transfers nothing:
105ENV=prod DEPLOY=true DRY_RUN=true uv run build.py
106
107# Production build and deploy. This is the one that writes to the server:
108ENV=prod BUILD=true DEPLOY=true uv run build.py
109```
110
111Generated site files reside in `.build/` for production and
112`.build-dev/` for development.
113
114The deploy is `rsync --delete-before`, so files the build no longer
115produces are removed from the server. That is what makes the dry run
116worth having: a build that silently produced fewer pages would quietly
117delete the rest. Lines beginning `*deleting` in the dry-run output are
118what the real deploy would remove.
119
120Builds are incremental: orgo keeps an `.orgo-cache.json` inside the
121output directory and re-renders only what changed, so the directory is
122left in place between runs. Delete it for a clean build. The two
123environments use separate directories because production rewrites image
124URLs in the output and development does not.
125
126orgo can also build and preview on its own, without `build.py`:
127
128``` shell
129orgo serve content -o /tmp/preview
130```
131
132## Deployment
133
134Production builds rewrite image URLs to root-relative ones
135(`/img/blog/...`) instead of absolute `https://img.cleberg.net/` ones so
136the site renders standalone on the onion service without fetching assets
137off-onion. The stylesheet is already same-origin.
138
139This means the web server must serve the image store at `/img/` on the
140`cleberg.net` vhost. The images live at `/var/www/img/` (their own host,
141`img.cleberg.net`); expose them under `cleberg.net/img/` with a symlink:
142
143``` shell
144ln -s /var/www/img /var/www/cleberg.net/img
145```
146
147Without this, images 404 in production. Development builds keep the
148absolute `img.cleberg.net` URLs, so local previews load images from the
149live host and need no symlink.
150
151Once assets are same-origin, the vhost CSP can tighten `img-src`,
152`style-src`, and `font-src` back to `'self'`, and drop `bubbles.town`
153from `script-src`/`connect-src` (the vote widget was removed; only a
154plain link to Bubbles remains). After deploying, purge the Cloudflare
155cache (responses carry a 31-day `max-age`).
156
157## Creating New Blog Posts
158
159To add new blog content, follow this procedure within Emacs:
160
1611. Open a new Org file (via `C-x C-f` or Doom\'s `SPC f f`).
1622. Insert the contents of the post template with `C-x i`, sourcing from
163 `utils/template.org`.
1643. Modify the new file as needed to add post content and metadata.
165
166This method streamlines content creation by reusing a preformatted
167template.