The Full Build Guide: Every Milestone, In Order
This is the complete, chronological story of how this project was built, milestone by milestone. Each milestone here is a real, deployed step -- not a plan that was later abandoned. For the deep dive on any specific bug mentioned here, see troubleshooting.md. For why a particular tool was picked, see tech-stack.md. For the supervision process itself, see how-i-supervised-codex.md (also on this site as "Process").
Milestone 1 -- Project scaffold
Next.js, TypeScript, Tailwind, and the initial Prisma schema. The folder structure and README were set up before a single real feature existed, so every later milestone had a consistent place to live.
Milestone 2 -- The news agent pipeline
A local script that fetches RSS feeds, deduplicates against already-saved articles, classifies and scores the rest with a local AI model (Ollama), ranks them, and generates draft social posts for the best ones. Runs locally on a Mac via a scheduled job, not on the deployed server, because the AI model needs real, persistent compute that a serverless platform like Vercel cannot provide.
Milestone 3 -- The dashboard
A password-protected admin site (Overview, Articles, Review Queue, Agent Config) reading the results the local agent saves to a shared database.
Milestone 4 -- Editable prompts and scheduling
The AI classify/generate prompts became editable from the dashboard instead of hardcoded, with version history. Daily scheduling was added via launchd (macOS's built-in scheduler).
Milestone 5 -- OpenAI as an alternative provider
A second AI provider option alongside Ollama, for anyone who would rather pay per request than run a local model.
Milestone 6 -- Real social publishing
LinkedIn and Twitter/X posting, using each platform's real API with OAuth. Verified with a real, live post before trusting it further.
Milestone 7 -- This documentation site
The public "How It Was Built" section itself, so the reasoning behind every decision would survive beyond a single conversation.
Milestone 8 -- Editable drafts, tooltips, and the first visual identity
Generated posts became editable before publishing. Tooltips were added across the dashboard. The first deliberate visual design pass (a cyan-accented, data-forward look) replaced the default shadcn styling.
Milestone 9 -- Hiding noise, making the pipeline visible, LinkedIn Company Page groundwork
Twitter/X drafts hidden by default (never actually being posted). A plain-English explanation of how article discovery actually works, shown directly on the Overview page. The LinkedIn Company Page code path was built, though it later turned out LinkedIn's own approval process for that specific feature had a hard structural blocker (see Milestone 10).
Milestone 10 -- Zernio: a free, real path to Company Page posting
LinkedIn's Community Management API turned out to require a brand-new, completely clean developer app -- the existing one already had other products on it, and LinkedIn will not grant that approval to an app with anything else attached. Rather than wait on a second application with no fixed timeline, Zernio (a third-party service that already holds that LinkedIn approval) was used instead, at zero cost since only one account was ever needed and Zernio's first two connected accounts are free.
Milestone 11 -- Analytics, lighter polling, and a strict grayscale palette
A real analytics page using the AI's own importance scores as a content quality signal, dependency-free CSS bar charts (no charting library), and auto-refresh that pauses while the browser tab is not visible. The first attempt at a deliberately minimal black/white/grey palette.
Milestone 12 -- An exact palette and a Review Queue redesign
A precisely-specified 5-step grayscale palette, and a real usability pass on the Review Queue: a segmented Personal/Company control replacing a bare HTML select, and clearer visual hierarchy.
Milestone 13 -- Fixing platform-mixing and adding a LinkedIn preview
Twitter and LinkedIn drafts had been rendering mixed together in one grid, which looked cluttered especially right after a page load. The decision of which platforms to show was moved to the server (eliminating a client-side loading flash entirely), and drafts were split into real Platform tabs. A live LinkedIn post preview was added, showing an approximation of how a post will actually look once published.
Milestone 14 -- A real layout bug, and a new color direction
A leftover two-column grid (from before the platform-tab split) was still forcing a LinkedIn card into a half-width column with wasted space beside it -- fixed by removing the outer grid and letting each card use full width internally. The palette changed again, this time to a navy/slate/ blue-grey scheme, based on direct user feedback that the grayscale version did not look right.
Milestone 15 -- Iterating again: a pastel, editorial palette
More feedback led to a third palette: Medium.com's real, confirmed brand accent green, blended with a soft pastel neutral base. This kind of repeated iteration is normal and expected when a builder cannot see its own rendered output the way a person can -- see the note on this in tech-stack.md.
Milestone 16 -- Real auto-publish, safely
Approved posts can now be published automatically on a schedule, without needing a person to click Publish. Since Vercel's free-tier scheduler can only fire once a day at an imprecise time, a free external scheduler (pinging a secret-protected route every few minutes) was used instead, so the time and destination could be genuinely dashboard-configurable with a real, accurate countdown.
Milestone 17 -- Genuinely mobile-responsive
A real collapsible mobile navigation menu, stacked card layouts for Articles on small screens, and a serious bug found only by measuring actual rendered width at a real phone size: the Review Queue was rendering nearly 3 times wider than a 375px screen, from a CSS Grid default plus a long unbroken URL that could not wrap. Both root causes were fixed, not just the symptom.
Milestone 18 -- Auto-publish gets an explicit opt-in, and posts can go back to draft
Being approved alone no longer means a post can be auto-published -- each post now needs a second, deliberate "include in auto-publish" signal. Approved or rejected posts can also be moved back to draft for reconsideration (blocked for already-published posts, since that would misrepresent something already public).
Milestone 19 -- A real race condition, fixed at the root
The Agent Config page's auto-publish switch could appear to "turn itself off" if someone interacted with it before the page's initial data fetch had finished loading -- the fetch would silently overwrite whatever the person had just clicked. Every control is now disabled until the initial load genuinely completes, closing the race structurally rather than patching the symptom.
What this adds up to
Nineteen real, deployed milestones, each one verified against the actual running application (not just read from source code) before being called done. The troubleshooting.md file has the detailed postmortem for every real bug hit along the way; this page is the map of how they connect.