Rapid Development with Next.js + FastAPI + Vercel + Neon Postgres



In the ever-evolving landscape of modern web development, the tools and workflows we choose can dramatically impact both developer productivity and project outcomes. At Wolk, we've curated a powerful stack that combines Next.js, FastAPI, Vercel, and Neon Postgres to create a smooth developer experience while delivering high-performance applications.
This article shares our journey to building our workflow and explains how you can implement a similar approach.
Introduction
Developer experience (DX) has emerged as a crucial factor in the success of software teams. Just as user experience determines how people interact with our products, developer experience shapes how efficiently teams can build, test, and deploy those products. A streamlined DX means faster iterations, fewer errors, more innovation, and ultimately, better software.
Our stack combines four powerful technologies:
Next.js: A React framework with built-in optimizations and a great developer experience.
FastAPI: A modern, high-performance Python web framework built for API development with automatic documentation.
Vercel: A deployment platform for fullstack frameworks that offers seamless preview deployments. Incidentally also the company behind Next.js
Neon Postgres: A serverless Postgres service with unique branching capabilities that enable isolated database environments for every feature branch.
This article is aimed at full-stack development teams, DevOps engineers, and technical leaders looking to improve their development workflows, particularly those working with JavaScript/TypeScript frontends and Python backends.
Local Development Environment
The foundation of a great developer experience is a smooth local development environment that minimizes friction between writing code and seeing it in action.
Setting Up the Stack
Our repository structure separates frontend and backend in a monorepo code while maintaining their relationship:
/
├── app/ # Next.js application
├── api/ # Vercel entrypoint for the backend
├── backend/ # FastAPI application
├── docker-compose.yml # Local development orchestration
├── .env # Environment configuration
├── requirements.txt # Python dependencies
└── package.json # Project dependencies and scripts
For local development, we use Docker Compose to orchestrate all necessary services. Our docker-compose.yml
file sets up:
The Next.js frontend development server
The FastAPI backend with auto-reloading
A local Postgres database for development
Supporting services like email testing tools
Here's a simplified version of our Docker Compose configuration:
version: "3"
services:
frontend:
build:
context: .
dockerfile: Dockerfile.dev
volumes:
- ./:/app
- /app/node_modules
ports:
- "3000:3000"
environment:
- NODE_ENV=development
command: npm run dev
backend:
build:
context: ./backend
dockerfile: Dockerfile
volumes:
- ./backend:/app
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://postgres:postgres@db:5432/app
command: uvicorn app.main:app --reload --host 0.0.0.0
db:
image: postgres:14
ports:
- "5432:5432"
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=app
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
Environment management is handled through a combination of .env
files and Docker Compose environment variables. For team members, getting started is as simple as:
# Clone the repository
git clone <https://github.com/our-org/our-project.git>
# Start the development environment
docker compose up
Once the environment is set up, the day-to-day development flow becomes remarkably efficient. The entire loop from database model change to frontend rendering can be completed in minutes, with each step providing immediate feedback through hot reloading.
Stack quirks
Vercel is a great platform for developing web applications but it is mainly focused on Next.js and other Javascript frameworks. Running Python on Vercel is supported but it does come with some quirks.
Vercel deploys a serverless function for every file it finds in the /api
folder. So if we would put our whole Python backend application in there we would create numerous functions as this backend consists of many files. Also the routing of API calls is by default done based on file naming, common Typescript frameworks but less used in Python web apps. To fix this problem, we build the backend application in a separate folder and add an entrypoint for Vercel to build a function from:
#/api/main.py
import sys
sys.path.append("./backend")
from app.main import app # type: ignore
app
When this is done the only thing left to do is add some configuration so that all routes starting with /api
are passed to the backend entrypoint so that FastAPI can handle the routing to the correct function itself. This can by defining a rewrite innext.config.ts
:
const nextConfig: NextConfig = {
rewrites: async () => {
return [
{
source: "/api/:path*",
destination: "/api/main.py",
},
]
},
}
Type Safety Across the Stack
One of the most significant productivity enhancements in this stack is the end-to-end type safety between frontend and backend.
FastAPI uses Python type hints and Pydantic models to validate data. We leverage these types to automatically generate TypeScript interfaces for our frontend, creating a single source of truth for data structures.
Our approach utilizes the OpenAPI schema that FastAPI generates automatically. We utilize OpenAPI Typescript to automatically generate Typescript types from the backend's OpenAPI schema. This gives us TypeScript interfaces that exactly match our API endpoints and data models.
This approach helps us:
Catch errors early: TypeScript will alert you immediately if you try to access a property that doesn't exist or has changed
Autocompletion: Your IDE can provide intelligent suggestions based on the actual API structure
Refactoring confidence: When you rename fields in the backend, TypeScript will identify all the places in the frontend that need updates
Documentation: The types serve as living documentation of your API interface.
This type-safety across the stack significantly reduces context switching cost when moving between frontend and backend code, allowing developers to work more confidently across the full stack.
Full-Stack Preview Environments with Vercel and Neon
Our personal favourite part of this workflow is the isolated preview environments enabled by Vercel and Neon.
Traditional development workflows often struggle with environment isolation. While features are developed in separate branches, testing often happens in shared environments, leading to:
Conflicts between features being tested simultaneously
Difficulty reproducing specific states for bug testing
Uncertainty about how changes will behave in production
Lengthy feedback cycles for stakeholders
Many teams solve this partially with frontend preview deployments, but often the backend and database remain shared resources. This creates an incomplete picture of how changes will actually behave in production.
The ideal solution needs to provide:
An isolated frontend deployment
A dedicated backend instance
An isolated database with the correct schema and test data
Automatic setup and teardown of all resources
Enter Vercel and Neon
Our solution combines Vercel's preview deployments with Neon's unique database branching capabilities:
Vercel automatically creates a deployment for every pull request, with its own URL
Neon Postgres allows us to create a complete database branch from our main database, with its own isolated state
When a developer opens a pull request, they get a complete, isolated environment with its own database. This environment is a perfect replica of production, but with only their changes applied.
This approach significantly accelerates the feedback loop, allowing stakeholders to review actual working features rather than mockups or descriptions!
Conclusion
The combination of Next.js, FastAPI, Vercel, and Neon Postgres has transformed our development workflow. Our team now enjoys:
A consistent, easy-to-use local development environment
End-to-end type safety between frontend and backend
Isolated preview environments for every pull request
Faster feedback cycles for both developers and stakeholders
Higher confidence in the changes being deployed
This stack has directly contributed to faster feature delivery, fewer production bugs, and a more enjoyable development experience.
If you're building with a JavaScript/TypeScript frontend and a Python backend, we highly recommend exploring this combination of technologies. The productivity benefits are substantial, and the enhanced collaboration between frontend and backend teams is invaluable.
Have you implemented a similar workflow? We'd love to hear about your experiences!