My website. cameron.stream
TypeScript 40%
JavaScript 33%
CSS 18%
Python 7%
Shell 1%
HTML <1%
Dockerfile <1%
<1%

README.md

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