The Backlog · captured, not ranked

The Backlog.

Everything we want to build, grouped by theme — not a P0/P1 plan. As we discuss, we add here; when we execute, we pick any item. What's done lives on the Control Room.

🏁 oll.in — THE flagship (committed) 📸 foto UN-PARKED — the CHF 29 on-ramp $9 MRR live · money path proven

"We don't have a plan — we have a backlog. As we discuss we add to it; when we execute we choose any."

This page is the open to-do — the captured set of everything wanted, grouped by theme, not ranked. There's no gate and no "one goal until…" ordering here: any item can be the next thing we pick up. Everything done & live lives on the Control Room (the shipped tally); the why / market / wedge in Strategy. The money path is closed & verified — a stranger can pay today.

🏁 oll.in — THE flagship (committed)

decision · Sam
Decision (Sam, committed): oll.in is THE flagship product — the agentic Swiss job-application & career agent for everyday job seekers (nurses, teachers, tradespeople, admin, care, sales) — the people who today DIY their applications with ChatGPT and pay ~CHF 40/mo LinkedIn Premium. It is not a tool for developers. Why it wins the flagship slot: it is the one product that lights up the whole platform — Core + Model + Memory (all three frozen spines) + the agent seam + ollwrite + foto — all proven live. A crazy-good landing is already built (landing/ollin-pro.html — everyday-user positioning, an agent-at-work mockup, honest illustrative case studies for a nurse / teacher / plumber), grounded in a competitor + market research brief and a faceless.so teardown. See the constellation · Platform 2.0 · Strategy.
Honest flag — still pre-revenue. The flagship's first franc is the CHF 29 on-ramp (the Bewerbungsfoto), not the full agent. The value ladder below is the plan, not shipped. The whole reason foto is un-parked is that the headshot is the nearest path to the first stranger franc — it also earns the email list + before/after proof that feed the rest of the ladder.

The value ladder — a cheap on-ramp into recurring revenue

Rung Price What it is Role
1 · On-ramp CHF 29 Bewerbungsfoto — an AI application photo (guest checkout, no login). Reuses trendfy's live Flux-LoRA pipeline + Core billing/email. Earns the first franc + the email list + before/after proof.
2 · Pass CHF 99 Application pass — the agent tailors CV + Motivationsschreiben per job (Swiss-format CV layout), grounded in the user's own corpus via Memory + ollwrite. The core value unit — one strong application, done for you.
3 · Radar CHF 19/mo Career Radar — the agent scouts fresh matching jobs and drafts applications on a cadence; the honest LinkedIn-Premium alternative. The first recurring MRR in the whole constellation.

The roadmap to make the flagship real — in order

Step 1 Un-park foto = the first franc 🔨 nearest dollar

foto-service is scaffolded under services/foto/ (thin Core client, tests). This is the CHF 29 on-ramp — the shortest path to a stranger paying.
  • Fresh Core guest-checkout pair — a small additive guest-checkout-session + guest-verify-session on a feat/ branch (the old PR #21 was closed / conflicting — write it fresh, don't revive). The headshot needs no login. Claude
  • Pin the Flux-LoRA model ids — reuse trendfy's live ai-models pipeline (already generating in prod); pin the exact model versions into services/foto, no new training. Claude
  • Wire the CHF 29 checkout on the landing — the built landing/ollin-pro.html / foto entry → Core guest checkout → generate → deliver. Claude
  • foto deploy config — Dockerfile + Coolify Base Directory /services/foto + Watch Paths + $PORT + a private Neon oll_foto DB, prepared to one click. Claude prepares
  • Replicate token — provision the Replicate API token for the image pipeline. Sam console
  • Stripe CHF 29 price + live webhook — create the one-time CHF 29 price + the live billing/webhook. Sam console · irreversible
  • Coolify app + a domain — the foto Coolify app + a front door (shot.oll.am or bewerbungsfoto.ch). Sam console
  • Prove it end-to-end — a real card → a real headshot → delivered to the inbox. Sam verifiesdone = the first stranger franc, on the flagship's on-ramp.

Step 2 Build the agent's job-SCOUT half ⏳ queued

The drafting half of the agent is already live via oll-mcp (proven end-to-end: web_search → ollam_draft). The missing half is scouting — finding the jobs.
  • Legal job APIs — integrate Adzuna / Arbeitnow / Jooble (ToS-clean job feeds), not scraping. Feeds Career Radar (rung 3) + the CHF 99 pass (rung 2). Claudedone = the agent can find matching jobs, not just draft for one you paste.

Step 3 Run the distribution playbook ⏳ queued

Everyday seekers don't read Show HN. Reach them where they search — honest, comparison-led, no spam.
  • Comparison pagesvs LinkedIn Premium · vs ChatGPT · AI Bewerbungsfoto vs the CHF 300 studio. Claude
  • Free tools + a self-select live demo — a low-friction try-before-buy that funnels into the CHF 29 on-ramp. Claude
  • Post in Swiss channels — the honest, everyday-seeker rooms (DE-CH). Sam

✍️ oll-write — the launch program

ordered · rungs
This one IS ordered — unlike the themes below, oll-write is a single build-to-launch program, so it reads top-to-bottom as the checklist. The product works locally today (calm manuscript editor + the ✨ op menu, the memory sidecar, Groq generation, Ollama nomic embeddings). Decision (Sam, 2026-07-05): full v2 build-out THEN launch — on a new dedicated domain (name TBD), at a custom price (number + free/paid split TBD), with Claude preparing everything and Sam doing the irreversible deploy + the live-Stripe clicks. Grounded in the build-out & GTM plan and the feature documentation. Honest flag: the humaniz first-franc stays P0 — this runs alongside/after it, and within oll-write the chargeable rung (2) lands before the exotic set (3).
⛔ Two decisions gate the money step — needs Sam. Everything up to Rung 2 can be built without them, but the checkout + go-live cannot close until: (1) the domain name for the dedicated front door; and (2) the price — the CHF number and the free/paid split (what's free vs behind Pro; the plan gates the Claude/70b quality dial + grounded chat behind Pro). Plus the irreversible launch clicks are Sam's: the oll-memory + oll-write Coolify deploys, the domain DNS, and flipping Stripe to LIVE + a real-card verify. Claude prepares each to one click.

Rung 0 Real product front 🔨 in progress

  • Landing page — hero + live editor preview + features + pricing, built from the design/mockups, matching the Manuscript aesthetic (cream floating page, Source Serif prose, warm ink, the quiet blue accent). Claudedone = a stranger lands and immediately gets "a real editor where your private corpus is live context, pay once."
  • Onboarding flow — the first-run path into the editor with demo data, so the three panes are never empty. Claudedone = a new user sees a working editor + a seeded corpus on first open, no blank slate.
  • Home / library — the document list surface (open, recent, new) rendered in the same design language. Claudedone = you can move between documents from a real home screen, not just one editor route.
  • Pricing / upgrade — the pricing surface + the in-app upgrade screen (numbers filled once the price is decided). Claude ⛔ price TBDdone = a Pro CTA that's ready to point at Core checkout the moment the price lands.

Rung 1 Trustworthy & correct ⏳ queued

  • Stable caller-supplied document_id + upsert + delete — today document_id is content-hash-derived, so editing a source re-hashes and orphans its old chunks (RISK 1). Move to a stable id with upsert-by-id + a delete affordance. Claudedone = edits replace chunks instead of leaving stale, contradictory copies in retrieval.
  • Relevance floor + honest abstention — three claim states (grounded / no-source / contradicted); a retrieval miss says "I don't have this," never invents a cited claim (RISK 2). Claudedone = no green citation ever points at nothing.
  • Retry loop on memory chat — lift the editor's TRANSIENT retry/backoff into memory chat so it survives Groq 429s like the editor does (RISK 3). Claudedone = chat and the editor share one resilient reliability seam.
  • PDF ingest wiring — the backend already parses base64 PDF; this is frontend upload accept + BFF passthrough only, no backend change. Claudedone = the biggest-corpus format (PDFs) drops straight into the sidecar.
  • Inline citation Plate node + drag-to-cite — a real citation node that validates every citation maps to a retrieved chunk before render (no orphan chips), and the drag-a-ChunkCard-into-the-draft gesture (cards are read-only today). Claudedone = click-to-passage trust, and the signature "drag a memory in as a citation" gesture is live.

Rung 2 Onboarding & the chargeable hook ⏳ queued

  • First-corpus "what I found" — on first ingest, an auto summary + 3 suggested questions via /api/extract, so the sidecar is never empty (NotebookLM's highest-leverage move). Claudedone = the corpus introduces itself the moment it's fed.
  • Export-to-Markdown-with-citations — your notes and their citations walk out as plain .md; the "is my corpus trapped?" objection, owned. Claudedone = nothing is locked in — retention argument closed.
  • Wire Core Stripe checkout at Sam's price — the in-app upgrade → Core billing → plan flips to Pro. Claude prepares ⛔ needs pricedone = a real card can buy Pro (Sam does the live-Stripe flip).
  • Gate the quality dial behind Pro — route grounded chat + the Claude/70b model dial through write-service, metered, so the paid levers actually reach answers (RISK 4); free tier gets Groq-8b. Claude ⛔ needs free/paid splitdone = the oll-write dollar — a clear reason to pay.

Rung 3 v2 differentiators ⏳ queued

  • Draft-from-bullets — outline → per-section retrieval constrained to that section's chunks → generate; grounding is scoped, not global. Claudedone = a grounded first draft from an outline, section by section.
  • Gap-chips — decompose the draft into claims via /api/extract, classify entailed / neutral / contradicted, calibrated by importance × gap to avoid alarm fatigue. Claudedone = the draft flags its own unsupported claims, quietly.
  • Voice / style profile — extract a style spec from the corpus, inject into every op ("learn my voice"); a reusable primitive humaniz can share. Claudedone = ops sound like the author, not a generic model.
  • Streaming answers — extend write-service's SSE rewrite to chat + long ops so answers arrive token-by-token. Claudedone = answers stream instead of landing all at once.

Rung 4 Launch ⏳ queued

  • Merge-ready oll-write PR — the standalone product, green CI, ready to deploy. Claude Sam godone = one reviewed PR that graduates the product.
  • oll-memory deploy — merge PR #80 → its own Coolify app (Base Directory /services/oll-memory, Watch Paths, $PORT, X-Service-Token) + a private Neon oll_memory DB (pgvector, ADR-008) + Ollama running nomic-embed-text (EMBED_DIM=768). Claude prepares Sam deploysdone = the memory sidecar is live on real services, not local-only.
  • Dedicated-domain wiring — DNS A/CNAME → VPS, Coolify domain + TLS, on the new front-door name. Claude prepares ⛔ name TBD Sam deploysdone = the product answers on its own domain over HTTPS.
  • Live-Stripe go-live — flip test → LIVE Stripe, set the live webhook, verify a real-card payment flips a plan to Pro. ⛔ Sam · irreversibledone = a stranger can pay for oll-write.
  • GTM first-week push — run the launch order from the plan (academics/PKM beachhead → authors → solo lawyers/grant writers → consultants; Show HN → pay-once directories → AI directories → Product Hunt last), honest angle: "private + a real editor + you own it," never "AI writing." Samdone = real strangers in named rooms in front of a working checkout. Full targets: the GTM plan, Part II.

💸 First stranger franc

money
The money path is closed & verified (Stripe webhook delivering, keyless CHF 9 merged, /upgrade 200 — see the Control Room). Nobody has paid yet because nobody has been told. The whole theme is getting strangers in front of a working checkout — honest framing, never spam.
  • Fire the distribution burst — the copy-paste kit is ready & accuracy-checked at oll-am-humaniz-distribution-kit.html (X thread · LinkedIn EN+DE · Reddit r/writing + r/AcademicWriting · Show HN · the 4-signup email · a 5–7-day schedule). Sam posts. Sam
  • Submit the sitemap to Google Search Console + Bing (powers Perplexity). sitemap.xml/robots.txt/llms.txt + JSON-LD already ship at root — this is the submit step. Sam
  • Confirm Cloudflare allows the AI crawlers — GPTBot · ClaudeBot · PerplexityBot (a blocked bot = invisible in AI answers). Sam

🧬 Convergence — one writing engine

strangler-fig
Two writing products (humaniz + specview) each carried their own auth/billing/email/model backend. The end state is one engine: each product becomes a thin client of the shared services — Core (auth/billing/email) + oll-model (the model call) + write-service (the prompts). Strangler-fig: move behaviour to the shared services one seam at a time, then retire the per-product backend. Convergence is now COMPLETE — write-service is a 13-endpoint text-ops engine and both products are fully migrated (dev-tested, PR'd), with no local ops left. Every step reversible until the outward cut-over.
✅ Shipped this session — awaiting your review / deploy (2026-07-02). The convergence is real & complete: write-service = a 13-endpoint text-ops engine (improve · clarify · spec · draft · rewrite · expand · compress · simplify · tldr · bullets + health, plus rewrite/stream SSE + brainstorm), Core-JWT gated → frozen oll-model (Groq), 119 tests, real Groq SSE frames verified (PR #65 + PR #66 + PR #67 → stage). humaniz runs on it (PR #17, needs-review) and specview runs on it fully — brainstorm was its last local op (PR #129, needs-review) — no backend per product. And ollwrite is now a functional product (Core auth + landing + full op menu + model toggle + Dockerfile). See the design doc §00. Not deployed yet — the items below carry the finish line.
  • Migrate humaniz's text-ops → write-service — DONE (dev-tested, PR'd): deleted services/humanizer.py + the 3-pass prompts + direct gateway calls; rewrite route is a thin passthrough. Proven e2e (humaniz → write-service → Groq; ZERO direct model calls). PR #17. needs-review · not deployed
  • Migrate specview's text-ops → write-service — DONE (dev-tested, PR'd): all verbs migrated (14 local skill files deleted; brainstorm — the last one — closed once write-service gained the endpoint), real-Groq e2e, 889 tests pass; async generate/spec pipeline left as-is for later. PR #129. needs-review · not deployed
  • write-service /rewrite/stream SSE streaming — DONE (PR #67 → stage): POST /api/write/rewrite/stream emits SSE frames (chunked today because the oll-model gateway is non-streaming; forward-compatible to real token streaming). Real Groq SSE frames verified. needs-review · not deployed
  • write-service brainstorm endpoint — DONE (PR #67 → stage): POST /api/write/brainstorm — specview's last local op; adding it closes specview's final per-product seam so it can fully retire its backend. needs-review · not deployed
  • Deploy a stable write.oll.amthe unlock for everything going live. The finish line for both DONE migrations AND ollwrite: deploy write-service, run the LOCAL frontends against the REMOTE backend, then point humaniz/specview at the remote and deploy ollwrite. Claude Sam go
  • Retire humaniz-backend entirely (Sam, 2026-07-03 — "why do we need humaniz-backend?"). Code-verified: the stage write-service already owns the Core auth/plan gate AND its own free-tier quota (services/write/usage.py), so the Flask backend's rewrite path is only a contract shim (/api/v1/text/rewrite/api/write/rewrite + HumanizeResponse reshape + /usage). The increment: frontend speaks write-service DTOs directly, nginx routes product paths to oll-write, delete the backend from the compose — the TRUE "no backend per product" end state. Do after PR #17 review (it tests the shipping architecture first). Claude Sam go
  • ollwrite productionizenow a functional product (standalone at ~/Projects/ollwrite): Core magic-link auth (login → oll_token cookie → middleware-gated /editor, JWT forwarded to write-service), rebranded landing → editor flow, the complete v1 op menu, Groq/Claude model toggle, standalone Dockerfile + Coolify README (npm run build green, Playwright-verified). Remains: its own remote repo + Coolify deploy · real-Core magic-link e2e (needs live Core + inbox) · plan-gate the model toggle (Claude tier billing). Full research + architecture: oll-am-ollwrite-product-design.html · spec: oll-am-ollwrite-spec.html. Sam decides front door
  • ollwrite design → build — the 6-increment launch (design study: oll-am-ollwrite-design.html §07). Every interaction mapped → write-service endpoint → Plate.js mechanism; the 13 stage write-service endpoints cover all but two flagged gaps: a new /api/write/continue (continue-from-cursor for ghost-text — today's ghost-text hits Groq directly + un-gated, must repoint) + an optional dedicated grammar verb.
    • Increment 1 — Manuscript design system + focus mode — DONE (dev-verified, not deployed): the real /editor restyled to the Manuscript surface (cream floating page, Source Serif prose at 66ch, Inter UI, warm ink #26231C, accent #3F6E8C, toolbar removed, idle-dimming top bar, grouped ✨ menu, ⇧⌘F focus mode), still wired to the write-service — a real Groq round-trip verified, npm run build green. shipped · not deployed
    • Increment 2 — premium ✨ menu + word-diff + the Ink-In accept — the grouped on-selection menu with word-level diff and the signature Ink-In accept animation. Claude · next
    • Increment 3 — ghost-text via CopilotKit + new /api/write/continue — continue-from-cursor, repointed off the direct Groq call onto a gated write-service verb. Claude
    • Increment 4 — The Margin marginalia mode — AI as red-pencil notes in the margin, dissolving on accept via the Ink-In. Claude
    • Increment 5 — product surface — library / ⌘K / onboarding / upgrade. Claude
    • Increment 6 — Core auth ON + deploy — flip magic-link auth on, plan-gate the model toggle, ship to write.oll.am. Sam go
  • Align landing / positioning copy to the 3-placement inference model + pay-once honesty — index/vision/vs pages still say "local Ollama / pay once" loosely (External is metered → "no subscription"; "pay once" is honest only for Internal + On-device). Claude

🔒 Infra & security

prod hardening
Stage taught real lessons (see the Ollama retro): prod should bake in every one of them. Today everything shares Coolify's default network with no isolation, an internal service got an accidental public URL, and a service token leaked in chat. Prod = collect the learnings and close them.
  • Rotate the leaked OLL_MODEL_SERVICE_TOKEN — it appeared in a chat log, so treat it as burned; rotate immediately. urgent Sam console
  • Secure the deployment (prod hardening) — rotate ALL secrets (the live Stripe key too); give each service its OWN token, not a shared one, stored as Coolify secrets; network isolation (prod on its own Docker network — not Coolify's default coolify); keep internal services (ollama, oll-model) OFF any public URL; require real secrets at boot in prod; rate-limit public endpoints; non-root containers. Reference: the learnings doc. Sam console
  • Cut a proper prod environment — separate network + stage.<svc>.oll.am isolation per the CI/CD design; then today's stage-on-live-URLs becomes pure stage/dev. (Interim: stage IS the live deploy line, main kept clean.) Sam console
  • Stop unnecessary deploys — set Coolify Watch Paths per app; today every docs push rebuilds oll-core etc. (higher-value now that stage deploys live). Sam console
  • Every env var ships a default — a test value even for secrets; minimum setup, maximum defaults; real prod overrides. Claude

⚡ Models / inference

speed ↔ quality
Hosted (Internal) inference runs on CPU, so model size is the speed↔quality dial. Pick a fast default, offer a quality step-up, and let the user choose.
  • qwen2.5:0.5b fast default + llama3.2:1b for quality — both pulled (PR #64); tune for the speed↔quality point. in flight
  • Model choice in humaniz — let the user pick quality vs speed among the Ollama models; evaluate an even-smaller/faster 2nd option. Claude

📸 Products — foto

↑ now the flagship on-ramp
Superseded — folded into the flagship. The Bewerbungsfoto headshot is no longer a stand-alone "product #2." It is now the CHF 29 on-ramp of the oll.in value ladder and its live, ordered checklist lives in 🏁 oll.in — Step 1 (un-park foto) above. This block is kept only for the reusable-asset note; do the work from Step 1.
Reusable assets it draws on: trendfy's live Flux-LoRA ai-models pipeline (guest-checkout image generation) + Core's billing/email. Swiss-format CV / Bewerbungsfoto is a document-layout convention, nothing about hosting.
How this list works. Items are grouped by theme, not ranked. There's no priority label and no "do this first" gate — when we sit down to execute, we pick whichever item makes sense that session. New wants get added here as they come up in discussion; finished ones move off to the Control Room. The machine-readable guardrails the autonomous job reads live in state.json.