Statac

Start

Serving a site while you write

statac serve shows your site on this computer while you write, and builds it again each time you save.

Start it

statac serve
3 notes: 3 no-site-address. Run `statac check` to see them.

Wrote 17 pages and 66 other files to `.statac/serve` in 0.15 seconds.
Serving `.statac/serve` at http://localhost:3000/
Press Ctrl+C to stop.

Open the address. Serve builds the site first, counting warnings and notes as statac build does.

It works from any folder inside the site. For a site elsewhere, name its folder: statac serve docs.

When you save

`content/posts/first-post/index.md` changed. Built 4 of 17 files in 0.08 seconds. Browser told to reload.
`assets/site.css` changed. Built 17 of 17 files in 0.08 seconds. Browser told to swap 1 stylesheet.

A save builds only what the change touches. The count is of pages: the post touched 4 of 17, the stylesheet all of them.

Open pages then reload. A save that changes only a stylesheet swaps it in, so what you had scrolled to or typed stays put.

Serve doesn’t watch files and folders whose names start with a dot, or a folder Statac built, such as _site.

What serve writes into your files

`content/posts/post-1.md` changed. Built 6 of 20 files in 0.02 seconds. Browser told to reload.
Stamped `content/posts/post-1.md`: `date` is `2026-10-09`.
Gone since the last build: 1 unclear-date.

Where front matter holds a stamp, such as date: =today, serve writes the date over it before each build. Stamped follows Built though the stamp came first. Here it replaced a date that had stopped the build.

Wrote an `id` into `content/post-1.md`.

Where the site sets write_feed_ids: true, serve gives an id: line to each post in a feed that hasn’t been published yet.

Serve’s own writing to a file is not taken for a save.

When something is wrong

`content/posts/post-1.md` changed. Built 3 of 20 files in 0.11 seconds. Browser told to reload.

warning  Broken link: nothing is published at `/post-9/`
  content/posts/post-1.md, line 5
   5 │ Read [Post 9](/post-9/).
     │               ^^^^^^^^
  Did you mean `/posts/`?
  More: https://statac.dev/e/broken-link/

Serve shows in full each problem new since the last build, and counts the ones that have gone:

`content/posts/post-1.md` changed. Built 3 of 20 files in 0.02 seconds. Browser told to reload.
Gone since the last build: 1 broken-link.

An error stops the build, and the browser keeps the pages as last built:

`content/posts/post-1.md` changed. 1 error stopped the build. The browser keeps the pages as last built.

error  Unclear date: `4/10/2026` could be 4 October or 10 April
  content/posts/post-1.md, line 3
   3 │ date: 4/10/2026
     │       ^^^^^^^^^
  Write it as `2026-10-04` or `2026-04-10`.
  More: https://statac.dev/e/unclear-date/

The panel says so too. Save the fixed file and the pages load again.

Drafts and posts waiting for their day

Wrote 20 pages and 66 other files to `.statac/serve` in 0.08 seconds.
Showing 1 draft and 1 post waiting for its day, which `statac build` leaves out.
Serving `.statac/serve` at http://localhost:3000/

Serve shows what a build leaves out: pages marked draft: true and posts dated after today. The panel marks each one. To see exactly what statac build would publish:

statac serve --no-drafts

A serve left running past midnight notices the new day at the next save.

The panel

Statac  Built at 14:02:07. 1 warning. Draft.

Every page serve answers carries this line at its foot: when the site was last built, how many problems it has, and whether the page is a draft or waiting for its day.

When an error stops the build, the line turns red and gives the first error:

Statac  Build stopped. Unclear date: `4/10/2026` could be 4 October or 10 April  content/posts/post-1.md, line 3  Write it as `2026-10-04` or `2026-04-10`.

Show details, beside the line, opens the panel:

Part What it shows
What stopped the build When, and each error as statac check draws it.
This page Whether it is a draft, or waiting and for which day; the problems in its own file.
Where this page comes from Its file and address; its layout and what chose it; the lists it is in, with its place in each; the feeds that carry it.
What a template can show here Every name a template can write on this page.
The site Its problems counted by kind; links to every draft and every post waiting for its day.
Written into your files The stamps and ids the last save wrote.

Tab reaches the button, Enter or Space presses it, and Escape closes the panel.

What can a template show here?

Write             Holds   On this page          Written at
page.title        text    Post 1                content/post-1.md, line 2
page.date         date    4 October 2026        content/post-1.md, line 3
                          Also .day .month .weekday .year
page.summary      text    no value
page.book         fields  the fields beneath
page.book.author  text    Author 1              content/post-1.md, line 6
site.posts        pages   12 pages

The panel has a table for page, one for site, and one for site.data where the site has a data/ folder.

Column What it says
Write The name as a template writes it, ready to copy.
Holds The kind of thing it gives: text, a number, a date, a page, a list.
On this page What {{ page.title }} would put on the page, cut short where long. A list is counted. no value means nothing is behind the name on this page.
Written at The file and line the value comes from.

A name that can’t follow a dot is written in brackets, as site.data.words["en-GB"].

Fetching as it starts

Fetching what's new from other sites. `--offline` turns this off.
Press Ctrl+C to stop.
Fetched `fetched/stills/youtube-abcdefghijk.jpg`.
Fetched 1 still.
`fetched/record` and `fetched/stills/youtube-abcdefghijk.jpg` changed. Built 1 of 4 files in 0.02 seconds. Browser told to reload.

After its first build with no errors, serve fetches once what statac refresh would: a still for each video that has none and, where the site has webmentions on, new mentions. This is the only time serve uses the network.

Serve doesn’t wait: it answers and builds your saves meanwhile, and builds each thing as it arrives. Commit what arrives in fetched/ with the site.

A video added while serve runs gets its still when serve next starts, or from statac refresh.

To fetch nothing:

statac serve --offline
Offline: nothing is fetched from other sites.

Your own commands under serve

Command Under serve, it runs
before_build Before the first build. Then again whenever a save touches a file or folder that before_build_watches names.
after_build Once, on the served folder, after the first build with no errors. Never on a save.

Your own commands run less often than under a build. In statac.yaml:

before_build: ./styles.sh
before_build_watches: [styles/]
Ran `before_build`: it runs again when a file `before_build_watches` names changes.
`styles/site.scss` changed. Built 4 of 4 files in 0.12 seconds. Browser told to reload.
Ran `before_build`.

Ran follows Built though the command ran first. What the command writes is built in the same round, and isn’t taken for a save. With no before_build_watches:

Ran `before_build` once, before the first build.

What after_build adds stays through later saves, and goes stale until serve is started again:

Ran `after_build`, which added 12 files and changed 1.
`after_build` ran once: what it made stays as it is until serve is started again.

Where the first build stopped at an error, the command waits:

`after_build` runs once, after the first build with no errors.

Warning:

A command is told that serve is running it: STATAC_SERVE is yes. A command that publishes the site should do nothing then, or starting serve publishes the preview, drafts and all.

A command that stops under serve stops that round. The next save tries again.

What is served, and where

What Under serve
The built site Built as statac build builds it, but into .statac/serve in the site’s folder.
_site Never written.
What the files hold Byte for byte what statac build --drafts writes, or what statac build writes when serve runs with --no-drafts.
The panel, and the script that waits to hear of a save Added to each page as it is sent to the browser, never written into a file.
Who can reach it This computer only. Serve listens on localhost, and refuses a request under any name but localhost, 127.0.0.1 or [::1] with its own port, so a page on another site can’t read yours through your browser.
A site whose url has a path Served under that path: https://example.org/blog/ at http://localhost:3000/blog/.
An address with nothing published at it The site’s own 404.html, or a plain page of Statac’s.

Options

Option What it does
--port=<number> The port serve answers on: 3000 unless you say.
--watch=<way> How serve learns of a save: native, poll or auto, which it uses unless you say.
--site=<folder> The site’s folder, the same as naming it after the command.
--today=<date> The day the site is built on, as statac build takes it.
--no-drafts Leaves drafts and posts dated after today out, as a build does.
--offline Fetches nothing from other sites.

Where another program is using the port, serve tries the ten after it and takes the first that is free:

Port 3000 is in use: serving on port 3001 instead.

Serve takes no --url.

Watching for saves

Way How serve learns of a save
native The system reports each change.
poll Serve looks at every file in the site’s folder twice a second. It works on every disk.
auto native, except on a disk that may not report changes, such as a network share or a folder shared with a virtual machine, where serve polls.
Watching by polling every 500 ms: the folder is on a `smbfs` disk, which may not report changes.

Whenever serve polls, it says so and why.

Note:

If saves aren’t noticed, run statac serve --watch=poll.

Where next?

Something unclear or wrong? Open an issue on GitHub.