Appearance
Password protection
Put a password in front of any deployed project — handy for staging sites, client previews, or anything that shouldn't be public yet. Visitors get a branded APCO password page — there's no username, just the password.
How it works
- The password you set is hashed with bcrypt — the platform stores only the hash, never the plaintext (passwords are limited to 72 characters, bcrypt's maximum).
- Enforcement happens at the edge: the router (Caddy) serves the password page for every request to your site (HTTP 401) before it reaches your app or static files.
- On a correct password, the platform sets a session cookie (
apco_site_auth— host-only,HttpOnly,Secure,SameSite=Lax, 7-day expiry) and redirects the visitor back to the page they originally asked for. They won't be asked again until the cookie expires, or the password changes. - Changing or clearing the password immediately invalidates every existing visitor session — the cookie's token is derived from the password hash, so old cookies stop working the moment the password does.
Protection covers the whole site — every path, and the dev channel host (dev-<slug>.apco.space) and preview hosts as well. /_apco/password is a reserved path used by the password page itself; avoid routing your own app to it.
Setting a password
Dashboard: open your project → settings → Password protection, enter a password, save. Clearing the field removes protection.
API: PATCH /api/v1/projects/:id with a projects:write key:
bash
# protect
curl -X PATCH https://apco.space/api/v1/projects/<id> \
-H "x-api-key: $APCO_TOKEN" \
-H "content-type: application/json" \
-d '{"password": "hunter2-but-better"}'
# remove protection
curl -X PATCH https://apco.space/api/v1/projects/<id> \
-H "x-api-key: $APCO_TOKEN" \
-H "content-type: application/json" \
-d '{"password": null}'MCP: AI agents can use the set_password / clear_password tools — see the MCP server.
Changes apply within moments — the platform rebuilds the project's route as soon as the password is set or cleared, no redeploy needed. Because the session cookie is tied to the password hash, this also signs out everyone who was already in.
It survives everything
The password is part of the project, not the deployment. It stays in place through:
- redeploys and rollbacks,
- stop/start cycles,
- slug renames,
- platform restarts (routes are reconciled at boot).
apco projects list shows a passwordProtected flag per project, so you can always see which sites are locked (the password itself is never returned by any API).
json
{ "slug": "docs", "url": "https://docs.apco.space", "passwordProtected": true }Accessing a protected site
Visitors get a dark-themed password page and enter the password — no username, no browser-native prompt. Once submitted, the platform sets the apco_site_auth session cookie and redirects them to the page they wanted. A wrong attempt sends them back to the form (you may briefly see ?apco_error=1 in the URL).
Not a substitute for app-level auth
Password protection is great for keeping previews private. For real user accounts, sessions, or per-user permissions, implement authentication inside your app.