All articles

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

Nathan & Robert

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:

  1. The Next.js frontend development server

  2. The FastAPI backend with auto-reloading

  3. A local Postgres database for development

  4. 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:

  1. Catch errors early: TypeScript will alert you immediately if you try to access a property that doesn't exist or has changed

  2. Autocompletion: Your IDE can provide intelligent suggestions based on the actual API structure

  3. Refactoring confidence: When you rename fields in the backend, TypeScript will identify all the places in the frontend that need updates

  4. 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:

  1. An isolated frontend deployment

  2. A dedicated backend instance

  3. An isolated database with the correct schema and test data

  4. 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!


More articles

Get in touch

Make smarter decisions with actionable insights from your data. We combine analytics, visualisations, and advanced AI models to surface what matters most.

Contact us

We believe in making a difference through innovation. Utilizing data and AI, we align your strategy and operations with cutting-edge technology, propelling your business to scale and succeed.

Wolk Tech B.V. & Wolk Work B.V.
Schaverijstraat 11
3534 AS, Utrecht
The Netherlands

Keep in touch!

Subscribe to our newsletter, de Wolkskrant, to get the latest tools, trends and tips from the industry.