Orbital
Personal finance app for iPhone, Android and the web, served by a single API.
- The problem
- Tracking expenses in a spreadsheet does not follow you on your phone. Orbital brings budgeting to iPhone, Android and the web without duplicating business rules: all three talk to the same API.
- What I did
- Personal project: database design, API, cross-platform app and tests.
Technical decisions
- Monorepo with the API contract in shared Zod schemas: if a response shape changes, the app fails to type-check immediately.
- Money is always stored in cents (bigint) and entries as calendar dates, avoiding floating-point and timezone bugs.
- Composite foreign key: the database itself rejects an expense linked to an income category.
- Recurring entries are generated on read, with no cron job, and a unique index prevents duplicates.
82 tests covering pt-BR amount parsing, month and timezone boundaries, and recurrence. In development, invite-only sign-up.
- TypeScript
- Expo
- React Native
- Hono
- Drizzle
- Better Auth
- Zod
- Cloudflare Workers
- PostgreSQL
// Só o TIPO cruza a fronteira: o TypeScript enxerga cada rota e cada resposta,
// mas o Metro não empacota uma linha do servidor dentro do app.
import type { AppType } from '@financas/api'
/* … */
const rpc = hc<AppType>(API_URL, {
/* … */- Line 3Only the API type enters the app. Not a single line of server code ships to iPhone, Android or the web.
- Line 5The client knows every route and response. If the API changes a shape, the app stops compiling right away.

