- ConnNote.vue: a status strip for the WebSocket-backed panels (page and
banner editors, analytics view) — "connecting…" while the socket is
pending (the staggered slot included), "reconnecting in ~N s…" during
backoff, hidden once open. A pending/lost socket no longer reads as a
silently empty or stale panel.
- PageEditor/BannerEditor: CodeMirror stays non-editable until the
page/banner doc has been accepted — typing before it would be clobbered
by the accept. A mere disconnect keeps the editor live: text stashes
and pending saves flush on reconnect.
- LangSelect.vue: one language selector for the page and structure tabs
(small flag, clean dropdown), v-modeled on the shell-wide editorLang —
switching in either panel switches both AND the page preview. While the
panel is open the selection overrides the normal language preferences
(swapdoc.setLangOverride: loadPlain and pagerite.js fetches/prefetches
pin ?lang=, the primary language by its own code); closing restores.
- reconnect.js: every socket (page/banner editors, analytics view, the
activity channel) now connects through a staggered slot — simultaneous
attempts at page load (Vite's HMR socket plus ours, repeated on every
refresh) trip the browser's WebSocket throttling, leaving all sockets
to the host "pending" for minutes, which was the recurring empty
editor. A watchdog closes sockets stuck CONNECTING so they reschedule
through the policy (jittered exponential backoff, reset only by a
healthy connection) instead of hanging forever; a reconnected editor
re-opens its document when the previous open died with its socket.
popstate always passed back=true, so going forward after back still
rotated the cube backwards. Track an incrementing idx in history.state
and only mirror the transition when the target entry is actually behind;
replaceState calls now preserve the state object instead of wiping it.
The first positional CLI argument (default localhost) names the site's
public hostname and its data directory under the cwd, replacing the
CWD-relative pagerite.* files. The public origin (https://<hostname>)
is now authoritative configuration instead of a value learned from
admin browsers: POST /_api/site-url, Data.site_url and the pagerite.js
reporter are removed, and page rendering, sitemap, robots.txt and
analytics own_origin all use SITE_URL consistently (localhost falls
back to the request's base URL).
Document GETs now stash their status (200/404) in a pending table,
consumed by the matching ping: visits gain a per-path statuses map and
crawler hits a status field. Trail links with a 404 status render in
red with the status code in the tooltip, alongside the read time.
- Charts grow to a larger intrinsic size (1052x174) and never upscale
past it; centered with equal side margins above the cap, full width
below, svg always within page bounds; overflow visible so wider fonts
don't clip at the viewBox edge
- Totals row aligns its left edge with the charts and shrinks (gap first,
then font) via container units to always stay on one line
- Unified chart text at 11px system-ui; fixed size independent of theme font
- Day view y axis reads "visits / 5 min" / "views / 5 min"
- Left margin and y tick spacing tightened (MARGIN_L 56 -> 40)
- Gap between visits and views charts removed
- Legend repositioned for the larger font
- keep visitor charts y-axis minimum range at 10
- keep 'all' chart x-axis minimum span at 30 days
- group crawler hits by (ip, ua) and list top pages visited, show crawler page load counts as N× prefix
- store and display geoip city, keep geoip country overwrite
- stream live updates over WebSocket /_api/ws/analytics
- include family ring arcs in transition map crop bounds
- remove top UA summary, limit crawlers to 10 and visits to 20
- human-readable relative timestamps with UTC tooltip
Add server-side visit analytics collection, a public-page ping endpoint,
and a full-screen AnalyticsView for admins.
Backend:
- Add pagerite/analytics.py: Analytics/Visit model, Store, and persistence
- Wire /_a ping endpoint and GET /_api/analytics into pagerite/app.py
Frontend:
- Add full-screen AnalyticsView with visitor charts and transition map
- Add VisitorCharts and TransitionGraph subcomponents
- Add analytics JS helpers in frontend/src/analytics/
- Send navigation pings from frontend/src/pagerite.js
- Mount AnalyticsView from frontend/src/main.js
- Document the feature in docs/analytics.md and update AGENTS.md