core: static sites serve a nested directory's index.html

`try_files {path} {path}/index.html /index.html` for SPA sites and the
dashboard: a URL like /docs/setup/ serves that directory's own index.html
before falling back to the root one, so a multi-page static site works at its
sub-paths while single-page apps still get client-side routing.

Found uncommitted in the checkout, author unknown, and already live: wildpc
runs from this tree, so every Caddyfile generated since used it.
This commit is contained in:
2026-10-23 15:19:33 -07:00
parent 959a896115
commit c6c361e38a
3 changed files with 15 additions and 11 deletions

View File

@@ -261,12 +261,15 @@ def _host_remote_block(label: str, host: str, target: str) -> list[str]:
def _static_serve_lines(serve_dir: str, spa: bool, indent: str) -> list[str]:
"""The `root`/`file_server` body for a static site. SPA sites get a fallback to
the root `index.html` (client-side routing); content sites (Hugo) get plain
`file_server`, which resolves directory indexes and 404s missing paths."""
"""The `root`/`file_server` body for a static site. SPA sites try a nested
directory index (`{path}/index.html`) before falling back to the root
`index.html` (client-side routing) — so a multi-page static site keeps working
at `/sub/dir/` URLs while single-page apps still resolve deep routes. Content
sites (Hugo) get plain `file_server`, which resolves directory indexes and
404s missing paths."""
lines = [f"{indent}root * {serve_dir}"]
if spa:
lines.append(indent + "try_files {path} /index.html")
lines.append(indent + "try_files {path} {path}/index.html /index.html")
lines.append(f"{indent}file_server")
return lines
@@ -456,7 +459,7 @@ def generate_caddyfile_from_registry(
lines += [
" handle {",
f" root * {root}",
" try_files {path} /index.html",
" try_files {path} {path}/index.html /index.html",
" file_server",
" }",
"}",

View File

@@ -145,7 +145,7 @@ class TestAcmeMode:
cf = generate_caddyfile_from_registry(_acme({}))
assert "@host_wildpc host wildpc.example.com" in cf
assert "root * /data/repos/wildpc/app/dist" in cf
assert "try_files {path} /index.html" in cf
assert "try_files {path} {path}/index.html /index.html" in cf
assert "file_server" in cf