Overview
Denta Fund is a platform connecting investors with dental clinics raising capital. I took it on as a freelance engagement, owning the frontend from an empty repository through to a working two-sided product.
Stack: Next.js, TypeScript, Zustand, shadcn/ui, Tailwind CSS, Google OAuth.
Two Sides, One Dataset
The core design problem is that a funding round means different things to each party. A clinic owner sees how close am I to my target. An investor sees what am I in, and how is it performing. Same underlying records, two different questions.
That shaped the architecture early: shared data layer, role-specific views on top, and routing that decides which one you get before the page renders.
Auth and Onboarding
Google OAuth as the single sign-in path — no passwords to store, reset, or leak.
The interesting part is what happens after. First login lands a user without a role, so onboarding branches: clinic owner or investor. That choice determines their dashboard, their navigation, and which routes they can reach. Route guards enforce it rather than the UI merely hiding links.
Dashboards
Both roles get a dashboard built on the same primitives — data tables, filters, status indicators, funding progress — configured differently per role.
The constraint I designed against was growth. A dashboard that reads well with five records and falls apart at five hundred isn't finished. Filtering, sorting, and pagination were in from the start, not retrofitted.
Design System from Scratch
No existing components, no established conventions. I built the system on shadcn/ui and Tailwind CSS: design tokens, theming, and a shared component layer above the primitives.
The payoff is compounding. Once the layer existed, new screens became composition — assemble existing pieces — instead of construction. That's what keeps a growing product from drifting into five slightly different button styles.
State
Zustand handles client state: session and role context, UI state, filter and view preferences. Small stores with narrow responsibilities, kept separate from server data so cached remote state and local UI state never blur together.
Status
Pre-launch. Public link to follow.
