krz/orgo

Lightning fast org-mode static site generator. fast go org-mode static-site-generator

Commit 57bf33c265

57bf33c26554f1e88965a824a72c363a81e4ba56

parent: 0001ef1846

Verified · cmc

cmc <hello@cleberg.net> · 2026-08-11 06:58 UTC

docs: explain what the two path arguments mean

The quick start showed `serve my-site -o _site` straight out of `init` and never said
what either path was, so adapting it to org files you already have meant guessing.

SOURCE is the URL root, not "the project directory": SOURCE/blog/post.org publishes at
/blog/post.html. That matters because guessing wrong still *works*. Pointing at a
repository root instead of its content/ subdirectory builds every page one level deep —
/content/blog/post.html — and copies README.md, build scripts and licence files into the
site as assets. Verified both ways against a real 179-file repository: the content
directory gives the 179 pages at the right URLs, the repository root gives the same 179
pages at the wrong ones plus 19 files that are not content.

Documents the rule, both symptoms of getting it wrong, a table of common layouts, that
OUTPUT may live inside SOURCE, that config and templates live in SOURCE and are not
published, --config for keeping the config elsewhere, and a worked example that audits
before it builds.

Layout: unified · split

docs/guide/01-cli.org +17
@@ -2,6 +2,23 @@
22#+DESCRIPTION: Every command and flag, and what each is actually for.
33#+LEDE: Six commands: build, serve, watch, audit, init, clean.
44
5* The two paths
6
7=build=, =serve= and =watch= all take the same pair:
8
9#+BEGIN_SRC sh
10org-ssg <command> <SOURCE> -o <OUTPUT>
11#+END_SRC
12
13*SOURCE is the URL root*, not "the project". =SOURCE/blog/post.org= is published at
14=/blog/post.html=, so if your writing lives in a =content/= subdirectory you point at
15=content/= and not at the repository around it. Choosing the directory above the one you
16meant still builds — it just prefixes every URL with that directory's name and copies
17your build scripts in as assets. [[file:../quickstart.org][Quick start]] works through it.
18
19*OUTPUT* may live inside the source; it is recognised and skipped, so a build never
20consumes its own output.
21
522* build
623
724#+BEGIN_SRC sh
docs/quickstart.org +70 −9
@@ -29,27 +29,88 @@ my-site/
2929 feed.xml an RSS feed
3030#+END_EXAMPLE
3131
32* Or skip all of that
32* Adapting it to org files you already have
3333
34You do not need =init=, a config file, or templates. Point the builder at org files you
35already have:
34You do not need =init=, a config file, or templates. Every command takes the same two
35paths:
3636
3737#+BEGIN_SRC sh
38org-ssg build ~/notes -o _site
38org-ssg serve <SOURCE> -o <OUTPUT>
3939#+END_SRC
4040
41You get a complete site with a built-in layout, navigation across your top-level pages,
42and syntax highlighting. Nothing in your files has to change.
41** SOURCE is the URL root
4342
44Before trusting it with a large collection, ask what it makes of your writing:
43This is the one thing worth getting right, and it is not "the project directory" — it is
44*the directory whose contents should sit at the top of your site*. A file at
45=SOURCE/blog/post.org= is published at =/blog/post.html=.
46
47So if your writing lives in a =content/= subdirectory, point at =content/=, not at the
48repository around it:
49
50#+BEGIN_SRC sh
51cd ~/my-site
52org-ssg serve content -o _site # → /blog/post.html
53#+END_SRC
54
55Pointing one level too high still builds, which is what makes it worth saying out loud.
56It just builds the wrong site:
57
58#+BEGIN_SRC sh
59org-ssg serve . -o _site # → /content/blog/post.html
60#+END_SRC
61
62Every URL gains a =/content/= prefix, and every non-org file in the repository —
63=README.md=, build scripts, licence files — is copied into the output as a site asset.
64If you see either symptom, you picked the directory above the one you meant.
65
66** Common layouts
67
68| Your files | Command |
69|------------+---------|
70| =~/notes/*.org= | =org-ssg serve ~/notes -o /tmp/notes-site= |
71| =my-site/content/**/*.org= | =cd my-site && org-ssg serve content -o _site= |
72| =my-site/*.org= at the top level | =cd my-site && org-ssg serve . -o _site= |
73| Org files scattered in a code repo | Do not. Copy or symlink the ones you publish into one directory. |
74
75** OUTPUT can live inside the source
76
77=org-ssg serve . -o _site= is fine: the output directory is recognised and skipped, so
78the build never copies its own output back into itself. Nothing dot-prefixed is published
79either, so =.git= stays out of a site built from a repository root.
80
81** Where config and templates go
82
83Both live in the *source* directory — =SOURCE/org-ssg.toml= and =SOURCE/templates/= — and
84neither is published. If you would rather keep the config elsewhere, name it:
85
86#+BEGIN_SRC sh
87org-ssg serve content -o _site --config config/org-ssg.toml
88#+END_SRC
89
90** A worked example
91
92A repository laid out as =content/= (org files), =theme/= (unrelated), =build.py=:
4593
4694#+BEGIN_SRC sh
47org-ssg audit ~/notes
95cd ~/my-site
96
97# What is actually in there, before trusting anything with it.
98org-ssg audit content
99
100# Build it somewhere disposable and look.
101org-ssg serve content -o /tmp/preview
102
103# Happy with it? Build for real, failing on broken links.
104org-ssg build content -o _site --strict
48105#+END_SRC
49106
50That reports which org constructs appear, how often, and whether each is supported. See
107The audit reports which org constructs appear, how often, and whether each is supported —
108names, counts and line numbers only, never your text. See
51109[[file:guide/09-auditing.org][Auditing a corpus]].
52110
111Nothing in your files has to change. With no config you get a complete site: a built-in
112layout, navigation across your top-level pages, and syntax highlighting.
113
53114* Write a page
54115
55116Any =.org= file under the source directory becomes a page at the matching path.