qino-journal System Reference
Complete reference for the qino-journal publishing and display system.
System Overview
qino-journal transforms research arcs into reader-friendly transmissions. The Student acts as a companion who walks alongside readers, asking the questions they would ask, voicing the difficulty of encountering abstract material.
High-Level Architecture
┌─────────────────────┐ ┌──────────────────────┐
│ Source Repo │ GitHub Action │ Backend Worker │
│ (concepts-repo) │ ──────────────────────▶│ │
│ │ POST /publish │ ┌────────────────┐ │
│ journal/ │ │ │ Publish Route │ │
│ └── transmissions/│ │ └───────┬────────┘ │
└─────────────────────┘ │ │ │
│ ┌───────▼────────┐ │
│ │ Parser │ │
│ └───────┬────────┘ │
│ │ │
│ ┌───────▼────────┐ │
│ │ Image Queue │ │
│ └───────┬────────┘ │
│ │ │
│ ┌───────▼────────┐ │
│ │ Queue Consumer │──┼──▶ image-gen service
│ └────────────────┘ │
└──────────┬───────────┘
│
┌────────────────────────────┴────────────────────────────┐
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ R2: Content │ │ R2: Images │
│ (markdown+json)│ │ (public URL) │
└────────┬────────┘ └────────┬────────┘
│ │
▼ direct browser access │
┌─────────────────────────────────────────────────────────┐ │
│ Frontend Worker │ │
│ (TanStack Start) │◀───────┘
└─────────────────────────────────────────────────────────┘
│
▼
┌─────────┐
│ Browser │
└─────────┘
The Student as Reader Companion
The Student is not a character discovering material for the first time. They are a pedagogical companion who has learned this material and now walks alongside readers as they encounter it.
What the Student Does
| Role | Purpose |
|---|---|
| Translator | Makes abstract findings concrete and approachable |
| Questioner | Asks what readers would ask (even knowing the answer) |
| Struggler | Mirrors the difficulty of encountering material fresh |
| Guide | Has understood; now helps others arrive |
Voice Markers
The Student's voice has specific signatures:
- "When I first saw this, I thought..." — acknowledges prior learning
- "What makes this tricky is..." — mirrors reader struggle
- "Let me try to make this concrete..." — translator role
- "I'm not sure..." — genuine uncertainty (reader's uncertainty)
- "Wait, does that mean...?" — questions as movement
Transmission Format
YAML Frontmatter
---
number: 1
slug: recognition-through-indirection
title: Recognition Through Indirection
date: 2025-12-29
arcs:
- id: recognition-through-indirection
title: Recognition Through Indirection
essence: How metaphorical distance can preserve meaning
threads:
- name: ecosystem-modality tension
context: Holding both levels without collapsing either
- name: crystallization
context: When vague quality becomes speakable
---
Body Structure
# Recognition Through Indirection
*Dec 29. Walking through two arcs today...*
[Body content — 600-900 words, Student's voice]
[Questions and discoveries woven INTO the prose]
[Ends with weight, not summary]
---
## Where I Am Now
**Still holding:**
- Does naming enable perception, or close it?
**Starting to see:**
- The modality tension and the language question are the same thing
**What I'm noticing about this:**
The pattern came before the naming. I keep forgetting this.
Key Differences from Earlier Format
| Before | After |
|---|---|
Separate ## Abstract section | Opening lines ARE the entry |
Heavy ## The Student aside | Light "Where I Am Now" coda |
| Threads section at bottom | Thread definitions in frontmatter |
| Hidden reflection field | Visible as "What I'm noticing" |
Thread Highlighting
Threads are concepts or questions that recur across transmissions. They appear in prose as [[thread-name]] and are highlighted with hover cards.
How It Works
- Frontmatter defines threads with name and context
- Parser extracts threads into structured data
- HighlightedMarkdown component scans for
[[...]]patterns - Hover cards show thread context on mouse over
Thread Colors
| Type | Color | Examples |
|---|---|---|
| Concepts | Cool tones (teal, sky) | ecosystem-modality tension |
| Questions | Warm tones (amber, rose) | does naming enable perception? |
Data Flow
Phase 1: Publishing (Source → Backend → R2)
┌──────────────┐ ┌─────────────────┐ ┌─────────────┐ ┌─────┐
│ Git Push to │───▶│ GitHub Action │───▶│ POST │───▶│ R2 │
│ main branch │ │ journal- │ │ /publish │ │ │
│ │ │ publish.yml │ │ │ │ │
└──────────────┘ └─────────────────┘ └─────────────┘ └─────┘
Backend processing:
- Validates API key and repo allowlist
- Parses each transmission with
parseTransmissionContent() - Stores both raw markdown AND parsed JSON
- Queues image generation for Student images
R2 storage structure:
journal-content/
└── concepts-repo/
├── manifest.json
├── visual-style.md (documentation)
├── visual-config.json (structured config for prompt builder)
└── 001-recognition-through-indirection/
├── transmission.md (raw markdown)
└── transmission.json (parsed structure)
Phase 2: Reading (Frontend ← R2)
┌──────────────┐ ┌─────────────────────┐ ┌─────┐
│ Browser │───▶│ Frontend Worker │───▶│ R2 │
│ Request │ │ get-transmissions.ts│ │ │
└──────────────┘ └─────────────────────┘ └─────┘
Server functions fetch:
manifest.json→ transmission list{id}/transmission.json→ parsed transmission with threads, arcs, Student state
Key Interfaces
Transmission
interface Transmission {
id: string;
title: string;
date: string;
arc: Arc; // Primary arc
arcs: Arc[]; // All arcs this transmission moves through
threads: Thread[]; // Thread definitions for highlighting
content: string; // Body markdown
student: StudentState; // Where I Am Now data
}
Arc
interface Arc {
id: string;
name: string;
status: "in-motion" | "completed";
essence?: string; // One-line description
}
Thread
interface Thread {
name: string;
context: string; // Shown in hover card
}
StudentState
interface StudentState {
questionsHeld: string[]; // Still holding
connectionsNoticed: string[]; // Starting to see
metaLearning?: string; // What I'm noticing about this
reflections: Array<{ // Dated entries (optional)
date: string;
content: string;
}>;
}
Parsing
The transmission parser (transmission-parser.ts) handles both new YAML frontmatter format and legacy section-based format.
Extraction Functions
| Function | Extracts |
|---|---|
extractYamlFrontmatter() | YAML block between --- markers |
extractArcs() | Arc array from frontmatter |
extractThreads() | Thread array from frontmatter |
extractStudentStateFromCoda() | Student state from "Where I Am Now" |
extractTitle() | Title from first # heading |
extractDate() | Date from frontmatter or content |
Content Hashing
The parser generates content hashes for differential regeneration:
interface TransmissionContentHashes {
transmission: string; // Hash of full content
arc: string; // Hash of arc info
connections: Record<string, string>; // Hash per connection
}
File Reference
Frontend (qino-journal)
| File | Purpose |
|---|---|
src/server/get-transmissions.ts | R2 fetching, types |
src/routes/index.tsx | Home page with transmission list |
src/routes/transmission/$id/index.tsx | Transmission display |
src/components/highlighted-markdown.tsx | Thread highlighting |
src/components/transmission-end-matter.tsx | Arc info at bottom |
Backend (qino-journal-backend)
| File | Purpose |
|---|---|
src/routes/publish.ts | Content ingestion, R2 storage, queue jobs |
src/lib/transmission-parser.ts | Markdown parsing, YAML frontmatter extraction |
src/queue/image-generator.ts | Queue consumer, image generation |
src/services/prompt-builder.ts | Builds prompts for Student images |
src/routes/status.ts | Image generation status |
src/routes/manifests.ts | Image manifest retrieval |
src/routers/transmissions-router.ts | tRPC router for mock data |
src/types.ts | Shared type definitions |
Content Generation (qino-claude)
| File | Purpose |
|---|---|
tools/qino-journal/commands/qino-journal/transmit.md | Transmission command |
tools/qino-journal/agents/journal-prose.md | Prose agent |
tools/qino-journal/agents/journal-editorial.md | Editorial agent |
tools/qino-journal/references/qino-journal/voice.md | Voice guide |
tools/qino-journal/references/qino-journal/student-guide.md | Student companion model |
Environment Configuration
Backend (wrangler.jsonc)
{
"services": [
{ "binding": "IMAGE_GEN", "service": "image-gen" }
],
"r2_buckets": [
{ "binding": "CONTENT_BUCKET", "bucket_name": "journal-content" },
{ "binding": "IMAGES_BUCKET", "bucket_name": "journal-images" }
],
"queues": {
"producers": [{ "binding": "IMAGE_QUEUE", "queue": "journal-image-queue" }],
"consumers": [{ "queue": "journal-image-queue", "max_batch_size": 1 }]
},
"vars": {
"ALLOWED_REPOS": "qino-claude,concepts-repo",
"R2_PUBLIC_URL": "https://<public-r2-bucket-url>"
}
}
Frontend (wrangler.jsonc)
{
"r2_buckets": [
{ "binding": "CONTENT_BUCKET", "bucket_name": "journal-content" }
],
"vars": {
"R2_IMAGES_URL": "https://<public-r2-bucket-url>",
"BACKEND_URL": "https://qino-journal-backend.workers.dev"
}
}
Visual Configuration
The journal uses a two-file system for visual styling:
| File | Purpose | Format |
|---|---|---|
visual-style.md | Human-readable documentation | Markdown |
visual-config.json | Machine-readable config for prompt builder | JSON |
visual-config.json Schema
interface VisualConfig {
arcLocations: Record<string, ArcLocation>;
defaultLocation: ArcLocation;
coreStyle?: string;
baseStyle?: string;
}
interface ArcLocation {
region: string;
environments: string[];
textures: string[];
indoor: string[];
outdoor: string[];
}
How It Works
- Publishing: GitHub Action reads
visual-config.jsonfrom source repo - Storage: Backend stores it in R2 at
{repoName}/visual-config.json - Image Generation: Queue consumer loads config before building prompts
- Fallback: If no config exists, hardcoded defaults are used
Arc-Based Locations
Each research arc unfolds in its own environment. The prompt builder selects environments based on arc ID:
{
"arcLocations": {
"recognition-through-indirection": {
"region": "Central European Alps",
"environments": [
"mountain terrace with wooden chairs and wool blankets",
"wintergarden with glass walls and mountain view"
],
"textures": ["weathered wood, wool blankets, ceramic mugs"],
"indoor": ["alpine lodge with books, fire, wood paneling"],
"outdoor": ["mountain terrace overlooking snow-covered peaks"]
}
}
}
Seasonal Interpretation
The prompt builder interprets the transmission date to determine seasonal atmosphere:
| Date Range | Season | Light Quality |
|---|---|---|
| Dec 1 – Feb 28 | Deep Winter | Blue-white snow light, warm interior glow |
| Mar 1 – Apr 30 | Early Spring | Pale sun, wet surfaces, first green |
| May 1 – Jun 30 | Late Spring | Golden afternoon, long shadows |
| Jul 1 – Aug 31 | Summer | Bright but not harsh, evening lingers |
| Sep 1 – Oct 31 | Autumn | Amber and copper, low sun |
| Nov 1 – Nov 30 | Late Autumn | Grey and silver, bare branches |
Special dates (solstices, equinoxes, Christmas) receive additional atmospheric notes.
Source Repo Structure
journal/
├── manifest.json # Transmission metadata
├── visual-style.md # Documentation (human reference)
├── visual-config.json # Config (machine-readable)
└── transmissions/
├── 001-first-transmission.md
└── 002-second-transmission.md