cameron.stream #
Personal site for cameron.stream. Built with Hono + JSX, server-rendered, deployed to Fly.io. Blog content is stored as site.standard.document records on ATProtocol (PDS), not as local files.
Setup #
pnpm install
The site needs no credentials for local or production reads. Blog and other protocol-native surfaces use public PDS APIs.
The following are set in fly.toml for production but can be overridden locally:
| Variable | Default | Description |
|---|---|---|
CAMERON_DID |
did:plc:gfrmhdmjvxn2sjedzboeudef |
Author DID |
PUBLICATION_URI |
(see fly.toml) | AT-URI of the site.standard.publication record |
PORT |
3002 (dev) / 8080 (prod) |
Server port |
HOST |
0.0.0.0 |
Server bind address |
SITE_URL |
https://cameron.stream |
Canonical site URL (used for OG tags) |
SEMBLE_HANDLE |
cameron.stream |
Bluesky handle for Semble page |
ENABLE_MARGIN |
unset | Set to "true" to enable margin notes |
The Git-backed About and Knowledge projection worker reads
CAMERON_BSKY_APP_PASSWORD from its private systemd environment file. Do not
put that credential in the repository or the Fly runtime.
Development #
pnpm dev
Starts the dev server at http://localhost:3002 with file watching.
Type checking #
pnpm typecheck
Custom typefaces #
Around is the site's custom geometric unicase display face. Its source geometry,
build environment, generated fonts, specimen, and design notes are all kept in
this repository. See docs/around-typeface.md before
changing or regenerating it.
Processional is a separate monumental unicase face derived from the Cosmic
Liturgical Brutalism style guide. Its specimen is at /type/processional; the
source and proofing workflow live in
docs/processional-typeface.md.
Blog authority #
Blog posts stay in Leaflet. The repository contains no Blog Markdown copies and does not write or reconcile Blog records. Cameron.stream reads the Leaflet publication directly from the PDS at runtime. Create and edit posts in Leaflet.
The About page is intentionally separate: content/about.md is Git-backed and
projects to stream.cameron.about/self. See
docs/public-content.md for the authority split.
Public knowledge #
Public Knowledge is a file-backed, linked knowledge base at /knowledge. It
opens on a public NOW note and includes Entries, Semble Links, and Margin
Annotations. Private Obsidian notes never enter the production build directly.
Canonical architecture and operations: docs/public-knowledge.md.
# Convert an allowlisted Coil note into an ignored local draft.
pnpm knowledge:stage "$HOME/Documents/The Coil/lessons/example.md" \
--summary "Public summary" \
--source "Primary source=https://example.com"
# Validate staged and published entries.
pnpm knowledge:check -- --include-drafts
# Preview ignored drafts locally. Production never enables this flag.
KNOWLEDGE_INCLUDE_DRAFTS=1 pnpm dev
# After Cameron reviews the exact rendered draft and supplies a receipt.
pnpm knowledge:promote example \
--reviewed-by Cameron \
--content-digest sha256:reviewed-file-digest \
--review-receipt-digest sha256:private-receipt-digest \
--confirm-public
# Preview the reviewed Standard.site Knowledge projection without writing.
pnpm knowledge:sync -- --all
# After reviewed source reaches main, run the credential-provisioned worker.
systemctl --user start cameron-site-content-sync.service
systemctl --user show cameron-site-content-sync.service \
--property=ActiveState,SubState,Result,ExecMainStatus --no-pager
# Install or refresh the isolated worker checkout and user units.
deploy/systemd/install-content-sync-worker.sh
knowledge/policy.json is default-deny and owns the Obsidian source mappings.
Draft Markdown is gitignored under knowledge/staged/. The Docker image copies
only knowledge/published/, so a local draft cannot leak through a broad build
context. Canonical Knowledge remains reviewed local Markdown. The projection
worker reconciles only approved entries recorded through the review pipeline and
stores public URI, CID, source-digest, and review-digest receipts in
knowledge/atproto-manifest.json. The public file stores only a digest of the
private route-scoped review receipt. Promotion, protocol mirroring, and
deployment are separate actions joined by the worker.
Deployment #
Deployed to Fly.io as cameron-stream. The normal Git-backed content path is the
credential-provisioned worker above. A direct Fly deployment updates the site
image only; it does not reconcile About or Knowledge records on ATProto:
fly deploy
The Fly runtime does not need a PDS credential. Projection writes happen only
through the guarded local worker. Do not invoke
scripts/sync-git-backed-content-from-origin.sh from an ordinary shell: that
shell normally lacks the worker credential and can deploy Fly successfully
before failing at ATProto reconciliation. The installed service operates from a
dedicated checkout under ~/.local/share/cameron-site/deploy-checkout; human and
agent work in /home/cameron/code/cameron-site-tangled cannot make the deploy
checkout dirty or ahead of Tangled main.
Stack #
- Hono -- HTTP framework with JSX support
- tsx -- TypeScript execution (no build step)
- marked + shiki -- Markdown rendering with syntax highlighting
- @atproto/api -- ATProtocol client for PDS reads/writes
- ioredis -- Optional caching layer
Project structure #
src/
index.tsx -- Routes and page shell
data.ts -- Leaflet/PDS Blog and Bluesky data fetching
leaflet-reader.ts -- Read-only Leaflet block conversion
markdown.ts -- Markdown rendering pipeline
cache.ts -- Redis/memory cache
components/ -- Page components (JSX)
public/
site.css -- Main stylesheet
host-primitives.css
host-theme.css
theme.js -- Dark/light mode toggle
knowledge/
policy.json -- Default-deny source mappings and privacy rules
published/ -- Explicitly reviewed entries included in production
content/
about.md -- Cameron-owned About source