Pimp My IDE / garage dispatchBack to the garage
October 9, 2026 / static sites / deployment safety

Your repo is not your web root.

A static server cannot tell a public page from an internal note. It serves the files you place behind it.

Build a public directory, inspect the transfer list, and probe the plain production URL. Exclusion rules are backup brakes, not the steering wheel.
Manifest required

A static host shipped the project instead of the site.

A T-Minus Labs postmortem describes a 150 KB engineering handoff that returned HTTP 200 from a production domain. The file held an admin bypass string, an unfixed payment flaw, and internal database names. The build output directory was the repository root, so tracked notes and tool configuration became public files.[1]

The author removed the files and redeployed. A separate cache layer still served the old copy on the custom domain. Cache-busted requests reached the clean origin, but visitors using the plain URL could still fetch the cached file. The repair needed two parts: block the exposed paths at the edge, then fix the server-side payment flaw that made the leaked information useful.[1]

The release boundary is a directory, not an intention.

Make the public tree boring.

Do not publish a mixed project directory and hope a denylist catches every private file. Put the deployable site in a dedicated directory such as public/ or dist/. Generate that directory from known inputs. Keep notes, prompts, CI files, editor state, backups, credentials, and repository metadata outside it.

Then inspect the exact transfer list before promotion. Rsync can list one source without copying it. It also supports --exclude, --exclude-from, and --files-from. Those controls define what moves, but they do not repair a source directory that mixes public and private material.[2]

rsync -anv --itemize-changes \
  --exclude='.git/' --exclude='.gitignore' \
  public/ host:/var/www/example/

Do not make the web server guess.

Caddy's file server joins the request path to the configured site root. It can hide file names and patterns, but its documentation says hide should not be treated as a security boundary for sensitive paths. The same page warns that symbolic links inside the root can reach outside it.[3]

Use the smallest root that can serve the site. Keep server-side hides for defense in depth. Test metadata paths after every deployment. A production check should request /.git/HEAD, /.git/config, internal note names, source maps when they are not intended, and backup suffixes.

Verify the visitor's route.

A cache-busting query answers whether the origin is clean. It does not answer whether the ordinary URL is still exposed. Check both when diagnosing. Close the incident only after the plain URL fails, the origin route fails, and the sensitive mechanism has been removed or made harmless.

HTTP 404 is one witness. Add filesystem inventory, transfer hashes, and a clean deploy source. If an internal file ever reached the public tree, assume copies may remain. Rotate real credentials, remove client-side trust, and fix the underlying authorization flaw.

Interactive makeover / deploy checklist plus receipt

Build the customs bay.

This browser-local bench combines four release checks, a sample transfer manifest, a connected gate, and a copyable review receipt. It replaces a loose deployment checklist with one visible route. It does not run a deployment.

Build outputInspect manifestPublic web root

Release interlocks

Select only the checks your release process performs. The sample manifest changes when the dedicated public directory is selected.

Sample transfer listMixed root
  • index.htmlship
  • assets/app.cssship
  • HANDOFF.mdhold
  • .git/confighold
  • .claude/launch.jsonhold

Traditional purpose replaced: an informal pre-deploy checklist. Better version: the controls, route, sample inventory, verdict, and receipt share one state.

Release gate0 of 4 checks selected

Inspection record

Boundary not definedThe template still needs a dedicated public root, an inspected transfer list, production probes, and a plain-URL recheck.
Sources read / October 9, 2026

Source log

Open the evidence boundary
  1. T-Minus Labs, "My static site was serving my internal docs", published August 31, 2026. The post documents the public handoff file, repository-root build output, dotfile behavior on that host, separate cache layers, plain versus cache-busted verification, the edge block, and the server-side repair. Hacker News item 49994449 was verified through the official API and used as the discovery route.
  2. Rsync manual, read October 10, 2026 UTC. It documents list-only behavior when one source has no destination, include and exclude controls, --files-from, remote-shell transport, and source trailing-slash behavior.
  3. Caddy documentation, file_server, read October 10, 2026 UTC. It documents request-path resolution against the site root, symbolic-link limits, hide, and the warning that hides are not a security boundary for sensitive paths.

Scope boundary: this dispatch draws a deployment pattern from one closed incident and two official manuals. The interactive customs bay is a teaching tool. Its selected state means the template structure is ready for evidence. It does not inspect a host or certify a deployment.