Before I built the marketing tool that made $0, I built a different product and never launched it. It was called briefflow. I built it in eight days, 175 commits. It worked end to end, I used it myself for two weeks, a handful of real people tested it, and it still never went public.
There’s a flattering way to tell that: I saw the retention problem coming and killed it on purpose. It isn’t quite what happened. The truer version is messier. It worked, I lived with it, real people tried it, and it never launched anyway. Not because I decided against it, but because I never really decided anything. What those two weeks and those tests taught me is the interesting part, and so is what I did with it, which was almost nothing.
Here’s the actual story, code and all.
What briefflow was
The premise came from my own inbox. I subscribe to more newsletters than any human can read - Lenny’s Newsletter, Superhuman, Snowball, simple.ai, ByteByteGo - and they pile into a labelled folder that only ever grows. Here is that folder, the week I started building:

One thousand five hundred and twenty-two unread. The guilt compounds. You don’t read them, you don’t unsubscribe, because unsubscribing feels like cutting off a knowledge source you chose on purpose.
The insight I wrote into the spec was: the backlog isn’t a queue to process, it’s a knowledge base to surface from. So briefflow didn’t try to help you get through your newsletters. It read them for you and produced one thing each day: a gazette. A single, editorial briefing - the seven-to-ten things actually worth knowing today, ranked, in a newspaper layout with a hard stop at the bottom. “That’s it for today.” The opposite of infinite scroll. The feeling of being done was supposed to be the whole habit.
The part I was proudest of wasn’t the summarising. It was what I called threads. When two newsletters covered the same story from different angles, the AI would detect the convergence and synthesise it - where the sources agree, where they diverge, a verbatim quote from each with its stance. Gmail will summarise a single email for free forever. It will never notice that two of the newsletters you actually read are circling the same argument from opposite ends. That was the bet: not a summariser, a synthesiser.
Here’s a real one it built. Three of my newsletters - Lenny’s Newsletter, Superhuman and The Product Compass - pulled into a single argument about AI agents, with each source’s verbatim quote and whether it agreed, diverged, or added a unique angle:

That panel - agreements, divergences, a quote and a stance per source - is the whole product in one screen. It’s also the part I’ll come back to.
The build
Eight days in February, 175 commits. It started life named nl-dygest and became briefflow on day two.
The stack was deliberately boring so I could move fast: Next.js 16 and React 19,
SQLite with Drizzle ORM as a single file on disk, Google OAuth for gmail.readonly,
@mozilla/readability to pull clean text out of the HTML sludge that newsletters
ship. Single user. No Postgres, no queue, no infra to babysit.
The interesting engineering was the gazette generator, and the interesting
decision there was to do the whole thing in one model call. No embeddings, no
separate scoring pass, no ranking service. I fetch up to fifty newsletters per
label, dedupe them, extract readable text, truncate each to 2,000 characters,
and hand up to thirty candidates to Gemini (gemini-3-flash-preview) in a single
structured-JSON request. One call does selection, editorial hierarchy, cross-source
synthesis, and personalisation. By my spec’s own math, about half a cent per gazette.
The prompt is really three phases stacked into one instruction. Phase one is the thread detection, and the line I’m still happy with is the guardrail:
## Phase 1: Cross-Newsletter Analysis
If you find a strong thread: set "detected": true and write a synthesis that
names sources explicitly, contrasts their perspectives, and ends with a "so what"
implication.
For each newsletter contributing to the thread:
- Extract the most representative verbatim quote (must be word-for-word)
- Describe the source's specific angle in 1-2 sentences
- Classify their stance: "agrees", "diverges", or "unique_angle"
Don't force a thread. A single compelling headline is better than a weak
synthesis. If no meaningful convergence exists, set "detected": false.
That last paragraph mattered more than anything else in the file. The failure mode of a synthesis feature is that it manufactures connections to justify its own existence - two unrelated newsletters welded into a fake “trend.” Don’t force a thread was me trying to prompt my way out of the product lying to the reader.
Phase two selects seven to ten pieces and assigns each to a section - one Headline, a few “Worth Your Time,” a handful “In Brief” - and here I fought hard for hooks over summaries. The instruction ships with worked examples so the model can’t hide in vagueness:
Write a HOOK - one sentence that creates curiosity and makes the reader want to
tap. Do NOT write a summary.
Good: "Stripe just rewrote their entire billing engine - the architectural
choices explain why most billing systems fail."
Bad: "This newsletter discusses Stripe's billing system changes."
Phase three is a personalisation pass: for every item, one line explaining why it matters to you specifically, referencing an interest you picked by name, with a concrete detail - and an explicit ban on generic filler like “relevant to your interest in AI.” There’s a language rule too: write each item in the same language as its source newsletter, so nothing gets flattened into translated English.
The whole contract comes back as one JSON object - thread, headline, worthYourTime, inBrief - which I parse, validate, and fan out across four database tables into an edition I can render and re-render. I deployed it to Fly.io in Paris, wired up a daily cron to generate the edition in the background, gave it a design I genuinely loved. It worked. I ran it against my own inbox and read it for two weeks - a real gazette, for an audience of one.

The italic relevance line under each item - “As someone interested in Product, this provides a necessary reality check on career progression” - is Phase 3 doing its job. Tap anything and the original newsletter slides in beside the summary, so the AI never gets the last word.
The reality check
On day seven - while I was still building - I stopped and wrote a document
called briefflow-reality-check.md. Not a spec. Its only job was to argue with
me. I went and read what everyone who’d walked this road had found: Meco with its
26,000 downloads, Readless, Summate, Remy, StackDigest - a whole graveyard-slash-
market of people solving exactly this. The pain is real and validated. People
sign up. Some even pay.
Then I hit the sentence that I couldn’t get out from under. I called it the Summary Paradox and wrote it down like this:
If a summary is “good enough,” did the user really need that newsletter? And if the summary isn’t good enough, what’s the point?
That’s the trap under every product in this category, and I’d built the product before I’d answered it. A newsletter you love isn’t an information payload. It’s a voice, a joke, an argument that takes four paragraphs to land. Compress Lenny into three bullets and you’ve deleted the reason to read Lenny. The better my summariser got, the more it argued for cancelling the subscription it was summarising.
And the retention question underneath it, which I also wrote down and also didn’t answer: the metric that decides whether this works was never signups. Everyone opens a new toy on Day 1. The metric is whether anyone opens the gazette on Day 14. I stared at that number - the one number that mattered - and I could not honestly convince myself it would hold. Not for strangers. Not even, if I’m honest, for me.
So by day seven I had a working product and a document explaining why it might not deserve to exist. But the document was still just me arguing with me. What actually made up my mind came from outside the code.
The problem underneath the problem
Part of the research was simply reading Reddit - real threads where people describe drowning in newsletters. And every time, someone says the quiet part: if you subscribe to more than you can read, that isn’t a tooling gap, it’s a discipline problem. They’re right. briefflow didn’t dissolve that problem, it added a layer on top of it - a smarter, better-designed layer, but still a machine that dives into an overflowing inbox and reassures you you’re on top of it. The thing actually driving the backlog was FOMO, and you don’t cure FOMO by getting more efficient at consuming the thing you’re afraid to miss.
Then I put it in front of two or three real people. The tests didn’t fail on features - the gazette worked, they liked it in the room. They failed on the only question that matters for something like this: would you come back tomorrow, with no notification pushing you? briefflow lives right next to an inbox you’re already avoiding, so why open a second thing to manage the first thing you won’t open? What does it give you beyond a clever new way to compare what four newsletters think? And in the end, are the newsletters actually getting read - or just re-packaged into another format you also won’t return to?
I couldn’t answer a single one of those. The wall was never the AI, the parsing, or the threads. The wall was habit. To work, briefflow had to change a behaviour, and I’d built a tool that quietly assumed the behaviour instead.
The part that isn’t flattering
So the kill was, for once, probably the right call. Here’s the part I’m less proud of: I never actually made it.
I wrote the doubt down on the 23rd of February, learned what I learned, and then just… kept committing features. I deployed the thing to a server for an audience of one. I went quiet for two and a half months. Then, in May, I came back - and instead of writing briefflow’s obituary, I wrote its relaunch: a detailed, phased, checkboxed plan to migrate it to Postgres, make it multi-user, swap Gemini for Claude, deploy to Vercel, and finally put it in front of people on X and Reddit. I never ran a single line of it. The last real commit is a one-line change to a gitignore file.
Sit with that sequence. I had earned, specific reasons to stop. I didn’t stop, I faded. Then I wrote a plan to un-stop, and I didn’t do that either. Even with the evidence on my side, I couldn’t turn it into a decision. I left the thing to rot in the gap between “kill it” and “fix it,” which is where most of my projects actually go to die.
If that shape sounds familiar, it’s because I did a mirror version a month later, in the open, and wrote about it. LaunchMap ended on a commit that wasn’t code either - a Reddit warm-up plan for a launch week that never came. briefflow I never launched; LaunchMap I launched to no one. Different failures, same allergy: to the ambiguous, human, no-finish-line work. Talking to users until you actually understand them. Changing someone’s habit. Showing up daily with no commit to mark that you did. I’m good at the part with a finish line, and I keep mistaking it for the whole job.
Writing an adversarial pre-mortem is genuinely good practice - it’s how I found the real problem here, and I’d recommend it. But a pre-mortem can diagnose; it can’t decide. The deciding is a different muscle, and it’s the one I keep letting atrophy.
What actually survived
There’s one thing I finished. During that February sprint I gave briefflow a design I called Zen Archivist - a warm paper-and-ink editorial system, Instrument Serif for the display type, a Washi-paper background texture, Sumi-ink text, sharp corners, no shadows, hairline borders doing all the separating. It was the most resolved part of the whole project, because visual craft is a task with a clean finish line and I reliably reach for those.
You are looking at it right now. When I built eronae, I didn’t design a new system - I ported briefflow’s. My own project files say so out loud: eronae’s stylesheet is commented “Editorial typographic primitives, ported from Briefflow,” and the design doc calls the whole thing an “editorial system derived from the Briefflow design language.” The product is on a shelf. The wallpaper became the house.
Which is about the most honest summary of that eight days I can give. I built a newsletter synthesiser that could tell you when two smart people were secretly disagreeing, deployed it, doubted it, planned its comeback, and shipped none of that to anyone. The only thing that made it out alive was the part that was never the point.
But the problem didn’t die with the product. It moved. I keep noticing a cousin of it everywhere now, including in myself: we don’t just hoard newsletters, we hoard everything. Raindrop full of articles I swore I’d read. Hundreds of X bookmarks. A LinkedIn “saved” list I have literally never reopened. All of it a content cemetery - things we meant to come back to and never did. Same shape as the newsletter backlog, same engine underneath: save now, absolve the FOMO, never return. I think there might be a real product in making that graveyard actually give something back.
And I can already hear briefflow laughing at me, because that is, once again, a behaviour problem - the exact kind I love to answer with an elegant machine that assumes the behaviour instead of changing it. So this time I’m trying to do it in the other order: sit in the problem, talk to the people who have it, understand why the bookmark gets saved and abandoned, before I write a line of the thing. The build was never where I lose. It’s everything around it. briefflow cost me eight days and taught me the lesson twice. I’d like to only need it a third time on paper.