← Back to Journal

System Architecture

How qino Journal transforms research arcs into reader-friendly transmissions

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

RolePurpose
TranslatorMakes abstract findings concrete and approachable
QuestionerAsks what readers would ask (even knowing the answer)
StrugglerMirrors the difficulty of encountering material fresh
GuideHas 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

BeforeAfter
Separate ## Abstract sectionOpening lines ARE the entry
Heavy ## The Student asideLight "Where I Am Now" coda
Threads section at bottomThread definitions in frontmatter
Hidden reflection fieldVisible 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

  1. Frontmatter defines threads with name and context
  2. Parser extracts threads into structured data
  3. HighlightedMarkdown component scans for [[...]] patterns
  4. Hover cards show thread context on mouse over

Thread Colors

TypeColorExamples
ConceptsCool tones (teal, sky)ecosystem-modality tension
QuestionsWarm 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:

  1. Validates API key and repo allowlist
  2. Parses each transmission with parseTransmissionContent()
  3. Stores both raw markdown AND parsed JSON
  4. 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

FunctionExtracts
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)

FilePurpose
src/server/get-transmissions.tsR2 fetching, types
src/routes/index.tsxHome page with transmission list
src/routes/transmission/$id/index.tsxTransmission display
src/components/highlighted-markdown.tsxThread highlighting
src/components/transmission-end-matter.tsxArc info at bottom

Backend (qino-journal-backend)

FilePurpose
src/routes/publish.tsContent ingestion, R2 storage, queue jobs
src/lib/transmission-parser.tsMarkdown parsing, YAML frontmatter extraction
src/queue/image-generator.tsQueue consumer, image generation
src/services/prompt-builder.tsBuilds prompts for Student images
src/routes/status.tsImage generation status
src/routes/manifests.tsImage manifest retrieval
src/routers/transmissions-router.tstRPC router for mock data
src/types.tsShared type definitions

Content Generation (qino-claude)

FilePurpose
tools/qino-journal/commands/qino-journal/transmit.mdTransmission command
tools/qino-journal/agents/journal-prose.mdProse agent
tools/qino-journal/agents/journal-editorial.mdEditorial agent
tools/qino-journal/references/qino-journal/voice.mdVoice guide
tools/qino-journal/references/qino-journal/student-guide.mdStudent 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:

FilePurposeFormat
visual-style.mdHuman-readable documentationMarkdown
visual-config.jsonMachine-readable config for prompt builderJSON

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

  1. Publishing: GitHub Action reads visual-config.json from source repo
  2. Storage: Backend stores it in R2 at {repoName}/visual-config.json
  3. Image Generation: Queue consumer loads config before building prompts
  4. 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 RangeSeasonLight Quality
Dec 1 – Feb 28Deep WinterBlue-white snow light, warm interior glow
Mar 1 – Apr 30Early SpringPale sun, wet surfaces, first green
May 1 – Jun 30Late SpringGolden afternoon, long shadows
Jul 1 – Aug 31SummerBright but not harsh, evening lingers
Sep 1 – Oct 31AutumnAmber and copper, low sun
Nov 1 – Nov 30Late AutumnGrey 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