How We Built JE-PFM with AI: From Spec to Production

The story of how we used domain-driven design, 135 Storybook stories, and AI-generated proof of concepts to build a personal finance platform.

Cover Image for How We Built JE-PFM with AI: From Spec to Production

Building a personal finance platform is complex. Ours spans 10 financial domains, 22 database tables, and 63 distinct use cases — from importing bank statements to tracking budget goals to managing recurring expenses. Rather than starting with a UI and bolting on features, we took an unconventional approach: get the domain architecture right first, then use AI to prove it works.

Here is the story of what we learned along the way.

The Foundation — Domain-Driven Design

Before writing a single React component, we invested heavily in domain modeling. We broke the platform into 10 independent financial domains: accounts, transactions, imports, tags, budgets, expenses, goals, alerts, notifications, and users. Each domain follows a strict 3-layer architecture:

  • Data-access — TanStack Query hooks wrapping Supabase client calls, with Zod validation at every boundary.
  • Feature — Pure business logic hooks that orchestrate data-access calls. Calculations, filtering, derived state.
  • UI-MUI — React components built with Material UI and Emotion, consuming only the feature layer.

This layering is not just organizational neatness. It means each domain can evolve independently. A change to how budgets are calculated never risks breaking the transaction import flow. Teams (or future contributors) can work on different domains without stepping on each other.

The tradeoff? It takes real discipline. You cannot skip layers. The UI cannot reach past the feature layer directly into data-access. Cross-domain imports are forbidden. These constraints feel rigid at first, but they pay dividends as the system grows.

Documenting Everything in Storybook

We documented every component in Storybook — 135 stories with 911 interactive variants covering every form, table, chart, and dialog across all 10 domains. This was not busywork. The stories became our source of truth for how components should look and behave, and they caught integration issues before they ever reached a browser.

Storybook also served as the communication layer between design intent and implementation. When someone asks "what does the budget creation flow look like?" the answer is a URL, not a Figma link that may or may not match the code.

The Component Demo — Proving Integration

To prove the domain packages actually work together, we hand-crafted a Component Demo app. This is not auto-generated scaffolding. It is a carefully assembled showcase of every domain's UI components connected to real data hooks. Building it forced us to consume our own packages the way a downstream app would, which surfaced API awkwardness and missing exports that unit tests alone would never catch.

If you cannot build a working demo from your own packages without hacks, your packages are not ready.

The AI Experiment — One-Shot Proof of Concept

Here is where it gets interesting. We wrote a comprehensive specification document covering all 63 use cases, 14 Zod schemas, and 22 Supabase tables. Then we fed that spec to an AI and asked it to generate a working Vite single-page application.

The result: the Oneshot POC — a fully functional prototype generated in a single AI session. It has authentication, account management, transaction views, import workflows, budgets, and expense tracking. All built from the specification alone.

This was not about replacing developers with AI. It was a litmus test. If an AI can read a specification and produce a working application from it, then the specification is genuinely complete. If it cannot, there are gaps — ambiguous requirements, missing edge cases, unstated assumptions. The AI session became, in effect, the most thorough spec review we have ever done.

Were there rough edges in the generated code? Of course. But the architecture held. The domain boundaries made sense. The data flowed correctly between layers. That told us what we needed to know.

The Production App — Bringing It All Together

With the architecture validated, we chose MakerKit as the production shell. It provides multi-tenancy, billing, admin dashboards, and team management out of the box — infrastructure we did not want to build from scratch. The JE-PFM domain packages plug into this shell, bringing all the proven financial functionality into a production-grade SaaS platform.

This is the part that the upfront architecture work made possible. Because each domain is a self-contained package with clean APIs, wiring them into a new host application is straightforward. The Component Demo already proved it works.

What We Actually Learned

The honest takeaway is that AI did not shortcut the hard work. The real effort was in the domain modeling, the Storybook documentation, and the specification writing. That took weeks. What AI did was compress the validation phase from additional weeks down to hours. Instead of building a throwaway prototype by hand to test our assumptions, we got one generated from the spec and learned immediately where the gaps were.

If you are building something complex, invest in your specification first. Make it precise enough that a machine can act on it. You will end up with a better spec, a faster feedback loop, and more confidence in your architecture before you commit to production infrastructure.

The entire platform is open-source on GitHub. Take a look, open issues, or fork it for your own use case.