public-tools.hjc925.cloud does two jobs. It lists tools that Herman recommends. It also runs the tools that we operate. Most entries in the list are links to other people’s tools. A few are ours. Each of ours has a public page that anyone can read and an admin panel that only Herman can reach.

The path convention

Every tool uses the same four paths. A new tool follows the same shape.
The admin path and the API path use different authentication. The admin path uses a human login with a session cookie. The API path uses the credential that the tool’s client holds. Both run inside the same process. Do not treat them as one.

Why paths and not subdomains

A subdomain for each tool needs a DNS record, a Caddy block, a certificate and a service unit. Each one is a separate door under the Gate 8 parity rule. A path needs one line in the Caddyfile.
A webpage-review.hjc925.cloud subdomain was considered and cancelled. If a second tool arrives, it gets a path under public-tools, not a subdomain.

One gateway owns authentication

One Node service holds the login for every tool. Each tool is a router inside it. There is one users.json, one login page and one session cookie. The reason is narrow. On a single host a cookie belongs to the host, not to the path. A cookie set at /webpage-review/admin is readable by anything on public-tools.hjc925.cloud. Separate credential stores would look isolated and would share the only boundary that the browser enforces. Authorization stays separate. Each user row carries a flag for each tool. A person can log in and still have no access to a given panel.

The Caddy split

Caddy serves every static file from disk. The gateway receives only /<tool>/admin* and /<tool>/api*.
The reason is availability. The public page is the page a client reads when something already goes wrong. The gateway can crash or restart and that page stays up.

Where things live

The service is a systemd user unit. systemctl is-active public-tools reports inactive and finds no unit. Use systemctl --user, with XDG_RUNTIME_DIR=/run/user/1000 set over SSH.