DB-Viz
2026live

DB-Viz

A full-stack database visualisation platform — migrated from NestJS to Next.js App Router

View Live
Next.js 14TypeScriptTailwind CSS v4better-authPrismaVercel
01

Overview

DB-Viz is a full-stack database visualisation and management platform. It allows teams to connect to databases, explore schemas, run queries, and visualise data relationships in real time. The platform was originally built on NestJS for the backend and a separate React frontend. We migrated the entire system to a unified Next.js 14 App Router architecture — server components handling data access, client components owning interactivity, and a single deployment surface on Vercel.

02

The Inspiration

DB-Viz started as a NestJS + separate frontend project — a clean separation of concerns that made sense at the time. But as the product grew, the overhead of maintaining two runtimes, two deployment pipelines, and two auth surfaces became friction that slowed everything down. The migration to Next.js App Router was a deliberate architectural decision to consolidate without losing capability.

03

Tech Stack

Next.js 14 (App Router)

Replacing NestJS + CRA with a unified Next.js app eliminated the separate API server entirely. React Server Components handle database queries and session validation at the edge — no client round-trips for initial data.

TypeScript (strict mode)

Migrating between architectures exposed a lot of implicit type assumptions in the original NestJS codebase. Strict TypeScript forced us to make every contract explicit — particularly around session types, API response shapes, and database query results.

better-auth

Replaced a custom NestJS JWT guard + Passport.js setup with better-auth. Type-safe session handling with cookie-based auth, far less boilerplate, and it works seamlessly in both Server Components and API Route Handlers.

Prisma + PostgreSQL

Carried over from the NestJS layer. Prisma's type-safe query builder was one of the few things that migrated with zero friction — the schema stayed the same, only the import paths changed.

Tailwind CSS v4

Moved from Tailwind v3 utility classes to v4's CSS custom property system. This let us build a proper design token layer — consistent spacing, colour, and typography scales — without fighting the framework or writing custom CSS overrides.

Vercel

Went from two separate deployment pipelines (NestJS on Railway, frontend on Vercel) to a single Vercel project. Preview deployments per branch made testing the migration safe — we could validate the new architecture without touching production.

04

Challenges & Solutions

The Problem

NestJS used class-based controllers and dependency injection — patterns that have no direct equivalent in Next.js Route Handlers. Naively porting them produced bloated route files with no separation of concern.

The Solution

Extracted all business logic into plain TypeScript service modules — no decorators, no DI container. Route Handlers became thin orchestrators. The result was actually cleaner than the original NestJS services because we removed the framework ceremony and kept only the logic.

The Problem

Authentication was deeply coupled to NestJS Guards and Passport strategies. Session validation was happening in middleware that had no equivalent in the Next.js request lifecycle.

The Solution

Rebuilt auth from scratch using better-auth with a cookie-based session model. Wrote a lightweight session utility that works in Server Components, Route Handlers, and middleware — giving us the same protection surface as the old Guard system but with a fraction of the code.

The Problem

After login, navigation to the dashboard kept redirecting back to the login page — even though the session cookie was being set correctly and getSession was returning the authenticated user.

The Solution

The root cause was a race condition between useSession hydrating on the client and the AuthProvider's useEffect firing with a stale null session. Fixed by removing the manual window.location redirect after login and letting the session state drive navigation — the redirect only fires once useSession reflects the authenticated state.

The Problem

The production cookie (visio.session_token) was visible in DevTools but not being forwarded to Next.js middleware on Vercel, causing every authenticated route to redirect to login.

The Solution

Traced the issue to better-auth's cookie prefix behaviour on HTTPS — Vercel's edge was receiving the cookie but middleware was checking the wrong name. Added fallback cookie name checks in middleware and verified the BETTER_AUTH_URL environment variable matched the exact production domain without a trailing slash.

The Problem

Tailwind CSS v4 caused a PostCSS parse error that crashed the build — a JSX component had been accidentally pasted into globals.css during a chaotic refactor session.

The Solution

Removed the embedded JSX, consolidated the shiki code-block CSS variables into a single :root block (removing the conflicting .dark overrides), and locked the dark mode colour scheme to oklch values that render consistently across both light and dark mode without the old navy-blue flash.

05

What I Learned

  • 01

    NestJS and Next.js solve different problems — NestJS gives you structure for complex backend domains, Next.js gives you colocation and deployment simplicity. The migration was worth it because our backend wasn't complex enough to justify a separate runtime.

  • 02

    React Server Components aren't just a performance feature — they change the security model. Database queries and session checks that previously needed an API hop now happen server-side with zero client exposure.

  • 03

    better-auth's cookie-based session is significantly easier to reason about than JWT + refresh token flows in a Next.js context, especially once you understand that the session cookie must match the exact domain in BETTER_AUTH_URL.

  • 04

    Race conditions in auth flows are almost always caused by trying to navigate before client-side session state has hydrated. The fix is always the same: let state drive navigation, never drive navigation manually after an async call.

  • 05

    CSS custom properties as a design token system scale better than utility class proliferation for design-heavy sites — especially with Tailwind v4's native CSS variable support.

  • 06

    When debugging cookie issues on Vercel, the first thing to check is whether the cookie name being set matches the cookie name being read in middleware — framework-level prefixing behaviour on HTTPS is the most common culprit.