docs/content/deploy/_index.md (5140B)
1 +++
2 title = "Deploying"
3 description = "A directory of files, and the hosts that will serve it"
4 toc = true
5 weight = 50
6 sort_by = "weight"
7 +++
8
9 ```bash
10 sqzass build -i mysite
11 ```
12
13 `mysite/public` is the site. Copy it somewhere that serves files and you are
14 done — there is no runtime, no server component and no build step left to run.
15
16 ## What sqzass does so the host does not have to
17
18 Every URL is a directory containing `index.html`, so pretty URLs need no
19 rewrite rules. Cache busting is in the filename, so it needs no cache headers.
20 Nothing in the output depends on host configuration.
21
22 This is deliberate, and the docs site is hosted on
23 [GitHub Pages](@/deploy/github-pages.md) to keep it honest: Pages offers no
24 custom headers, no redirect rules and no rewrites, so anything that needed them
25 would break here first.
26
27 The payoff is that moving hosts is a copy. The same directory is correct on
28 Cloudflare Pages, Netlify, S3 behind CloudFront, or nginx.
29
30 ## What else is written
31
32 `sitemap.xml` lists every page, with `<xhtml:link>` alternates for pages that
33 exist in more than one language — which is the form Google asks for when a site
34 is bilingual. `robots.txt` allows everything and points at the sitemap.
35
36 Neither carries `priority` or `changefreq`, because Google confirmed in 2023
37 that it ignores both. Neither carries `lastmod` either, and that one is a
38 choice: the honest sources for it are all unreliable here. A file's mtime is
39 its checkout time, so in CI every page would claim to have changed this
40 morning, and it would break the guarantee that two builds produce the same
41 bytes. Git commit times are accurate but need full history, and
42 `actions/checkout` clones shallow by default — so it would quietly stamp every
43 page with the same date. Google ignores a site's `lastmod` entirely once it
44 finds it untrustworthy, which makes a wrong one worse than none.
45
46 `llms.txt` is a flat list of every page — title, URL and description — in the
47 [format proposed at llmstxt.org](https://llmstxt.org). A language model asked
48 about your site can read one file instead of crawling the whole thing. It costs
49 nothing to emit because the title, URL and description already exist.
50
51 Put your own `sitemap.xml`, `robots.txt` or `llms.txt` in `static/` and sqzass will not
52 generate that file at all. It does not overwrite yours, and it does not
53 silently ignore it either.
54
55 ## Where these guides go
56
57 Every one of them is the same two facts: run `sqzass build`, publish `public/`.
58 The pages differ only in where those facts are written down and what each host
59 calls its preview URL.
60
61 ## Sites served under a path
62
63 `https://user.github.io/repo`, `https://group.gitlab.io/project` and
64 `https://user.codeberg.page/repo` are all project sites, and all of them serve
65 your output under a path rather than at a domain root. Put the whole thing in
66 `base_url`:
67
68 ```toml
69 base_url = "https://user.github.io/repo"
70 ```
71
72 sqzass then prefixes every URL it generates — page links, stylesheet hrefs, the
73 search index — while the output directory stays flat, because that directory is
74 the root the host serves.
75
76 Leaving the path out is the one mistake here that is silent. The build succeeds,
77 the pages are all there, and every link and stylesheet resolves one level too
78 high.
79
80 ## static/ is a passthrough
81
82 Anything in `static/` lands in the output with its path and name intact, which
83 is how host-specific files work without sqzass knowing about any host:
84
85 | | |
86 |---|---|
87 | `CNAME` | GitHub Pages custom domain |
88 | `.domains` | Codeberg Pages custom domain |
89 | `_headers`, `_redirects` | Netlify, Cloudflare Pages |
90 | `.well-known/*` | Domain verification, `security.txt` |
91
92 Only CSS and JavaScript get a content hash. A name that is the contract keeps
93 its name.
94
95 ## Two files worth knowing about
96
97 `.nojekyll` is written into every build. Without it GitHub Pages runs the
98 output through Jekyll, which swallows directories beginning with `_`.
99
100 `CNAME`, if you need one, goes in `static/` and is copied through with its name
101 intact — a hashed `CNAME` is a file GitHub will never look for.
102
103 ## What a build emits
104
105 The complete list, so that "moving hosts is a copy" is something you can check
106 rather than take on trust:
107
108 | | |
109 |---|---|
110 | everything in `static/` | paths and names intact; CSS and JS get a content hash |
111 | `assets/highlight.<hash>.css` | unless `[highlight] enabled = false` |
112 | `asset-manifest.json` | logical name → written URL, always |
113 | `<path>/index.html` | one per page |
114 | `search-<lang>.json` | one per language, unless `[search] enabled = false` |
115 | `feed-<lang>.xml` | one per language that has a dated page |
116 | `sitemap.xml`, `robots.txt` | unless `static/` supplied one with that name |
117 | `llms.txt` | same terms |
118 | `404.html` | when `templates/404.html` exists |
119 | alias stubs | one per `aliases` entry |
120 | `.nojekyll` | always, and it wins over a `static/.nojekyll` |
121
122 Nothing else, and nothing outside the output directory.
123
124 ## Determinism
125
126 Two builds of the same input produce byte-identical output. That makes the
127 build safe to run in CI as a check, and it means a deploy that changes nothing
128 uploads nothing.