krz/orgo
Lightning fast org-mode static site generator.
clone: git clone https://gitbay.org/krz/orgo.git
v0.22.0: docs/guide/08-workflow.org · raw
1#+TITLE: Watching and serving
2#+DESCRIPTION: The write-save-see loop, and what the development server does and does not do.
3#+LEDE: Filesystem events, debounced rebuilds, and a browser that reloads itself.
4
5* serve
6
7#+BEGIN_SRC sh
8orgo serve content -o _site
9#+END_SRC
10
11Builds, watches, serves at [[http://127.0.0.1:3000][127.0.0.1:3000]], and reloads the
12browser when a rebuild lands. This is the command to leave running while you write.
13
14Add =--drafts= to see work in progress, =--port= to move it, and =--host 0.0.0.0= to
15reach it from another device.
16
17** It binds loopback deliberately
18
19A development server serves unreviewed drafts off your laptop. Exposing that to whatever
20network you are on — a café, a conference, an office — should be something you ask for,
21so the default is =127.0.0.1= and =--host= is the way out.
22
23** The reload script never reaches disk
24
25The script is injected into HTML *responses*, not into the built files. What you deploy
26is the site as built, with no development machinery in it. If you are curious, compare a
27served page with the file in your output directory.
28
29** How reload works
30
31The page carries the build generation it was rendered from, and asks the server "anything
32newer than N?". The server holds that request open until there is, then answers — so a
33reload is immediate rather than polled, but the mechanism is ordinary HTTP with no
34WebSocket.
35
36Baking the generation into the page closes a race: if a rebuild lands between a page
37being served and its first request going out, the server answers at once instead of the
38tab sitting on stale content until your *next* edit.
39
40A reload only follows a *successful* rebuild. Reloading onto an unchanged page because
41the build just failed tells you nothing — the error is already on your terminal.
42
43* watch
44
45#+BEGIN_SRC sh
46orgo watch content -o _site
47#+END_SRC
48
49The same rebuilding without the server, for when something else already serves the output.
50
51* What counts as a change
52
53Rebuilds are driven by OS filesystem events, so nothing happens while nothing happens.
54The rule for what triggers one is deliberately *not* the rule the build uses to find
55content — the question is "would this change the site?", not "is this a page?".
56
57*Triggers a rebuild:* any =.org= file, any asset, =orgo.toml=, and anything in the
58templates directory. The last two are skipped by the build when looking for content, but
59both change the output.
60
61*Does not:*
62
63- The output directory. Without this the build's own writes would raise events that
64 trigger a rebuild, forever.
65- Dot-directories. =.git= churns on every command, and rebuilding a site because git
66 wrote an index lock would make watching useless in a repository.
67- Editor scratch files: =file.org~=, =#file.org#=, =.#file.org=, =*.swp=, =*.tmp=. Emacs'
68 backup files matter here — they do not start with a dot, so they would otherwise look
69 exactly like content.
70
71* Debouncing
72
73Saving a file is rarely one event: an editor writes a temp file, renames it over the
74original, and touches the directory. Events are collected for 120ms of quiet before a
75rebuild starts, so one save is one rebuild.
76
77* Rebuild failures do not stop the session
78
79A build that fails prints the error and keeps watching. The usual cause is a half-saved
80file, and the next keystroke fixes it. Nothing needs restarting.
81
82#+BEGIN_EXAMPLE
83blog/post.org changed: build failed: parsing blog/post.org: ...
84blog/post.org changed: 2 rendered, 180 cached
85#+END_EXAMPLE
86
87* Where native watching is unavailable
88
89Some network and container filesystems have no event API. orgo falls back to polling
90every two seconds and says so, rather than failing:
91
92#+BEGIN_EXAMPLE
93note: native file watching unavailable (...); polling every 2s
94#+END_EXAMPLE
95
96* Serving details
97
98- =/= and any directory URL serve =index.html=.
99- Content types are set by extension; unknown extensions are served as binary.
100- Everything is sent =Cache-Control: no-store=, because a cached dev response makes an
101 edit look like it did not land.
102- URL resolution refuses to leave the output directory. =..=, percent-encoded =..=,
103 backslashes, absolute paths and embedded NULs all resolve to nothing.
104
105* A typical session
106
107#+BEGIN_SRC sh
108# One terminal, left running.
109orgo serve content -o _site --drafts
110
111# Write. The browser keeps up.
112
113# Before publishing, check what a real build says.
114orgo build content -o _site --strict
115#+END_SRC