Most web applications ship APIs that look complete on paper but have never been tested by a real client. The web app — the only consumer — bypasses the API entirely, rendering data server-side with template logic. The API exists, the docs page works, but nobody has actually built anything against it.
The Web App Can Cheat
Django (or Rails, or any server-rendered framework) can cheat. Need a list of projects with their task counts? Throw a queryset annotation into the view, pass it to a template tag, done. The data never touches the API.
This means:
- Endpoints that return incomplete data go unnoticed
- Missing filters, search, and custom actions aren't felt
- Inconsistent URL patterns don't matter when the server handles routing
- Data shapes that would be awkward for a client are invisible
A Native Client Can't Cheat
When you build a desktop or mobile app against your own API, every shortcut is exposed:
- Missing endpoints: The Flutter app tried to load events and hit a 404 — the ViewSet existed but wasn't registered in the main router. The web app worked fine because it never used that route.
- Fragmented paths: Notes at
/api/notes/, messages at/messages/api/threads/. Three separate routers for one API. A web app doesn't care. A mobile developer stares at this for an hour wondering what they're doing wrong. - Missing actions: Need to filter tasks by project AND status? The web app just chains
.filter()in the view. The API might not expose those query parameters at all. - Incomplete responses: The web template can call
file.derived_files.countin a loop. The API serializer might not include that field, because nobody asked for it.
The Hidden Cost to Outside Developers
This is where it really hurts. You ship your API, someone gets hired to build an integration, and they hit wall after wall:
- Endpoints at inconsistent paths
- Filters that work on some resources but not others
- Data shaped differently between similar endpoints
- Custom actions that aren't documented because the web app never needed them
And they blame themselves. "I must be doing something wrong." They spend days debugging what's actually a gap in your API. They might not even realize the problem is on your side — they just think your API is hard to work with and move on.
You'd never hear about it.
The Native App as First External Developer
Building a desktop or mobile client against your own API is the cheapest way to find these problems before a customer does. Every pain point the native app hits is a pain point an integration partner would hit.
In practice, building the AskRobots Flutter app exposed:
- An events endpoint that was registered at the wrong path
- API path fragmentation across three separate routers
- Missing REST endpoints for features that only had MCP access
- Dashboard data that had no API at all — the web page aggregated it server-side
- The realization that 5 features could be added immediately (API ready) while 5 others needed backend work first
None of this was visible from the web app. Everything worked. The API just hadn't been pressure-tested.
The Virtuous Cycle
Each client you add tightens the whole system:
- Flutter app tries to build a screen → finds API gap
- Fix the API for Flutter → MCP server gets better (same endpoints)
- Better MCP → AI agents work more reliably
- AI agents hit the API harder → find more edge cases
- Outside developers eventually connect → everything just works
The first native client is the most valuable one. Not because of the app itself, but because of everything it forces you to fix underneath.
Comentários
No comments yet. Be the first!