Skip to content

Tech Stack & Why

Every choice below was made for a specific reason tied to what this product actually needs — a POS handling real money on a laptop behind a counter and, increasingly, on a phone.

Backend

TechRoleWhy it was chosen
GoAPI serverFast to run, cheap to deploy, and its static typing catches whole classes of bugs (a mis-typed money field, a nil pointer on a transaction) before they ever reach a till. Simple concurrency model handles concurrent checkouts without extra machinery.
MySQLDatabase of recordBattle-tested relational storage for data with real referential structure — transactions belong to wallets, budgets belong to expenses, variants belong to products.
gorilla/muxHTTP routingA minimal, unopinionated router — Clean Architecture (below) does the structural work, so the routing layer stays thin.

Frontend — shared

TechRoleWhy it was chosen
TypeScriptLanguageEnd-to-end type safety from the OpenAPI-generated client through business logic to the rendered screen.
TamaguiCross-platform UI kitLets one component tree render as real DOM on web and real native views on iOS/Android, with shared styling and theming — the mechanism behind Cross-Platform.
TanStack QueryServer-state / cachingHandles request de-duplication, caching, and revalidation for API calls made from the shared libs/ui layer, on both platforms.
ts-patternExhaustive pattern matchingEvery screen's state is a discriminated union (loading / loaded / error / …); ts-pattern's .exhaustive() makes the compiler refuse to build if a new state is ever left unhandled.
ZodRuntime validationValidates form input and, via generated schemas, API responses — a second line of defense alongside TypeScript's compile-time checks.
React Hook FormFormsEvery create/update screen (products, expenses, budgets, …) is a form; this keeps them fast and free of unnecessary re-renders.

Frontend — platform-specific

TechRoleWhy it was chosen
Next.jsWeb app frameworkServer-side rendering for the web app's auth checks and initial page data — a POS screen shouldn't flash "loading" before showing a cashier their queue.
React NativeMobile runtimeThe same component and business-logic layer, compiled to genuinely native iOS/Android apps rather than a wrapped webview.
SolitoNavigation glueLets the same screens resolve /transactions/:id-style links on both Next.js routing and React Navigation, keeping URL structure consistent across platforms.

API contract

TechRoleWhy it was chosen
OpenAPIAPI specificationlibs/api-contract/src/api.yaml is the one place the shape of every endpoint is defined.
KubbCodegenGenerates a typed TypeScript client, Zod schemas, and TanStack Query hooks straight from the OpenAPI spec for libs/ui to consume — no hand-written fetch calls to drift out of sync with the backend.

Workspace & delivery

TechRoleWhy it was chosen
NxMonorepo toolingOne repository for API, web, mobile, and shared libraries, with dependency-aware builds/tests and consistent tooling across all of them.
Jest + React Testing LibraryFrontend unit & integration testsSee Testing Strategy.
Go's built-in testing packageBackend unit & integration testsSame.
PlaywrightEnd-to-end testsSame.
GitHub Actions + GitHub PagesThis documentation siteThe same pipeline pattern (build → deploy) the product itself could use for CI/CD.

Explore the source

Built with VitePress. Content lives in docs-site/ — see the README for how to run it locally.