Back to Blog
Engineering

Building a Modern Documentation Platform with Next.js and Neon Postgres

Learn how we built Venture Creative Media using Next.js 15, React 19, Neon Postgres, and Better Auth.

Sarah Chen
Sarah ChenSenior Full-Stack Engineer at Venture Creative Media
8 min read
Building a Modern Documentation Platform with Next.js and Neon Postgres

# Introduction

When we set out to build Venture Creative Media we needed a stack that delivered real-time responsiveness without sacrificing developer velocity. After plenty of prototypes we committed to Next.js 15, React 19, Neon Postgres, Kysely, and Better Auth. The combination gave us a streaming-first UI, serverless Postgres with branching, and a unified auth workflow for the web, dashboard, and Chrome extension.

## The Technology Stack

### Next.js 15 with the App Router

Next.js is still the backbone of the UI:

- **Server Components by default** mean we ship far less JavaScript to the browser. - **Layouts and route groups** help us share navigation and metadata effortlessly. - **Edge-friendly streaming** keeps the marketing site fast globally. - **Deep TypeScript support** keeps the whole team confident.

When we need interactivity we explicitly mark a component as client-side, but the majority of UI renders on the server.

### Neon Postgres + Kysely

Neon powers the database layer. Branchable Postgres, generous free-tier storage, and connection pooling are perfect for Vercel’s serverless model. We couple Neon with Kysely so SQL lives in TypeScript:

- **Branch previews** spin up isolated Postgres branches per pull request. - **Autoscaling compute** lets us pause staging environments when they’re idle. - **LISTEN/NOTIFY triggers** drive our real-time idea voting. - **Kysely-generated types** keep API routes and UI code in sync with the schema.

Better Auth sits on top, issuing both httpOnly cookies (for marketing & dashboard) and bearer tokens (for the Chrome extension) off the same session source.

## Design Philosophy

Our interface borrows its black-and-white minimalism from Night.co:

- **Pure OKLCH black and white** for consistent contrast. - **Generous typography** courtesy of Geist Sans and variable font weights. - **Purposeful motion** powered by Framer Motion. - **WCAG AAA contrast** baked into every component.

## Performance Optimizations

### 1. Image Optimization

We rely on `next/image` with tuneable quality and priority flags so critical assets show up instantly.

### 2. Code Splitting

Dynamic imports keep heavier components on the shelf until they are needed.

### 3. Database Query Optimisation

Kysely lets us fetch exactly the columns required for each page:

```typescript const ideas = await db .selectFrom('ideas') .select(['id', 'title', 'bucket', 'capturedAt']) .where('votesComplete', '=', true) .orderBy('capturedAt', 'desc') .limit(12) .execute() ```

## Challenges and Solutions

### Challenge 1: Server vs Client Components

We default everything to the server. Components only move client-side if they need browser APIs or local state.

### Challenge 2: Real-time Updates

Neon triggers emit events that our API fans out through Server-Sent Events. This gives the Chrome extension instant updates without maintaining WebSocket infrastructure.

### Challenge 3: Type Safety

We generate TypeScript types straight from SQL migrations so queries, API handlers, and UI components stay in lockstep.

## Results

- **Page load time**: consistently under 1.5 seconds (95th percentile). - **Lighthouse score**: 98+ across every marketing page. - **Bundle size**: 60% smaller compared to our initial prototype. - **Developer productivity**: 2× faster shipping thanks to typed queries and branched databases.

Venture Creative Media