Building GrammarLens

I built this app to find out whether I could take something from a question to a finished product on my own. This is what actually happened, including the parts that didn't work.

Back to the product

The problem I picked

Grammar checkers correct you. They rarely teach you. Someone can accept the same correction fifty times and still not know why their version was wrong — the tool has removed the mistake but left the misunderstanding in place.

The bet was that an explanation delivered at the moment of the mistake is worth more than a correction, and that a language model makes that explanation cheap enough to give away on every check.

To fill in: one or two sentences on what made you choose this problem specifically — your own experience, something you noticed, a gap you kept running into.

What four people told me

I interviewed four people who use English regularly but aren't native speakers. Four is a small number and I won't pretend otherwise — it's not enough to size a market. It was enough to test whether my assumptions about behaviour held up, which is what I needed at that stage.

To fill in: the two or three findings that actually changed the product. The most useful thing you can write here is a belief you held going in that turned out to be wrong.

Deciding what not to build

I wrote a PRD before writing code, mostly so that I'd have something to argue with later. The useful half of it was the list of things I deliberately left out.

To fill in: two or three features you cut, and the reason for each. Cuts are the strongest signal on this page — they show judgement under constraint, which is the actual job.

Cost as a design input

GrammarLens calls a language model to produce each explanation, so usage has a direct marginal cost. As a solo project with no revenue, that meant the economics had to be part of the design rather than something to solve later.

Three decisions came out of that:

  • Batched evaluation. Grouping checks into a single request instead of firing one per sentence, which cut the number of calls substantially.
  • User-selectable practice length. Framed to the user as a convenience — pick a short or long set. It's also the main lever on cost per session.
  • Local storage with sqflite. Practice history lives on the device. No backend to run, no server bill, and a much simpler privacy story.

Each of these has a real trade-off. Batching adds latency. Local-only storage means history doesn't follow the user to a new phone. I took both, because a product I can afford to run beats a better one I can't.

What changed after testing

I put the build in front of testers and ran two rounds of changes based on what came back. The second round included a full visual pass, moving the interface to Material 3 for consistency and legibility.

To fill in: what specifically changed in round one and round two, and what prompted each. Concrete before-and-after beats a general statement that you iterated.

Where it stands

The app is complete and going through App Store submission preparation. The next milestone is a public build and usage data from people I've never met — which is the point at which most of what I currently believe about this product becomes testable.

Product page