No. 14 in the series

The Writing Room Is a Building Now

or: My Next Project May End Up Being Your Next Writing System

The Writing Room Is a Building Now

This week, five chapters of Babydoll Book 2 ran through a quality gate, scored a 10.0 each, had those scores written back to a Postgres database running on a single box in the other room, got converted from markdown into Substack-ready Word documents by a Node.js script, and queued themselves for Sunday publication straight through September.

Nobody pasted a character sheet into a chat window. Nobody re-explained the canon. The system already knew.

That is not a demo. That is the production system, and this article shows you what ran.

Your feed is selling you a different version of this. The ad promises grammar fixes, scene expansion, a button that makes your prose “better.” What it ships is a text box with a model behind it. What my system ships is at a URL you can open right now: vampiresoftucson.veridianstudios.com. They show you a UI. This shows you what the system makes.

The ad-tier tools have a tell. They demo the text box and never the output, because the output is the part that is hard. A UI is a weekend. A system that ships a finished chapter every Sunday for six months is the part nobody puts in the ad. The full architectural autopsy of the writing-checker category already ran in Why ProWritingAid Is Anything but Pro, so I will not repeat it here.

One more receipt, quieter than the first. This article was prepped and drafted on the same stack. The session queried fifteen prior pieces from that Postgres instance, pulled their context by meaning through the vector index, and wrote under the same read-only governance every chapter runs under. The article ran inside its own subject. That is the receipt.

A Product Is Built for a Market. A System Is Built for a Work.

Step up from the social-media ads and the tools get serious. NovelCrafter sells the codex, a story bible that feeds your lore back to the model. Sudowrite sells the muse, generation and scene expansion on tap. n8n sells the pipeline, a self-hosted automation kit you wire together yourself. Every one of them is good at what it does. Every one of them is a product aimed at a market.

I did not build a product. I built a system aimed at one novel series, and that difference is the whole article.

A product is built for everyone, which is the same as being built for no one. A system is built for a work. The docker-compose.yml at the center of this piece was never designed to be lifted. It was designed to publish Vampires of Tucson, eleven books of theological horror set on the Arizona border, on a schedule, every week.

The specificity is the point: the Rocket book ships every Sunday through September 13, Babydoll queues up behind it as the three-month window rolls forward, and the weekday notes pipeline runs the interstitials between them. The novel is not a proof of concept I cooked up to show the architecture off. It is the load the architecture was built to carry.

The novel is not a proof of concept. It is the load.

The Manifest

Here is the building. Thirteen services, each one a room the series has documented or leaned on across fifteen articles. Read the comments. Each service names what it does, the governance boundary it respects, and which earlier piece in this publication introduced the idea it implements.

# docker-compose.yml (annotated)

services:

  postgres:          # The single source of truth (network-accessible)
    image: pgvector/pgvector:pg16
    # Databases: canon, search, substack, shared, elf
    # Roles: canon_editor (write-all), claude_reader (read + qr/word_count only)
    # Governance: canon is read-only to the AI. Two fields writable: qr, word_count.
    # ATW: "The Canon Is Firmware" (Jun 2026)

  ollama:            # Local embedding inference
    image: ollama/ollama
    # Model: nomic-embed-text (search_document: prefix)
    # Used by: memory-builder (embed on write), memory_search (embed on query)
    # ATW: "The Canon Is Firmware" - the semantic layer

  novel-pg:          # Governance MCP (the Postgres wire)
    build: ./scripts/novel_pg_mcp.py
    # pg_read across all databases; pg_write to two canon fields only
    # memory_search (embeds the query on Ollama, vector-searches memory)
    # ATW: "Bringing It All Together" - the read-only MCP

  novel-canon:       # Notes / synthesis MCP
    build: ./novel-canon/server.py
    # Enforces: alias registry, FK validation, duplicate guard on deltas
    # ATW: "Bringing It All Together" - the constraint server

  webtier:           # Canon web editor (PostgREST + HTML)
    build: ./wwwroot
    # Pages: canon-book, canon-character, canon-location, canon-coterie
    # Role: canon_editor - the ONLY writable path into canon (mine, not the AI's)
    # ATW: "Your Docs Are for You. Your Database Is for the AI."

  memory-builder:    # Daily embedding refresh
    build: ./scripts/pg_build_memory.py
    # Incremental: embeds new/changed items, deletes orphan rows
    # Throttled to protect host thermals (tune to your hardware)
    # Cron: daily, midnight

  ttl-prune:         # Weekly note TTL enforcement
    build: ./scripts/ttl_prune.sh
    # LOW: 7d / MED: 30d / HIGH: 90d, every note home, no exceptions
    # Cron: Saturday, noon

  novel-format:      # Chapter -> Substack .docx converter
    build: ./scripts/md_to_substack_docx.js
    # Internal dialogue -> italic, the beast -> bold,
    # handwriting -> blockquote, machine voice -> code
    # On demand

  novel-qr:          # Quality Rating scorer
    # Runs against the Standards Reference. Output: a 0 to 10.0 score.
    # Hard gates plus craft criteria. Score written to canon.chapters.qr.
    # ATW: "The Standards Document" - the quality layer

  tts:               # Audio production
    build: ./scripts/tts_generate.py
    # Per-publication voice + model, runner-script pattern
    # On demand

  instagram:         # Chapter art distribution
    build: ./scripts/instagram_post.py
    # Posts chapter art with a structured caption
    # On demand

  scheduled-tasks:   # Session automation
    # db-sync-check: daily gap detection, and more as needed

  claude-cowork:     # The operating brain (Claude, CoWork mode)
    # Not a container. The daily writing session.
    # Pointed at novel-pg and novel-canon. Reads canon, writes qr and
    # word_count only. Everything else: read-only.

  claude-code:       # The build crew (Claude Code)
    # Not a container. The build session.
    # MCP edits, schema changes, scripts, infrastructure.
    # Scoped separately from CoWork: Code builds what CoWork operates.

Read top to bottom, the file clusters into four jobs, and the first is storage: postgres, one container holding every database, with pgvector bolted in so the AI can search its memory by meaning and not just by spelling. Inference is ollama, a local embedding model, so no manuscript text ever leaves the house to get vectorized. Governance is the two MCP servers and the web editor, novel-pg, novel-canon, and webtier: the wires the AI reaches through, and the one door a human uses to write canon. Production is everything that turns a draft into a published artifact, the memory builder, the TTL prune, the .docx converter, the quality scorer, the audio renderer, the Instagram poster, and the tasks that fire while I sleep.

Underneath all of it sit two roles that are not containers at all.

Two Claudes, One Key Ring They Do Not Share

This system requires Claude. Not “an LLM,” not “your model of choice.” Claude, specifically, in two distinct roles the compose file names at the bottom.

Claude Code is the build crew. It edits the MCP servers, changes the schema, writes the scripts, and does the byte-critical work that touches the filesystem directly. Claude in CoWork mode is the operating brain. It runs the writing sessions, scores the chapters, preps the articles, and drives the publication pipeline, reaching the data only through the MCPs and the boundaries they enforce.

Code builds the room. CoWork works in it. They are scoped apart on purpose, and that separation is architectural, not incidental. The brain that runs your novel every day should not also hold the keys to rewrite the building it runs in.

The Part the Tools Hand You, and the Part They Cannot

The commercial tools give you generation. What they cannot give you is governance. Governance is specific to your work and your rules.

In this system the canon is read-only to the AI, so across the cast, the locations, and the chapter records, Claude reads every one of them on every query and writes exactly two fields back, a quality score and a word count. It cannot invent a character. It cannot quietly move a scene from Tucson to Tombstone because the prose flowed better that way. The session context is loaded from the database, not pasted by me at the top of every chat, so it is the same context every time and it is right every time. None of that is possible without the schema layer this publication spent a year building.

Docker keeps that governance honest one level down. Its job here is not packaging. It is isolation. Each service runs in its own container with defined edges, so the writing system does not leak into the host machine and the host machine does not leak into the writing system. It is the same principle as canon-read-only, applied to infrastructure: contain the thing, define what is allowed to cross the boundary, and nothing contaminates anything by accident.

Which makes the hardware requirement smaller than it looks. One machine that can run Docker. That is the entire list. I run mine on a NAS because I owned one and it stays on, but that is my choice, not a tax I am passing to you.

A laptop works. A desktop works. A cheap always-on box in a closet works. The isolation is exactly what lets the writing system share that one machine with everything else on it without either side stepping on the other.

Why Postgres, When SQLite Would Fit a Novel in One File

One service in the manifest replaced something simpler. It earns an explanation.

SQLite, by its own documentation, does not do networks: it is file-based and single-process, brilliant when one program owns one file, and out of its lane the moment that file has to answer to more than one client at once. I cited the SQLite project’s own Appropriate Uses checklist as the receipt for this move back in The Canon Is Firmware: when the data is separated from the application by a network, you want a client/server engine.

In this system, CoWork, Code, the web editor, the memory builder, and the scheduled tasks all want the same data at the same time, sometimes from different machines. SQLite cannot serve that table. Postgres can. The writing room did not outgrow SQLite because SQLite is bad. It outgrew it because the room grew rooms.

Docker and Postgres end up solving the same problem from opposite ends. Docker keeps the system contained. Postgres keeps it reachable. One holds the walls in, the other lets every service through the same door, and between them the building stays sealed and connected at the same time.

Build Yours

Here is the part where I hand it over.

The thirteen services split into two groups. The split is the instructions. The infrastructure layer ports straight across: postgres, ollama, the memory builder, the TTL prune. None of that is specific to vampires or to novels. It is plumbing, and plumbing is plumbing.

The production layer is mine: novel-pg, novel-canon, novel-format, novel-qr, the services that know what a chapter is and what my Standards Reference says a 10.0 looks like. Swap those for your own equivalents and the compose file becomes yours.

I am going to put the whole stack on GitHub. Not today. In a few weeks, once I have scrubbed the secrets and written enough of a README that it does not strand the first person who clones it. And I am going to be honest about what lands there: an alpha. Untested in any hands but mine, rough at the edges, a starting point and not a polished release. The gift is the blueprint and the scaffolding, not a plug-and-play machine that writes your novel for you on the first run.

That is still more than the market is offering, because the market is not offering it at all.

The Writing Room Is Real. Here Is the Building.

The first article in this publication was called The Writing Room Is Real. The argument was that the room was not a metaphor but databases, MCPs, scheduled tasks, and quality gates, a thing you could actually build, and the series would document the building of it in real time.

Fifteen articles later, the room has walls, named rooms, one door, plumbing, and a load it carries every Sunday.

The writing room is real. Here is the building.

NovelCrafter, Sudowrite, n8n, the whole shelf of them are selling you a version of this, and selling is the right verb. Mine is not for sale. In a few weeks the compose file, the scripts, the whole blueprint go up where anyone can take them.

Many are selling one. I’m giving mine away.


You may also like: - Bringing It All Together - The Architecture Underneath the Writing Room - Your AI Policy Isn’t Governance, or the Difference Between a Reminder and a Control

All entries

All writing on this site contains elements of both human and AI produced material. This author uses all resources at his disposal.