The public blog did not grow an admin. The console is a third tree: a Vite + Vue 3 app under /admin, served as static assets, with one Worker gate.
Readers still get static posts. Comments still go through the same two public endpoints. Public POST still publishes. The change they can notice is a comment disappearing after I hide or delete it.
What it is for
One operator. Overview numbers, a 30-day view/comment series, countries, posts, visitors, and every comment row — including hidden ones. Hide, restore, or delete. That is the proof the console is real.
Visitors are distinct session ids from comment_views. There is no session table.
What it is not
The dump (GET /api/admin/state) is a fetch, not the store. The SPA hydrates from a browser cache and only Refresh hits the Worker again. Emails are in that dump. They stay in IndexedDB on this machine until I clear the cache.
Cloudflare Access sits in front of /admin and /api/admin. The Worker still verifies the Access JWT. The public pe_session cookie is not operator identity.
No in-app agent. No reader flags. No hold-all. Those stay parked.
What did not change
Opening a post is still not a Worker request. The comment island still waits for the section and for consent. Search, a PWA, media uploads, and site-wide view counts stay named absences.
Comments
Comments load when this section is visible.
To load comments we set a first-party session cookie and record that you opened this section. Name and email stay in this browser after you post.