# 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.