More FE

I prompted the LLM to look at the src/dockb/controllers/README_API.md file and suggest a good breakdown for the remaining server-side work to support the FE. It suggested the following, which seemed good to me:

Phase 1: API Data Contracts (no dependencies)

  1. Pydantic wire-format schemas
  2. ProseMirror serialization

Phase 2: Repository Read Methods (depends on models — already done)

  1. List/find queries on repositories

Phase 3: Service Layer (depends on parts 2 and 3)

  1. CRUD services
  2. SessionContext enhancement

Phase 4: Controllers + App Wiring (depends on parts 1–5)

  1. FastAPI route handlers
  2. Response middleware
  3. App assembly

Phase 5: History (independent of Phases 3–4, can run in parallel)

  1. History infrastructure
  2. History service + API endpoints

I started working through the 10 components, in an afternoon on the weekend, in between doing other things, and it changed 15 files, and created 22. I then started to think about the actual FE.

FE Design Summary from README Files

Core Editing Principle (README_editing.md)

Wire Format (README_API.md)

Session Architecture (infrastructure/session/README.md)

Async Processing (services/semantics/README.md)

Data States (README_data_states.md)

No dedicated FE README exists

The FE design is distributed across the API spec and editing README. The key FE facts are:

  1. ProseMirror-based editor
  2. Debounced keystroke batching
  3. Receives async notifications (sentence/paragraph splits) via piggy-back or polling
  4. Never sees tokens — only text nodes
  5. Tells the BE what changed (which node, relative to hierarchy), not where (character offsets)

On closer analysis, I realised the TUI FE would be a waste of time, and that the RUST FE was not going to work so well, and that using a TipTap FE would work better.

See frontend/README.md

DockB Frontend

React + Tiptap editor for the DockB document hierarchy.

Tech Stack

Architecture

The frontend communicates with the FastAPI backend via REST endpoints defined in `src/dockb/controllers/README_API.md`. All document content uses ProseMirror JSON wire format (chapter → paragraph → sentence → text).

Document Hierarchy

Document (plain JSON)
  └── Chapter (ProseMirror tree)
        └── Paragraph (ProseMirror tree)
              └── Sentence (ProseMirror tree)
                    └── Text (inline)

Wire Format Mapping

Backend NodeTiptap ExtensionTop Node
ChapterChapterYes
ParagraphParagraphNo
SentenceSentenceNo
TextBuilt-inNo

Key Design Decisions

Structure

frontend/
├── src/
│   ├── api/client.ts          # API client for all REST endpoints
│   ├── editor/
│   │   ├── schema.ts          # ProseMirror schema matching backend
│   │   ├── ChapterEditor.tsx  # Tiptap editor for chapter content
│   │   └── extensions.ts      # Custom Tiptap node extensions
│   ├── types/index.ts         # TypeScript types matching wire format
│   ├── components/
│   │   ├── DocumentList.tsx   # Document browser
│   │   └── ChapterView.tsx    # Chapter sidebar + editor
│   ├── App.tsx                # Main app with navigation
│   └── main.tsx               # Entry point
├── package.json
├── vite.config.ts             # Dev server + API proxy
└── .eslintrc.cjs

Development

cd frontend
npm install
npm run dev    # Serves on :3000, proxies /api to :8000

The Vite dev server proxies `/api` requests to `http://localhost:8000` where the FastAPI backend runs.

To run the back end:

make run

Commands

CommandPurpose
npm run devStart dev server
npm run buildTypeScript check + production build
npm run lintESLint check

Now an admission

I got impatient. I'm a newbie with the frontend tech that I'm using, so I told the LLM to build a UI. It did. But...
it did not show any documents, because there are none yet, but it did not give me the option to create one. So I worked with it (not so impatiently this time), using good design and TDD principles, and it created a "New document" link. The UI was extremely bare bones, un-styled, but it worked. Then when I created the document, the FE showed a blank screen. The reason being that the BE had a bug...
and this bug was because I had not properly checked the tests before I told the LLM to proceed.

My admission is that it is very easy to trust too much, be overly enthusiastic, and skip good practices. I did that.

This does concern me, that I, as an experienced developer, who firmly believes in good programming practices, in my own project (of which I am proud and not under pressure), could succumb to this weakness.

We will need to teach junior engineers:

  1. Grass roots programming - how about some assembly, and C?
  2. Best principles

And we absolutely SHOULD NOT put them under pressure, because the temptation to cut corners will be so easy to take, even without pressure, simply from enthusiasm.