Deploying a FastAPI + Next.js Monorepo in 30 Seconds Without Writing a Single Dockerfile | Deployxa

FastAPI backends and Next.js frontends are the most common AI-generated polyglot stack. Here is how to deploy both from one monorepo without writing a Dockerfile.

← Back to Dispatch Articles
Engineering Log

Deploying a FastAPI + Next.js Monorepo in 30 Seconds Without Writing a Single Dockerfile

FastAPI backends and Next.js frontends are the most common AI-generated polyglot stack. Here is how to deploy both from one monorepo without writing a Dockerfile.

Deploying a FastAPI + Next.js Monorepo in 30 Seconds

The most common AI-generated full-stack stack in 2026 is FastAPI on the backend and Next.js on the frontend. Cursor, Claude Code, and Lovable all default to this combination when you ask for a "full-stack app with a Python backend and a React frontend." It is a great choice: FastAPI is fast, typed, and async; Next.js is the dominant React framework with SSR, API routes, and server components. But deploying both together has traditionally been painful, because they are different runtimes (Python and Node) that need different containers, different build commands, and different port bindings. The standard solution is to write two Dockerfiles, configure a reverse proxy, and pray. Deployxa's zero-config polyglot engine eliminates all of that. Here is how to deploy a FastAPI + Next.js monorepo in 30 seconds without writing a single Dockerfile.

The direct answer is that Deployxa auto-detects both frameworks from your repository structure, generates the correct internal build configuration for each, and deploys them as sibling containers with isolated networking. The FastAPI container runs on its own port, the Next.js container runs on its own port, and Deployxa's Traefik v3 reverse proxy routes traffic between them based on your domain configuration. You do not write a Dockerfile, you do not configure a reverse proxy, and you do not manage port bindings. The platform handles all of it.

Why Polyglot Monorepos Are Hard on Traditional Platforms

Traditional deployment platforms are optimized for single-runtime apps. Vercel is built for Node.js (specifically Next.js). Railway and Render support multiple runtimes, but you typically deploy each service as a separate app, which means separate build configurations, separate environment variables, and separate domains. AWS and GCP support anything, but they require you to write Terraform, configure VPCs, and manage IAM policies. None of these platforms are designed for the case where you have a single Git repository with both a Python backend and a Node frontend, and you want to deploy both with one push.

The result is that polyglot monorepos are a tax on AI-generated apps. The LLM generates a clean repository with backend/ (FastAPI) and frontend/ (Next.js) directories, and you spend hours figuring out how to deploy both. The standard approaches are: deploy them as separate apps on Railway or Render (which means two build configurations and two domains), or write a Docker Compose file and deploy to a VPS (which means learning Docker Compose, configuring Nginx, and managing SSL yourself). Neither is great for vibe coders who just want their app on the internet.

A second reason polyglot monorepos are hard: build-time coupling. In a monorepo, a push to either backend/ or frontend/ triggers a rebuild of both on most CI systems, because the CI does not know which service changed. Deployxa's polyglot engine uses path-based build triggers: a push that only touches frontend/ only rebuilds the frontend, and a push that only touches backend/ only rebuilds the backend. This cuts build time in half for the common case of single-service changes.

How Deployxa's Zero-Config Polyglot Engine Works

Deployxa's ingestion service inspects your repository structure and identifies the frameworks present. For a FastAPI + Next.js monorepo, it typically sees:

  • backend/requirements.txt or backend/pyproject.toml (Python)
  • backend/main.py or backend/app/main.py (FastAPI entry point)
  • frontend/package.json (Node.js)
  • frontend/next.config.js (Next.js)

From this, it identifies two services: a FastAPI backend and a Next.js frontend. It generates the correct internal build configuration for each: for FastAPI, it installs Python 3.11+, pip installs the requirements, and starts the app with uvicorn main:app --host 0.0.0.0 --port $PORT. For Next.js, it installs Node 20+, runs npm install and npm run build, and starts with npm start. Each service runs in its own container with isolated networking, and Traefik v3 routes traffic between them.

The key insight is that the polyglot monorepo is the normal case for AI-generated apps, not the exception. The LLM generates a Python backend because Python is the dominant language for AI/ML features, and it generates a Next.js frontend because Next.js is the dominant React framework. A platform that requires you to split these into separate apps is fighting the grain of how AI-assisted development works. Deployxa embraces the polyglot monorepo as a first-class deployment target.

How the Two Services Communicate

Each service gets its own Deployxa subdomain by default: my-app-backend.deployxa.app and my-app-frontend.deployxa.app. The frontend can call the backend via this URL, or via a custom domain you configure (e.g., api.myapp.com). The Traefik v3 reverse proxy handles TLS termination, routing, and load balancing for both services.

The services can also communicate via an internal network if you prefer lower latency and no public ingress for the backend. The internal network is configured via the Deployxa dashboard under Networking > Internal Routes. When enabled, the frontend reaches the backend at http://my-app-backend:8000 (an internal DNS name), which is faster and does not consume public bandwidth.

The communication pattern matters for security. If the backend exposes admin endpoints that should not be public, the internal network is the right choice. If the backend is purely an API for the frontend, public ingress is fine. Deployxa supports both, and you can mix: public ingress for /api/* and internal-only for /admin/*.

Step-by-Step: Deploying a FastAPI + Next.js Monorepo

Here is the exact workflow for a typical Cursor-generated monorepo.

Step 1: Structure your repository

Your repository should have a clear separation between backend and frontend. A typical structure looks like:

my-app/
  backend/
    requirements.txt
    main.py
    app/
      routers/
      models/
      schemas/
    ...
  frontend/
    package.json
    next.config.js
    src/
      app/
      components/
      lib/
    ...
  README.md

The LLM usually generates this structure automatically. If it does not, you can restructure manually before pushing.

Step 2: Push to GitHub

git init
git add .
git commit -m "fastapi + next.js monorepo"
git remote add origin https://github.com/yourname/my-app.git
git push -u origin main

Step 3: Connect to Deployxa

In the Deployxa dashboard, click New App, and select your repository. Deployxa's ingestion service detects both frameworks and creates two services: my-app-backend and my-app-frontend. You will see log lines like:

[ingest] Detected Python project at backend/
[ingest] Framework: fastapi
[ingest] Runtime: python 3.11
[ingest] Start command: uvicorn main:app --host 0.0.0.0 --port $PORT
[ingest] Detected Node.js project at frontend/
[ingest] Framework: nextjs
[ingest] Runtime: node 20.x
[ingest] Build command: npm run build
[ingest] Start command: npm start
[ingest] Created 2 services: my-app-backend, my-app-frontend
[ingest] Path-based build triggers enabled

Step 4: Configure environment variables

Add environment variables for both services. The backend typically needs DATABASE_URL, SECRET_KEY, and any API keys. The frontend typically needs NEXT_PUBLIC_API_URL pointing at the backend's Deployxa URL (e.g., https://my-app-backend.deployxa.app).

Step 5: Deploy

Click Deploy. Both services build in parallel, and each is live within 60 to 90 seconds. The AutoRepairService stands by to patch any missing dependencies (Python packages or npm packages). The localhost rewriter handles any hardcoded URLs in the frontend. The build resilience injector bypasses ESLint and TypeScript strictness in the Next.js build.

Step 6: Add a custom domain

In the Deployxa dashboard, add a custom domain for the frontend service (e.g., myapp.com). SSL is provisioned automatically. The backend service gets a subdomain (e.g., api.myapp.com or my-app-backend.deployxa.app), and the frontend's NEXT_PUBLIC_API_URL should point at it.

Step 7: Verify with deployxa doctor

Run deployxa doctor for each service to verify health. The 14-point readiness engine checks SSL, DNS, environment variables, health endpoints, and container status for both services.

deployxa doctor --app my-app-frontend
deployxa doctor --app my-app-backend

Common Pitfalls

Four pitfalls appear in polyglot monorepo deployments. First, CORS. The frontend's browser requests to the backend's URL are cross-origin, so the backend must send CORS headers. FastAPI's CORSMiddleware handles this, but the LLM often forgets to configure it for the production origin. Add the frontend's Deployxa URL to the CORS origins list. Second, environment variable leakage. The frontend's NEXT_PUBLIC_API_URL is exposed to the browser, so it must not contain secrets. If your backend URL includes credentials (it should not), use a separate non-public variable. Third, build context pollution. If your frontend/ directory accidentally contains a requirements.txt (e.g., from a stray file), the ingestion service may get confused. Keep backend and frontend directories clean and unambiguous. Fourth, port binding conflicts. Both services default to specific ports (FastAPI on 8000, Next.js on 3000), but Deployxa assigns each container its own port via the PORT env var. If your code hardcodes the port, it will not pick up the assigned port. Use os.environ.get("PORT", 8000) in FastAPI and let Next.js read PORT automatically.

Troubleshooting: Common Monorepo Deployment Errors

Below are common errors and their interpretations.

Error: [ingest] Could not identify framework in backend/

The ingestion service found a requirements.txt but could not identify the framework (FastAPI, Flask, Django). Ensure fastapi is in requirements.txt and main.py has app = FastAPI().

Error: [ingest] Multiple Node.js projects detected

The ingestion service found multiple package.json files (e.g., in frontend/ and a nested frontend/admin/). Move the nested project or add a .deployxaignore to exclude it.

Error: CORS policy blocked the request

The browser blocked a cross-origin request from the frontend to the backend. Add the frontend's URL to the backend's CORS origins:

# backend/main.py
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://my-app-frontend.deployxa.app", "https://myapp.com"],
    allow_methods=["*"],
    allow_headers=["*"],
)
Error: Cannot find module 'next' in frontend

The package.json in frontend/ does not list next as a dependency. The AutoRepairService will install it, but if it fails, add it manually: npm install next react react-dom.

Handling the API URL Connection

The trickiest part of a polyglot monorepo is connecting the frontend to the backend. Locally, you might run the FastAPI server on localhost:8000 and the Next.js dev server on localhost:3000, with the frontend fetching from http://localhost:8000/api/.... In production, both URLs change, and the frontend needs to know the backend's production URL.

The clean solution is to use an environment variable (NEXT_PUBLIC_API_URL) in the frontend, and set it to the backend's Deployxa URL in the Deployxa dashboard. The localhost rewriter handles the common case where the LLM hardcoded localhost:8000 in the frontend's fetch calls, but for new code, you should use the environment variable explicitly.

// frontend/src/lib/api.ts
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000';
export async function fetchAPI(path: string) {
  const res = await fetch(`${API_URL}${path}`);
  if (!res.ok) throw new Error(`API error: ${res.status}`);
  return res.json();
}

Server-Side vs Client-Side Fetches

A subtlety: Next.js server components and server actions can call the backend via the internal network (no CORS, lower latency), while client components must call via the public URL (subject to CORS). The pattern is to use a different env var for server-side calls:

// frontend/src/lib/api-server.ts
const API_URL = process.env.API_URL_INTERNAL || process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8000';
// Use this in server components and server actions

Set API_URL_INTERNAL to http://my-app-backend:8000 in the Deployxa dashboard. This avoids CORS for server-side calls and reduces latency by using the internal network.

When to Use a Polyglot Monorepo vs a Single Runtime

The FastAPI + Next.js stack is great for apps that need AI/ML features (which Python handles well) alongside a polished React frontend (which Next.js handles well). Examples include: AI-powered SaaS apps with a Python backend running LLM calls, data science dashboards with a Python backend running Pandas/NumPy, and real-time apps with a Python backend running async WebSockets.

For simpler apps (a CRUD app with no AI features, a marketing site with a contact form), a single-runtime stack (Next.js with API routes, or FastAPI with Jinja templates) is simpler and sufficient. The polyglot monorepo is worth the complexity when you genuinely need both runtimes, not as a default.

Pricing Reality: The Cost of Two Services

A polyglot monorepo deploys as two services, which has cost implications. On Deployxa's free tier (3 apps, 512MB RAM each), a monorepo consumes 2 of the 3 app slots. On the paid tier ($9/month for 15 apps), a monorepo consumes 2 of the 15 slots. The cost per slot is $0.60/month, so a polyglot monorepo costs $1.20/month on the paid tier.

| Setup | Apps used | Monthly cost on Deployxa Paid |

|---|---|---|

| 1 Next.js app | 1 | $0.60 (pro-rated from $9/mo for 15 apps) |

| 1 FastAPI + Next.js monorepo | 2 | $1.20 |

| 5 monorepos (10 services total) | 10 | $6.00 |

| 7 monorepos + 1 standalone (15 services) | 15 | $9.00 (max) |

Compare this to Railway, where each service is a separate app at $5/month minimum: a FastAPI + Next.js monorepo costs $10/month, and 5 monorepos cost $50/month. Deployxa's flat pricing is significantly cheaper for polyglot monorepos.

When a Polyglot Monorepo Is Not the Right Choice

A polyglot monorepo is not the right choice when: you do not need both runtimes (use a single-runtime stack instead), your team is small and lacks Python expertise (use Next.js API routes with TypeScript end-to-end), your backend is purely a CRUD API with no AI/ML features (use a Node.js backend like Hono or Express), or your frontend is a static site with no server-side rendering (use Vite with a static host like Cloudflare Pages). The polyglot monorepo adds complexity (two build pipelines, two env var sets, CORS, internal networking), and that complexity is justified only when you genuinely need both runtimes.

Conclusion: Polyglot Without the Pain

The FastAPI + Next.js monorepo is the most common AI-generated full-stack stack, and it should be as easy to deploy as a single-runtime app. Deployxa's zero-config polyglot engine makes it so: push the repository, and the platform handles the rest, with no Dockerfiles, no reverse proxy configuration, and no port binding. Stop fighting your deployment platform and start shipping.

Ready to deploy your polyglot monorepo? Drag your project to Deployxa Drop for an instant live preview, or install the CLI with npm i -g @deployxa/cli and deploy from your terminal. For more on AI-generated deployment patterns, see our free developer tools and read about the five common AI coding mistakes.

Ready to deploy with Deployxa?

Deploy your apps globally with automatic SSL and AI diagnostics.

Start Free Now