KM
← Back to Blog
Academia logo

From Idea to Production: How I Chose My Tech Stack (and What I’d Change Next)

A practical breakdown of the decisions behind Academia’s multi-tenant Next.js + NestJS stack, the tradeoffs I made to ship, and the improvements I’d prioritize next.

Apr 24, 2026• By Kubsamel Kamu• ~8 min read
The question that shaped the stack
Do I want the “perfect” stack on paper, or a stack that helps me ship a reliable product under real constraints?
Academia is a workflow-heavy, role-based platform — dashboards and clear state matter. (Click to zoom)

What I optimized for

Academia is an academic project workflow platform: from onboarding and group formation to milestones, evaluation readiness, and final defense. That domain pushes you toward tenant isolation, RBAC, and predictable UI patterns.

  • Multi-tenant by default: institutions must be isolated (data + access).
  • Role-based experiences: student/advisor/coordinator dashboards and navigation.
  • Fast UI delivery: consistent tables, forms, and state handling.
  • Clean API boundary: versioning + predictable auth.
  • Reliability: background jobs shouldn’t block requests.

Frontend stack

Why Next.js (App Router)
Great fit for products that mix marketing pages and authenticated dashboards, and where route/layout structure maps cleanly to role-based sections.
UI: Tailwind + shadcn/ui
Tailwind keeps the system consistent; shadcn/ui avoids rebuilding primitives for every dashboard pattern.
State: TanStack Query + Zustand
Query handles server-state (cache, retries, invalidation). Zustand handles small client state without turning into a dumping ground.
Networking: Axios + interceptors
Central place to attach auth tokens and ensure tenant context flows consistently.

Multi-tenancy

One of the most important decisions in Academia is how tenant context is derived: from the request host/domain. The client includes a tenant-aware header (for example X-Tenant-Domain) so the backend can enforce isolation.

Why derive tenant from the host?
  • Tenant selection becomes implicit — fewer UI/UX chances to pick the wrong tenant.
  • Requests carry tenant context consistently, which makes server-side enforcement easier.
  • Scaling to new institutions becomes mostly configuration + onboarding, not code branching.

Backend stack

NestJS for modular features
Academia isn’t a single-controller API — modules keep boundaries clear as features grow.
PostgreSQL + Prisma
Relational modeling fits institutions/users/projects/milestones/evaluations naturally, and Prisma keeps types aligned with schema changes.
Auth: JWT + RBAC
UI hiding isn’t security. RBAC enforced at the API boundary keeps the system honest.
Async work: Redis + Bull
Queues keep heavy work off the request path and enable dedicated workers when needed.
Real-time: Socket.IO
For notifications, messaging, and live status updates without over-engineering.

The tradeoffs I made to ship

Strictness vs delivery speed
Shipping quickly sometimes means tolerating temporary framework/tooling noise — but it should stay temporary, not become the default.
Two repos (frontend + backend)
Cleaner boundaries and scalability, but more coordination and setup.
Queue complexity
Redis/Bull adds operational overhead, but pays back quickly once workloads grow.

What I’d change next

1) Make type safety non-negotiable
Remove “ignore build/type errors” workarounds and add CI gates that fail on TypeScript errors.
2) Observability from day one
Structured logging (request IDs + tenant IDs), metrics for queue latency/failures, and clear error reporting for API clients.
3) Stronger API contracts
Generate typed API clients from OpenAPI/Swagger and standardize error shapes across endpoints.
4) Multi-tenancy hardening
Enforce tenant scoping consistently in queries and guards/interceptors.
5) Testing balance
More unit tests around permissions/tenant boundaries, plus a few high-value end-to-end tests for key workflows.

Closing thoughts

The best stack is the one that supports the actual product constraints. For Academia, multi-tenancy, RBAC, and workflow-heavy dashboards made Next.js + NestJS + Postgres + Prisma + Redis a practical combination.