krz/orgo
Lightning fast org-mode static site generator.
clone: git clone https://gitbay.org/krz/orgo.git
v0.19.1: docs/guide/10-deploying.org · raw
1#+TITLE: Deploying
2#+DESCRIPTION: Producing a production build, and putting it somewhere.
3#+LEDE: The output is a directory of files. Everything after that is your host's problem.
4
5* The production build
6
7#+BEGIN_SRC sh
8orgo build content -o _site --strict
9#+END_SRC
10
11Two differences from the build you run while writing:
12
13- =--strict= turns broken internal links and parse diagnostics into a non-zero exit, so a
14 bad build fails rather than shipping.
15- No =--drafts=, so pages marked =#+DRAFT:= stay out.
16
17Everything in =_site= is the site: HTML, the generated =syntax.css=, and every asset
18copied from the source. There is no runtime, no server requirement and no build step
19downstream.
20
21* Set base_url for production
22
23#+BEGIN_SRC toml
24[site]
25base_url = "https://example.com"
26#+END_SRC
27
28Relative URLs work anywhere, which is why the default is empty — but two things need
29absolute ones: *feeds*, because a feed is read away from the site that served it, and
30*canonical links*. Without a base URL the =absolute= filter is an error rather than a
31quietly relative link, so a feed template will tell you.
32
33No trailing slash.
34
35* One thing to exclude
36
37The build writes =.orgo-cache.json= into the output directory. It is a dot-file, so
38most static hosts ignore it, but it is not part of the site — exclude it if your host
39uploads everything:
40
41#+BEGIN_SRC sh
42rsync -a --delete --exclude '.orgo-cache.json' _site/ user@host:/var/www/site/
43#+END_SRC
44
45Keeping the cache *between* deploys, where the CI runner can see it, is what makes CI
46builds incremental. Keeping it on the *server* achieves nothing.
47
48* Continuous integration
49
50#+BEGIN_SRC yaml
51name: build
52on: [push]
53jobs:
54 build:
55 runs-on: ubuntu-latest
56 steps:
57 - uses: actions/checkout@v4
58 - uses: dtolnay/rust-toolchain@stable
59 - run: cargo install --path .
60 - run: orgo build content -o _site --strict
61 - uses: actions/upload-artifact@v4
62 with:
63 name: site
64 path: _site
65#+END_SRC
66
67=--strict= is the point of running this in CI at all: it turns a broken link into a
68failed build.
69
70** Caching between runs
71
72Cache =_site/.orgo-cache.json= *and* =_site= together, or not at all. The manifest
73describes files it expects to find; a cache without its outputs simply triggers a full
74rebuild, which is correct but pointless.
75
76Given how fast a full build is — a 179-page site in well under a second — caching CI
77builds is rarely worth the configuration.
78
79* Static hosts
80
81Nothing here is orgo-specific; a built site is ordinary static files.
82
83- *Netlify, Vercel, Cloudflare Pages*: publish directory =_site=, build command
84 =cargo install --path . && orgo build content -o _site --strict=.
85- *GitHub Pages*: upload =_site= as the Pages artifact.
86- *Any web server*: copy =_site= to the document root.
87
88** URLs end in .html
89
90orgo writes =blog/post.html= and links to it that way, so the site works with no
91server configuration at all — including opening it from a filesystem path.
92
93If you prefer extensionless URLs, that is a server-side rewrite, and you should also set
94=base_url= and check that your rewrite rules do not break the relative links in the pages.
95
96* Checking a build before shipping
97
98#+BEGIN_SRC sh
99orgo build content -o _site --strict
100orgo serve content -o _site
101#+END_SRC
102
103Serving the production build locally is the last check worth doing: it catches a missing
104asset or a broken relative link in the browser, where you would notice.
105
106* What a clean build looks like
107
108#+BEGIN_EXAMPLE
109built 182 page(s) (182 rendered, 0 cached), copied 3 asset(s) from content -> _site (0 unresolved link(s), 0 diagnostic(s))
110#+END_EXAMPLE
111
112Both zeros matter. Unresolved links are internal links pointing at nothing; diagnostics
113are malformed org that degraded rather than failing. With =--strict= neither can reach
114this line, because either would have failed the build.
115
116* After an upgrade
117
118The first build on a new version is worth running with =--no-cache=, so you compare the
119new output to the old rather than to a cache written by both. What a version number
120promises — and what it does not — is in [[file:11-versioning.org][Versioning and
121upgrades]].