KPR Simulator
An ad-free Indonesian mortgage calculator showing what happens after the fixed rate ends, and where instalments break

- regulated figures cited to their source
- 27
- unknown figures refused by name
- 7
- network requests; figures stay in the link
- 0
- effective rate of flat 5% over 20 years
- 7.95%
On this page
The problem
A KPR, an Indonesian home mortgage, is the largest financial commitment most households will ever make. Banks quote a fixed rate for two or three years, and then the loan floats. A family that budgets around Rp3.2 juta a month can face Rp4.8 juta in year four. Every calculator I found assumed one rate for the whole twenty years, so it hid the biggest risk in the loan.
The calculators had other gaps too. "Flat" and "efektif" interest are both advertised, they can't be compared directly, and most borrowers can't tell which one they are being quoted. The calculators show a number with no working. And nearly every one in Indonesian search results exists to collect leads for a bank or a property portal.
What I built
The page answers the question a borrower can take to the bank
I changed what the calculator asks. "Can I afford Rp3.2 juta?" becomes "My loan breaks at, say, 13.4%. My bank doesn't publish its margin over the base rate, so what is it?" The threshold page finds the exact floating rate at which the instalment passes a share of income you choose. Two edge cases get their own plain answers: already over the limit at a zero rate, and still affordable above the highest rate searched.
Every rupiah can be traced
Money is always a whole number of rupiah. Rounding is its own labelled step in the working, and it names the convention it follows. That step is where calculators drift a few rupiah from bank statements, so I made it visible. The engine never reads today's date; the month is always passed in. The same inputs give the same result forever, which matters when someone checks it against a bank statement six months later.
Two separate calculations check each other
The effective rate is worked out twice, by two routines that share no code. If they shared a helper, they could share a bug. This check also corrected my own brief. The PRD said a flat 5% is roughly a 9% effective rate. That holds over one to five years, but over twenty years the computed figure is 7.95%. The app states the computed number, and I fixed the brief.
Unknown figures are refused by name
Every regulated figure, such as the subsidy rate, price ceilings, income ceilings and tax rates, is stored with its legal basis, source link and verification date. The build fails if one has no citation. When I couldn't trace loan-to-value ratios, the minimum down payment or the subsidised loan tenor to a regulation still in force, I didn't guess. They became seven declared gaps the app names and explains in both languages. Amber marks the floating-rate band and every assumed value, and red marks the affordability limit. Nothing else uses those colours.
Your figures never leave the browser
Income and loan amounts are stored in the part of the link after the hash sign, which browsers never send to a server. The site makes no network requests and has no analytics or ads. A build check confirms the exported site calls nothing external.
Result
KPR Simulator is live, public and free of ads, in Indonesian first and English second. It shows the full payment schedule with an amber band where the rate becomes unknown. It covers the threshold rate, flat and efektif side by side, and the subsidised FLPP path with a check that names which criterion fails. It adds total cost of ownership and an extra-payment simulator. A parameter page lists all 27 cited figures. I built it alone over two days in August 2026.
The app never advises, ranks or names a bank. It states in the interface that it is not financial advice, that the floating rate is unknown and unpublished, that bank fees vary, that loan approval is not modelled, and that figures should be confirmed with the bank.
Under the hoodTechnical detail for engineers
- The engine is
(inputs, product, rulePacks) => Schedule, with no React, DOM ornew Date()inlib/. Periods are explicit{ year, month }integers. - Hand-written annuity and flat amortisation, prepayment with an early-settlement penalty, effective-rate derivation, and bisection for the threshold (
lib/rate/threshold.ts).lib/rate/irr.tsandlib/rate/effective.tsshare no code; the IRR solver feeds both the tests and the displayed figure. - Flat 5% converts to 9.11%–9.32% effective over one to five years, and 7.95% at twenty years.
- Rule packs live in
data/rules/(FLPP ceilings, BPHTB and PPh rates, traced to Kepmen PUPR, Permen PKP and tax law), validated with Zod. The seven gaps are indata/gaps.json: LTV ratios, FLPP tenor, minimum down payment, SBUM, per-kabupaten NPOPTKP, bank fees and base-rate snapshots.data/sbdk/snapshots.jsonships empty on purpose. - The FLPP 5% rate rests on a ministry statement, not an article traced to its clause, and the parameter page says so.
- Research overturned the PRD: Bank Indonesia had relaxed LTV to 100% and, for a first home, left the maximum to bank discretion.
- The conservation assertion and trace types were committed before the amortisation loop, and the rule validator before any rule data.
- 1,614 assertions across 14 test files run in about two seconds; 1,186 are the conservation sweep over tenors, rates and principals.
- Four production dependencies: Next.js 14.2.15 (
output: 'export'), React 18.3.1, React DOM and Zod 3.23.8. No finance, currency, date or charting library; the schedule elevation is hand-built SVG andIntl.NumberFormathandles display.check:offlineasserts zero external requests. - Six routes (
hitung,ambang,subsidi,banding,biaya,parameter) in two locales, plus home. Shipped JS is about 964 KB raw, above the 200 KB gzipped target. actions/deploy-pageshung atdeployment_in_progressfor about ten hours with no change on my side, then deployed in fourteen seconds on 7 August 2026. The diagnosis is written intoCLAUDE.md.- A late UX pass collapsed an eleven-control form into three named steps.
- About 9,500 source lines and 37 commits on 6–7 August 2026.
Screenshots
Hiring, or building something similar?
I'm open to full-time roles and select freelance work.