Published 2026-09-19 · 4 min read

Between the idea and the app: a PRD

Before PFEx's first line of code there were documents. This is how I talked an idea through with AI into a PRD, split that PRD into components and milestones, and then built it week by week.

阅读中文版

I wanted to build an app that treats one person's finances as a market. Before I touched a screen or a line of code, I did something else: I talked a vague idea through with AI until it became a document I could execute.

It starts with one idea

All I had at first was one sentence: bookkeeping apps hand you a list of transactions, and I want you to see your money the way you watch an index.

That sentence is a direction, not a requirement. It does not say what question the app answers, or what it refuses to do. So instead of writing code, I sat down and forced it into those sentences.

What the idea itself turned out to look like, I wrote up in the original concept piece. This one is only about how I turned it into an app, step by step.

Talking the requirements through with AI

I gave that sentence to the AI and went one round at a time. I did not ask "do you think this is good". I asked the details I could not answer myself. Three came up most: what question does it actually answer; in that securities vocabulary, which words really have to land in the data model and which are only for the screen; and what will it refuse to do.

The answers all became product decisions, and they are not the subject here. What mattered was the way I asked: it turned my "I think this is nice" into "this is the question I answer, and this is what I will not do".

Having AI write the PRD

Once the requirements were clear, I had the AI organise them into a PRD, doc/prd.md. It went through three rounds, and the last one rewrote it against the current implementation, replacing the two stitched-together drafts before it.

I only insisted on one thing: the PRD has to be a baseline I can compare against. Every task's acceptance criteria had to point back to one of its clauses.

Splitting the PRD into tasks

A PRD says what, not how to start. So I had the AI split it into tasks, which became doc/tasks.md, marked v1.0, dated 19 September 2026.

The split is by component, not by screen. Everything falls into four buckets: infrastructure (core and data), computation engines (pure Dart under domain/engine), UI components, and page modules. The direction between layers is fixed: pages depend only on engine interfaces, engines touch no IO, data implements repositories, and core is available to everyone.

I also wrote in a few hard rules to use as code-review gates. Two I still remember:

  • the engine directory may not import drift, flutter or dart:io, so engines can be unit-tested on their own;
  • every user-facing string must come from the localisation files, no hard-coding.

Then milestones. The whole thing was laid out as 12 weeks, M0 to M11, one theme each: infrastructure and data, the core transaction flow, the engine cluster, then the market UI, review, the status system, bilingual, the remaining pages, a releasable MVP, Japanese and Korean, AI reports, and finally polish and store submission.

For every task I required four things: which component it belongs to, which task it depends on, which PRD clause its acceptance criteria map to, and what test closes it out. Only with all four is a task genuinely independently buildable and independently acceptable.

Building it milestone by milestone

With the task table in hand, the rest was moving week by week. I had the AI take one task from a milestone at a time, delivering the code and the tests together, per the conventions above.

Take the engine week. I wrote the acceptance criteria and the test requirement first: empty account, negative balance and transactions spanning days all had to be covered. The AI then delivered the engine and its unit tests against that standard. Because the engine is a pure function that touches no IO, those cases ran directly as unit tests.

Later the AI wrote pages, components, localisation copy, and unit tests. At the end of each week I checked the acceptance criteria myself and sent back whatever did not match. In this workflow the AI produced a lot, but the standard for "is this right" was always the clauses I had written into the documents first.

What I learned

Looking back, the rounds I spent on requirements at the very start paid for themselves, and they paid off in the process:

  • requirements written as acceptable clauses gave the AI a standard to check against instead of guessing;
  • writing down what the app refuses to do kept the AI from quietly adding things while it split the tasks;
  • tasks written as "component plus dependency plus acceptance plus test" are what made week-by-week independent delivery possible;
  • when a document changes, the latest version is the one that counts, and the AI starts from it every time.

Ideas are easy to have; a document you can accept is not. Between the two sit the rounds I spent at the start, talking it through with the AI.

← PreviousThe original concept: one person's finances as one market

Back to devlog · Back to PFEx