For a long time, my personal accounting system was a small automation stack: a Telegram bot wizard collected transaction details, wrote rows into Google Sheets, and custom spreadsheet charts handled the statistics.
It was a good setup because Telegram made capture fast and Sheets made analysis flexible. But every improvement also meant keeping bot prompts, spreadsheet columns, formulas, and charts aligned.
I built xpenser to keep the useful parts of that workflow while moving the repetitive structure into a small web app: transactions, vendors, nested categories, currencies, dashboard periods, reports, Telegram workflows, and email summaries.
The project also became a reference app for the stack behind it. The same schema-first TypeScript contracts drive validation, OpenAPI output, typed clients, React forms, auth-aware endpoints, telemetry, Telegram integration, and MCP access.
This post walks through what shipped, what I deliberately did not build yet, and why chat/agent-friendly finance data needs careful permission wording.






