01

The Product & The Loop

What Wera is, why it was specced before it was coded, and how to read the whole system top-down.

TL;DR

Wera exists to run one loop faster than a spreadsheet can: discover a fresh internship posting β†’ tailor a truthful resume β†’ apply β†’ watch the scoreboard move. Before any code, the team wrote a full product spec and had it adversarially reviewed. Then they built the loop as one thin vertical slice β€” riskiest piece first β€” and only thickened it afterwards.

Every fall, a CS student applying to internships ends up with the same artifact: a groaning spreadsheet with 80 rows, half-remembered statuses, and a resume that's identical for every company. Wera's bet is that the job hunt isn't a tracking problem β€” it's a momentum problem. The product's memorable thing is a scoreboard: applied this week vs. quota, rendered like a serious instrument, that makes you want to move the number.

Think of Wera as a flywheel with a gauge bolted to it. Each part of the product exists to remove friction from one push of the wheel: discovery removes "where do I even find postings," tailoring removes "rewriting my resume takes an hour," and the pipeline removes "wait, did I apply to this already?" The gauge β€” the scoreboard β€” is what makes you push again tomorrow.

Meet the cast

Before tracing any code, hear the components introduce themselves:

The build journey began on paper

The git history starts with something unusual: two commits of documents before any scaffold. That's not procrastination β€” it's the cheapest de-risking there is.

1
Stage 1 Β· Before code

Write the spec β€” then let reviewers attack it

A 1,200-line product spec was written, then reviewed by engineering, design, and a second AI model before a single file was scaffolded.

docs/SPEC.md defines the loop, ten application statuses, the data model per phase, and hard success thresholds ("≀10 minutes from job URL to approved PDF"). Then it went through adversarial review β€” and the review report is committed at the bottom of the spec itself.

What

A reviewed blueprint: docs/SPEC.md, DESIGN.md, and docs/IMPLEMENTATION.md (the milestone order).

Why

A wrong sentence costs a minute to fix; a wrong schema costs a week. Review findings β€” like "your differentiator ships too late, move it to Phase 1" β€” reordered the entire plan while it was still words.

How

Multiple review passes (engineering, design, a second model as an outside voice) each left findings; accepted ones were folded into the spec with dates and rationale, and the verdict table is committed in the document.

2
Stage 1 Β· Before code

Order milestones by risk, not by convenience

Milestone 1 wasn't the login page β€” it was proving LaTeX could compile to PDF in the target runtime at all.

docs/IMPLEMENTATION.md is blunt about it: "Do not reorder: M1 (the compile spike) is first because it is the least-proven link in the product's critical path." If Tectonic couldn't compile the real resume template inside a background job, the product's differentiator was dead β€” better to learn that in week one.

What

Six milestones, M1β†’M6, each ending "green and shippable," committed as a handoff document any coding agent (or human) could execute.

Why

Risk-first ordering means the thing most likely to kill the project gets the most calendar time to be replaced if it fails. The spec even names the fallback: HTML-to-PDF printing.

How

Each milestone has tasks, a verification gate ("CI green; a template using \write18 fails safely"), and a paste-ready prompt. M4's note says it all: "This milestone is the product."

3
Stage 2 Β· Scaffold

Scaffold the monorepo with one-way arrows

One app, five packages, and a rule: the app imports packages, never the other way around.

The monorepo uses pnpm workspaces + Turborepo. The spec explicitly bans a speculative apps/worker directory: "Do not create the directory until that limit is actually hit."

What

apps/web plus packages/{core,db,ai,connectors,resume} β€” the boundaries you saw in the group chat.

Why

Package boundaries are cheap walls: they make "domain logic can't secretly depend on the UI" a compile error instead of a code-review hope.

How

Each package exports factories and pure functions; @wera/core imports nothing at all, so the rulebook can never be contaminated by I/O.

Reading the system top-down

Here's the actual home page β€” the whole read path of a screen, in eleven lines. This is what "server components call stores directly" means:

apps/web/src/app/page.tsx

export default async function Home() {
  const { rows: applications, error } = await loadApplications();

  return (
    <main className="min-h-screen bg-ground text-ink">
      <AppHeader />
      <ScoreboardBand applications={applications} />
PLAIN ENGLISH

This page is an async function that runs on the server β€” it can await data before any HTML leaves the building.

It loads the user's applications by calling a plain function β€” no HTTP request, no API endpoint, just a function call into the database layer.

Then it returns the screen…

…a page shell using the design system's tokens ("ground" paper background, "ink" text)…

…the persistent header…

…and the scoreboard band β€” the product's hero β€” fed directly with the data loaded three lines up.

πŸ’‘
No API layer is a decision, not an omission

In a classic stack you'd find GET /api/applications between the page and the database. Wera has none: reads happen at render time on the server, writes go through server actions. Fewer moving parts, and the type system flows unbroken from SQL to JSX.

The core idea: ship the loop thin

Imagine building a water slide. You could perfect the ladder for a month, then the platform, then the slide, and discover at the end that water doesn't reach the top. Or you could build the entire slide, skinny β€” a trickle of water, a short drop β€” and ride it on day three. Wera did the second: paste a job, analyze it, generate a PDF, mark applied, watch the number move. Every later feature just widened a slide that already worked.

This is the vertical slice (or "walking skeleton") strategy: implement one end-to-end path through every architectural layer before elaborating any single layer. It front-loads integration risk β€” the failures that live between components, which are the expensive ones to discover late. The spec's phase ordering (Β§17) records the reasoning: the original CRM-first plan put the differentiator in Phase 3, "plausibly after peak application season" β€” a scheduling failure mode, not a technical one.

Tradeoff: a thin slice ships with known thin spots (fit scores existed in the backend but were hidden from the UI until trustworthy β€” a deliberate, documented decision). The failure mode of the alternative β€” layer-by-layer construction β€” is a system that is 80% "done" for months with zero user-visible loops closed.

Check your bearings

You're starting a project like Wera. Following its playbook, what do you build in week one?

A teammate reports the pipeline page shows stale data and asks you to "check the API endpoint." In Wera, where do you actually look?

Why put the status state machine in a separate @wera/core package instead of a utils.ts inside the web app?

πŸŽ“ Level Up

Vertical slices & risk-first sequencing

What you saw in this module has two names worth keeping: the walking skeleton (one thin end-to-end path through every layer, working, before anything is elaborated) and risk-first sequencing (spend week one on the thing most likely to kill the project). Together they're the difference between "80% done for six months" and "usable in week three."

Best practices
  • Identify the least-proven link on the critical path and spike it first β€” with a named fallback if it fails.
  • Write the spec's success metrics as thresholds you can fail ("≀10 min URLβ†’PDF"), not vibes.
  • Get the plan reviewed while it's still words β€” reviews of prose are 100Γ— cheaper than reviews of systems.
  • Ship the whole loop thin; let real usage reorder the backlog.
Common pitfalls
  • Building foundations for months because "everything depends on them" β€” foundations are only right once a real slice exercises them.
  • Scaffolding speculative directories (apps/worker) "for later" β€” YAGNI applies to folders too.
  • Treating the demo-ready UI as progress when no end-to-end path works behind it.