Open Pajak is a fully client-side tax calculator for the Indonesian tax regime. The SPA bundles calculators for PPh 21/26, PPh 22, PPh 23, PPh Final Pasal 4(2), PPN, and PPNBM, and turns every calculation into a transparent table + formula narrative so practitioners can audit each step. All inputs stay in the browser—no personal identifiers (NIK, names, addresses) are ever collected or stored.
- Production: https://openpajak.hamardikan.com
(Deployable bundle hosted on Cloudflare Pages – mirrors the code insideopen-pajak-v1/.)
- ✨ Receipt workspace — save simulations to local storage, export Excel/PDF receipts, and print the redesigned letterhead with CTA buttons to the website & GitHub repo.
- 📤 Bulk upload via Excel — template download + offline uploads create grouped receipts, now expandable inline with per-entry preview/export.
- 🌐 Full localization pass — language changes now re-run calculations instantly (tables, waterfall notes, summaries, and export layouts react to locale switches).
- 📚 Improved history drawer — search + sort controls, scrollable layout, and batch receipts shown in place.
- 🖨️ Polished PDF — hidden iframe print workflow to avoid blank tabs and a full-width navy header that matches the site branding.
- Multi-tax coverage: switch between
/pph21,/pph22,/pph23,/pph4-2,/ppn, and/ppnbmvia the TanStack Router poweredAppShellnavigation. - Domain-specific forms: each route renders a
TaxPageLayoutwith tailored inputs (subject types, PTKP, TER category, DPP overrides, inclusive/exclusive PPN mode, dsb) plus sample presets to help users learn the flows. - Calculation transparency: pure functions in
src/lib/tax/*.tsemitbreakdownrows that surface DPP, PKP, tariff tiers, and rounding for every scenario.FormulaExplanationCardandFormulaSourceNotereference the official Buku PPh 21/26 guidance (public/Buku_PPh2126_Release_20240108.pdf). - Shared UI primitives: form fields, number formatting, cards, tables, and alerts live in
src/components/**for consistent styling with Tailwind + shadcn/ui tokens. - Offline-first SPA: built with React 19, Vite, and Bun. No backend, so the bundle can be deployed to static hosting (Cloudflare Pages, Netlify, dsb.).
open-pajak/
├─ README.md # This file
├─ open-pajak-v1/ # Bun + Vite workspace
│ ├─ src/
│ │ ├─ components/ # AppShell, tax layout primitives, shadcn wrappers
│ │ ├─ lib/tax/ # Pure calculators per tax type
│ │ └─ routes/ # File-based TanStack Router pages (one per tax calculator)
│ ├─ public/ # Static assets (favicon, Buku PPh reference PDF)
│ ├─ bun.lock / package.json / tsconfig.json
│ └─ vite.config.ts # Vite + TanStack router plugin + Tailwind setup
└─ ... # Local planning docs (kept outside version control)
ℹ️ Only
README.mdis intended for upstream pushes; other docs stay local for planning/reference.
All app code lives inside open-pajak-v1/. Use Bun (>= 1.1) for dependency management and scripts.
cd open-pajak-v1
bun install
# Local development (Vite dev server on port 3000)
bun dev
# Production bundle + type check
bun run build
# Preview the built assets
bun run servebun test— run the Vitest suite (React Testing Library is available for DOM assertions).bun run lint— TypeScript-aware ESLint (TanStack config) for catching logic mistakes.bun run format— Prettier format check.bun run check— Convenience script (format write + eslint --fix) when sweeping the repo.
Add new tests next to their pages/engines (e.g., src/routes/pph21/pph21.page.test.tsx or src/lib/tax/pph21.test.ts) and focus on edge cases like TER rounding, PTKP thresholds, PKP zero floors, PPN inclusive pricing, etc.
- Model the math first inside
src/lib/tax/<tax>.ts. Keep every helper pure/deterministic and follow the interfaces insrc/lib/tax/types.ts. - Update the UI inside
src/routes/<tax-type>.tsx, using shared primitives such asTaxFormSection,TaxResultTable, andTaxSummaryCard. - Document formulas with
FormulaExplanationCardand source links so users can trace regulations back to Buku PPh / PMK references. - Respect privacy: inputs must remain numeric or enumerated metadata; never prompt for or persist personal identifiers.
- The build is a static bundle; host it on any CDN/static host.
- Static assets live in
open-pajak-v1/public/. Only keep essentials (favicon + PDF reference); unused template files have been removed. - If you need environment toggles, use
import.meta.env, but prefer committed constants whenever possible.
This project is provided as-is for educational and operational use in calculating Indonesian taxes. Consult professional tax advisors before relying on the outputs for filings.
Open Pajak is an open-source project maintained by the community. Shout-out to the folks who have pushed code so far:
- @hamardikan (project owner & maintainer)
- @lynxluna (Didiet Noor)
- @revanp (Revan Pratama)
- @ulilalbabn (Ulil Albab)
- ...and everyone who reports bugs, suggests UX improvements, or contributes new calculators/features.
Want to help? Open an issue or PR in this repository—UI polish, localization tweaks, and regulation updates are always welcome.