LoanLens — Behind the Build
💡 Inspiration
It started with a number: 391%.
That's the average APR on a two-week payday loan. It's legal in most states. Most borrowers never see it — because lenders bury it in fine print, express it as a flat "finance charge," or simply never mention it at all.
We kept coming back to one question: what if the person signing that contract actually understood what they were agreeing to? Not after the fact. Not after the debt spiral. Before they signed.
Financial literacy isn't just about teaching people budgeting basics. It's about making sure that when someone is sitting across from a lender — stressed, time-pressured, and desperate for cash — they have the same clarity that a finance professional would have. LoanLens is our attempt to give everyone that clarity, instantly and for free.
🔨 How We Built It
LoanLens is a single-file HTML application — no framework, no backend
dependencies beyond a lightweight API proxy. The entire product lives in one
.html file.
Stack
| Layer | Technology |
|---|---|
| Frontend | Vanilla HTML/CSS/JS |
| AI (document extraction) | Claude AI (vision) |
| AI (analysis + chat) | Claude AI (text) |
| Styling | Custom CSS with CSS variables |
| Math engine | Pure JavaScript |
The APR Calculation
The core of the app is converting opaque loan terms into a single honest number: the true Annual Percentage Rate. Here's the formula we use:
$$ \text{APR} = \frac{\text{Total Payback} + \text{Fees} - \text{Principal}}{\text{Principal}} \times \frac{365}{\text{Term (days)}} \times 100 $$
For example, the classic payday loan scenario:
$$ \text{APR} = \frac{390 - 300}{300} \times \frac{365}{14} \times 100 = \frac{90}{300} \times 26.07 \times 100 \approx 391\% $$
That single number — honest, unambiguous — is what most lenders never show you.
Architecture
The app has three flows:
Upload flow — User drops an image or PDF. We base64-encode it and send it to Claude's vision API, which extracts every financial term into structured JSON. We then run the APR formula and pass everything to the analysis prompt.
Manual flow — User types in the raw numbers. We skip the vision step and go straight to analysis. Useful when someone has verbal or phone-quoted terms.
Demo flow — Pre-loaded scenarios (payday, auto, rent-to-own) that run the full pipeline with synthetic data, so judges and users can see everything without needing a real document.
After analysis, a contextual chatbot is initialized with full knowledge of the specific loan, so users can ask follow-up questions like "what happens if I miss a payment?" and get answers grounded in their actual numbers.
📚 What We Learned
Prompt engineering is product design. The quality of Claude's output changed dramatically based on how we structured the system prompt. Getting the model to return clean, parseable JSON — with fallback defaults for missing fields — took more iteration than the UI did.
APR is genuinely hard to communicate. The number alone isn't enough. We learned that translating
391%into$6.43 per dayor$90 on a $300 loanis what actually makes people react. Abstract percentages don't land. Concrete dollars do.Privacy framing matters. Early testing showed users hesitated to upload financial documents. Adding the privacy modal — explaining clearly that nothing is stored, no account is needed, and the backend is stateless — meaningfully reduced that friction.
Single-file architecture has real tradeoffs. Keeping everything in one
.htmlfile made iteration fast, but managing state across three screens without a framework required careful discipline.
🧱 Challenges
1. Extracting structured data from unstructured documents
Loan documents vary wildly. A payday lender's one-page slip and a 40-page
mortgage disclosure use completely different terminology for the same concepts.
Getting Claude to reliably identify principal, totalPayback, termLength,
and termUnit across all of them — and gracefully handle missing fields —
required building a robust JSON schema and fallback logic.
2. Calculating APR without a term in days
Many loan documents express terms in months or years, not days. We had to build a unit-conversion layer:
$$ \text{Term}_{days} = \text{termLength} \times \begin{cases} 1 & \text{days} \ 7 & \text{weeks} \ 30.44 & \text{months} \ 365 & \text{years} \end{cases} $$
Using 30.44 (the average days per month) rather than 30 meaningfully
improves accuracy on longer-term loans.
3. Keeping it honest without being alarmist
We wanted LoanLens to be genuinely helpful — not just a tool that screams
"PREDATORY" at everything. Building the three-tier verdict system
(fair / warning / predatory) with loan-type-specific APR thresholds was
important so a 15% personal loan and a 391% payday loan are treated
very differently.
4. Making it work without an account
Every design decision — stateless backend, no database, no auth — was made deliberately to lower the barrier for the people who need this most. The tradeoff is that there's no history, no saved reports. For this use case, that's the right call.
🎯 The Bottom Line
LoanLens is a one-hackathon build, but the problem it addresses is a multi-billion dollar crisis. Predatory lending is legal, widespread, and disproportionately harms people with the fewest options.
We believe financial literacy isn't a curriculum — it's a tool you pick up at the moment you need it. That's what we tried to build.
Built With
- ai
- api
- canvas
- claude
- css
- html
- javascript
- vanilla
Log in or sign up for Devpost to join the conversation.