Lulu Bank: AI Banking App
Most banking concepts are screens. I wanted one where the money actually moves.
Solo. I designed and built the whole thing with AI coding agents: the Expo app, the Express API, the Postgres schema, and the AI assistant.
Role
Designer and Builder
Category
Vibe Coded · Fintech
Timeline
2026

6
Screens: home, transactions, cards, chat, profile, transfer
1
Postgres ledger with atomic transfers
SSE
Streaming AI assistant
IBAN
Mod-97 valid accounts, generated per user
Solo
Designed and built by one person
“Powered by AI · Not financial advice”
From the app's assistant screen
Lulu Bank is a digital banking app I built for myself, end to end, using AI coding agents. It is not a Figma prototype with tappable hotspots: it is an Expo mobile client talking to an Express API over a real PostgreSQL database, where a transfer actually debits one account and credits another.
I wanted to find out what happens when a designer stops handing off and starts shipping. The answer, mostly, is that the interesting problems move from 'what should this look like' to 'what happens when two people send money at the same time'.
Vibe coding gets you a convincing screen in minutes. It does not get you a bank. The hard parts showed up immediately:
Fake data hides the real design problems
An agent will happily hardcode a balance of €6,820 and call it done. But a balance that never changes never forces you to design the empty state, the failed transfer, or the race between two screens.
Money needs to be correct, not plausible
A transfer that looks right but leaves the ledger unbalanced is worse than no transfer at all. Correctness had to live in the database, not in the UI.
AI features drift into decoration
An assistant that answers 'what can you do?' with marketing copy is a demo. It had to read the actual account and act on it.
Design and code can drift apart fast
With no handoff step, nothing stops the app and its API from describing money differently. That gap has to be closed structurally.
The core problem: make an AI-built banking app where the money is real, the failures are handled, and the assistant is a feature rather than a widget.


Put correctness in the database
Transfers run as a single Drizzle transaction against PostgreSQL. The API rejects self-transfers, insufficient funds and unknown IBANs before anything is written, so a half-completed transfer cannot exist.
Give every account a real IBAN
Each new user gets a generated, mod-97-valid IBAN rather than a random string, so transfers look up a real counterparty and the transaction history can join back to the person who sent the money.
Treat auth as a first-class surface
Signup, login and logout with scrypt-hashed passwords and random 32-byte bearer tokens stored as sessions. The design of the signed-out state mattered as much as the dashboard.
Make the assistant do the work
The AI screen streams over SSE and opens with the actions people actually want, pay €25 to Marco, show my latest transfers, request €40 from Emma, instead of an empty prompt box waiting for inspiration.
Generate the contract, don't retype it
The API is described once in an OpenAPI spec, and Orval generates the typed client hooks and Zod schemas from it. The app cannot quietly disagree with the server about what a transfer is.
The app runs as a real product rather than a prototype:
A working ledger
transfers move money atomically between two IBANs, with self-transfer, insufficient funds and unknown-account cases all handled explicitly.
Six connected screens
home, transactions, cards, AI chat, profile and transfer, each reading live data rather than fixtures.
A streaming assistant
the AI screen answers over SSE with suggested actions grounded in the account, not a generic chatbot.
A typed contract end to end
one OpenAPI spec generates the client hooks and validation schemas, so the app and API stay in step.
Building it myself changed what I notice as a designer. Most of the decisions that made the app feel trustworthy were not visual: they were about what the system does when something goes wrong.
AI writes the screen, not the system, the agent produced a balance in minutes and a correct ledger only after I designed the transaction rules myself.
Correctness belongs in the database, putting transfer validation in a single Postgres transaction removed a whole class of states the UI would otherwise have to explain.
Generated contracts beat good intentions, one OpenAPI spec generating both client hooks and schemas stopped the app and API drifting apart with no handoff step.
Suggested actions beat an empty prompt, opening the assistant with real account actions made it a feature instead of a chat box.


Contact me
Have a project in mind, or just want to say hi? I'm always open to new conversations.