Sol-37 Manual / Machine State / 2026-04-17

Site Server Manual

Sol-37 is a static public archive with a live service spine. Visitors mostly see a Windows 95 style shell, but the real system includes Caddy routing, GUI share metadata injection, IRC-backed logbook transport, a semantic retrieval API, a local model-backed chat API, a public AI dashboard with access gating, streamed voice playback, metrics generation, and media watchers.

Local Origin 127.0.0.1:8888
Public Host sol.system42.one
Site Root random/www
Operating Mode Static + Daemons

Read this page as a systems manual, not marketing copy. Sol-37 works because the static tree, generated state, and local services are all treated as first-class parts of the product.

Visible Surfaces

  • / for the retro desktop shell
  • /gui for direct shared-window entry
  • /chat for the dedicated Sol console
  • /dashboard for the AI dashboard app
  • /sitemap.html for archive browsing
  • /site-metrics.html for traffic and telemetry
  • /programs/logbook.html for the public logbook
  • /programs/media-player.html for media playback

Core Services

  • caddy-sol37.service
  • sol-chat-api.service
  • sol-chat-model.service
  • local-dashboard-api.service
  • dashboard-access-daemon.service
  • knowledge-query-api.service
  • sol37-gui-share.service
  • public-logbook-api.service
  • public-logbook-irc-logger.service

Generated State

  • site-index.json
  • knowledge-index.json
  • site-metrics.json
  • audio/playlist.json
  • video/playlist.json
  • assets/share-previews/

Shell Architecture

index.html is a single-file shell app acting as a lightweight window manager. It owns desktop icons, Start menu state, taskbar state, program registration, shared-window launch behavior, and the floating desktop assistant.

The benefit is deployment simplicity. The cost is that a large amount of interaction logic remains centralized in one document.

Program Layer

Pages embedded inside the shell are not just static documents. The site map, media player, logbook, star map, DOSBox surface, and dedicated chat client each bring their own interaction model while still being launched by the shell.

HTTP Topology

Caddy on :8888 is the local origin and the route switchboard.

/api/logbook/* -> 127.0.0.1:8890 /api/knowledge/* -> 127.0.0.1:8892 /api/chat/* -> 127.0.0.1:8895 /api/dashboard/* -> 127.0.0.1:8896 /api/dashboard-access/* -> 127.0.0.1:8897 /gui -> 127.0.0.1:8893 /chat -> /chat/index.html /dashboard -> /dashboard/index.html *.md routes -> 127.0.0.1:8894 markdown bridge

/chat, /dashboard, and their access-state routes are explicitly marked no-store. That is a real production safeguard against stale interactive clients, not a cosmetic header.

Publishing Path

The public host is exposed through Cloudflare tunnel infrastructure, but the site should still be reasoned about as a local-first system. The shell, APIs, and generated state all originate on this machine and are merely published outward.

Audio and image cache headers are intentionally different from chat headers. Media should cache. Chat clients should not.

The dashboard is also intentionally split between public publication and local control. A dedicated access daemon keeps local and LAN use always on, while public internet access can be enabled or disabled without taking the page off the desktop shell.

Runtime-wise, the dashboard now behaves more like a small operations surface than a static viewer: the camera feed tracks live viewers with stale-stream expiry, supports a dismissible caption overlay plus fit/fill/fullscreen controls, routes its shared comments through a private IRC-backed lane, and can emit public push milestone announcements from live server metrics without re-firing low-end milestones on every small viewer dip. The page no longer renders its own visible orb; voice stays on a hidden audio lane so the main desktop shell remains the only visible assistant surface. Captioning also depends on the fast vision backend, so the camera stream can be healthy while captions are briefly unavailable during backend warmup.

Assistant Surfaces

There are two real assistant clients:

  • the floating desktop assistant inside index.html
  • the dedicated public chat client in /chat

They now share the same broad runtime model: same-origin chat API, SSE text streaming, optional voice playback, retrieval grounding, and persistent session identity.

They also share the same actual backend path: /api/chat* proxies to sol_chat_api.py on 127.0.0.1:8895, which in turn uses the local model service.

The transport is no longer identical across surfaces. /chat remains SSE-first, while the floating assistant now prefers one-shot JSON for page-grounded summary turns and keeps SSE for freeform turns.

Assistant State

The floating desktop assistant now remembers whether it was explicitly closed. Shared GUI links still default to hiding the assistant unless assistant=1 is present, but manual close/open state is tracked separately in local storage.

Chat Flow

Browser -> POST /api/chat { stream, session, message, page_context? } -> Caddy -> sol_chat_api.py -> retrieval via /api/knowledge -> local model backend on 127.0.0.1:18080 -> SSE events or JSON final reply -> browser transcript updates incrementally or at completion

The dedicated chat client still uses SSE deltas. The floating assistant now prefers non-stream JSON when it already has grounded page context, and it retries without stream if a streamed turn yields no usable reply.

Page Context

The desktop assistant distinguishes between two context shapes:

  • compact page context for prompt grounding and suggestion generation
  • full extracted page text for read-aloud behavior

This matters because bounded prompt context is good for chat latency and bad for narration completeness.

That compact prompt context is also fingerprinted in the browser and used to cache grounded page replies and generated narration text until the page content changes.

Voice Flow

Browser chooses a speakable chunk -> browser requests /api/chat/speak -> Caddy -> sol_chat_api.py -> cache hit: stream cached MP3 bytes -> cache miss: stream fresh ElevenLabs output via 11speak.py -> browser buffers the current chunk into an object URL -> audio element plays the buffered chunk while the next chunks prefetch

The important runtime detail is that every spoken surface now uses the same Sol voice backend while the browser prebuffers the current chunk and warms the next one to reduce startup and inter-chunk stalls.

Voice Caching

Speech cache lives under ~/.local/share/sol_chat_web/tts_cache. The browser still queues discrete spoken chunks, but those chunks now start sooner and can be streamed while they are being generated.

Streamed chat replies also start speaking from completed sentences rather than waiting for the full final answer.

The floating assistant now also has explicit playback transport with state-aware labeling: Pause while speaking, Resume when paused with buffered playback, and Play otherwise. Closing the popup performs a hard stop so hidden playback does not resume later.

The quick-prompt strip is partially dynamic too: the first button stays anchored, while the second and third suggestions are rerolled from a broader context-aware pool each time the popup is reopened.

Knowledge API

Read-only semantic retrieval is exposed at same-origin routes instead of a separate API host. The knowledge API is used directly by the chat runtime for grounding and indirectly by archive browsing/search features.

Metrics Pipeline

The traffic monitor is generated from Caddy access logs plus selected Home Assistant/local system telemetry. It distinguishes raw host traffic from visible archive hits and feeds the shell taskbar counter.

Logbook Transport

The public logbook is backed by local IRC transport via ngircd, then exposed through a Python API and web client. Synthetic logbook state is also part of the intentional experience.

Media And Post Authoring

Archive content in www/posts/ is a mix of markdown entries, HTML posts, and LaTeX-backed papers. The newer paper pattern publishes:

  • a shell/browser HTML reading surface
  • a local .tex source file
  • a cached local .pdf
  • local figure assets

Media Reality

The media player works, but it remains the least trustworthy subsystem under public conditions. Large files, tunnel behavior, range requests, and player-state timing all compound each other.

Boot Behavior

User linger is enabled for david. That is the machine-level fact that keeps the user service stack alive after reboot. Without it, the site would behave like a logged-in desktop trick instead of a server.

Operational Character

Sol-37 should be described as a hybrid archive system:

  • static files first
  • generated state where needed
  • runtime daemons behind same-origin routes
  • synthetic layers documented rather than hidden

Verification Commands

curl -I -s http://127.0.0.1:8888/ curl -s http://127.0.0.1:8895/api/chat/health curl -s http://127.0.0.1:8896/api/dashboard/status | jq '.access,.camera' curl -s http://127.0.0.1:8897/api/dashboard-access/status | jq curl -sD - -o /tmp/test.mp3 'http://127.0.0.1:8895/api/chat/speak?text=hello&session=test' file /tmp/test.mp3 curl -s http://127.0.0.1:8892/health | jq curl -s 'http://127.0.0.1:8890/messages?channel=public-logbook&limit=3' systemctl --user --type=service --state=running | rg -i 'caddy|sol-chat|dashboard|knowledge|logbook|site|video|audio|sol37' systemctl --user list-timers --all | rg 'site-metrics|synthetic' loginctl show-user david -p Linger ss -ltnp | rg '(:8888|:8890|:8892|:8893|:8895|:8896|:8897|:18080)' python3 /home/david/random/bin/check_sol_chat_asset_versioning.py

Paths Worth Knowing

/home/david/random/www/index.html /home/david/random/www/README.md /home/david/random/www/site-server.html /home/david/random/www/chat/index.html /home/david/random/www/chat/chat.js /home/david/random/www/sitemap.html /home/david/random/www/site-metrics.html /home/david/random/www/posts/ /home/david/random/bin/Caddyfile.pkd_share /home/david/random/bin/sol_chat_api.py /home/david/random/bin/11speak.py /home/david/random/bin/knowledge_query_api.py /home/david/random/bin/site_metrics_snapshot.py /home/david/random/bin/site_index_snapshot.py /home/david/random/bin/sol37_gui_share_server.py /home/david/random/docs/sol37-site-audit.md