PS

Tech Stack

What I reach for, and why

A list of technologies says very little. What matters is why each one was chosen over the alternative, and what it cost.

Mobile client

FlutterCross-platform app framework
One codebase carrying two genuinely different products — the diner app and the owner app — behind a routing gate. The alternative was two native codebases for a team of one.
ProviderState management
Enough structure to keep state out of widgets without the ceremony of a heavier solution. For an app this size, more machinery would cost more than it returns.

API

NestJSBackend framework
Its module and provider system is why DealPlate's twenty-plus domains stayed navigable. Guards and parameter decorators let the auth boundary be declared rather than repeated.
TypeScriptLanguage
End to end — API, admin console and this site. With Prisma's generated types it means a schema change surfaces as a compile error rather than a runtime surprise.
class-validatorRequest validation
Applied as a global pipe with whitelist and transform, so unknown properties are stripped and params are typed before any handler runs.

Data

PostgreSQLPrimary database
Relational because the domain is relational — users, restaurants, promotions and coupons are nothing but relationships. Indexes on lat/long, zip and city make proximity a database concern.
PrismaORM and migrations
The migration workflow is the real value. Ten incremental migrations tell the story of how the product changed; a rewritten schema tells you nothing.

Identity

Firebase AuthFederated identity
Email/password and Google sign-in without owning credential storage. One identity across the mobile app and the admin console.
JWT + PassportSelf-issued tokens
The other approach, used in i-Bank — full control over token contents and lifetime, at the cost of owning the security surface yourself.

Web

Next.js (App Router)Web framework
Server Components keep content on the server and JavaScript off the client. Route groups let the admin console share a layout without sharing an auth posture.
Tailwind CSSStyling
Design tokens as CSS variables, consumed as utilities — which is what makes a single theme switch flip the whole site coherently.
shadcn/uiComponent primitives
Components copied into the repo rather than installed as a dependency. Accessible defaults that stay editable instead of fighting a library's opinions.
MotionAnimation
Scroll and transition animation that respects prefers-reduced-motion. Motion should confirm a change, not announce itself.

AI

ClaudeStructured extraction
Reads a photographed restaurant flyer into typed promotion fields against a fixed JSON schema. Constrained output, not free generation — and it fails closed when unconfigured.
Groq / WhisperSpeech to text
Called directly from the device on the user's own key, so audio never passes through infrastructure of mine.