Deploying a Django + React Full-Stack App Without Writing a Dockerfile
Django and React are a classic full-stack combination: Django handles the backend (ORM, authentication, admin, API), and React handles the frontend (interactive UI, state management, client-side routing). Together, they power a huge fraction of the web apps built in 2026. 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 manage the static files (Django's collected static files served by the React dev server in development, but by a CDN or Nginx in production). Deployxa's zero-config polyglot engine eliminates all of that. Here is how to deploy a Django + React full-stack app in minutes 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 Django container runs on its own port (serving the API and admin), the React container runs on its own port (serving the frontend), 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 static file collection manually. The platform handles all of it, just as it does for the FastAPI + Next.js monorepo.
Why Django + React Is a Common AI-Generated Stack
Three reasons explain why AI assistants frequently generate Django + React apps. First, Django is the most popular Python web framework, with a mature ORM, built-in admin, and excellent documentation, which means the LLM's training data is dominated by Django examples. Second, React is the dominant frontend framework, which means the LLM defaults to React for any frontend work. Third, the separation of concerns (Django for backend, React for frontend) is a clean architecture that the LLM can generate reliably, without the complexity of server-side rendering. For vibe coders who want a Python backend (for AI/ML features, data processing, or just because Python is approachable) and a React frontend (for a modern, interactive UI), Django + React is the natural choice.
The trade-off is that Django + React is a polyglot monorepo, which means deploying it requires handling two runtimes. Traditional platforms (Vercel, Netlify) are optimized for single-runtime apps, which means Django + React apps end up split across two platforms (Django on Railway or Render, React on Vercel), which adds operational complexity. Deployxa's polyglot engine handles both in one deployment, which simplifies the workflow.
The Architecture: Two Sibling Containers
Here is how Deployxa deploys a Django + React monorepo.
The Django container
The ingestion service detects Django from your requirements.txt (or pyproject.toml) and manage.py. It configures the build and start commands:
- Build command: pip install -r requirements.txt && python manage.py collectstatic --noinput && python manage.py migrate
- Start command: gunicorn myproject.wsgi:application --bind 0.0.0.0:$PORT --workers 3
- Runtime: Python 3.11 with the necessary system packages (libpq-dev for Postgres, etc.)
The React container
The ingestion service detects React from your frontend/package.json (or client/package.json). It configures the build and start commands:
- Build command: npm install && npm run build
- Start command: npm run preview (for Vite) or npx serve -s dist (for Create React App)
- Runtime: Node 20 with a static file server
The reverse proxy
Traefik v3 routes traffic based on your domain configuration. The frontend is served from yourapp.com, and the API is served from yourapp.com/api (shared origin, no CORS) or api.yourapp.com (separate origin, requires CORS). The shared-origin pattern is recommended, because it eliminates CORS issues. For more on this, see our article on the CORS trap.
Step-by-Step: Deploying a Django + React 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:
my-app/
backend/
requirements.txt
manage.py
myproject/
settings.py
wsgi.py
myapp/
models.py
views.py
urls.py
frontend/
package.json
vite.config.ts
src/
App.tsx
README.mdStep 2: Configure Django for production
In backend/myproject/settings.py, configure the following:
import os
DEBUG = False
ALLOWED_HOSTS = [os.getenv('DJANGO_ALLOWED_HOST', '*')]
CORS_ALLOWED_ORIGINS = [os.getenv('FRONTEND_URL', 'http://localhost:5173')]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.getenv('DB_NAME', 'mydb'),
'USER': os.getenv('DB_USER', 'postgres'),
'PASSWORD': os.getenv('DB_PASSWORD', ''),
'HOST': os.getenv('DB_HOST', 'localhost'),
'PORT': os.getenv('DB_PORT', '5432'),
}
}
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'Step 3: Configure React to call the Django API
In frontend/src/lib/api.ts, configure the API URL:
const API_URL = import.meta.env.VITE_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();
}Step 4: Push to GitHub
git init
git add .
git commit -m "django + react monorepo"
git remote add origin https://github.com/yourname/my-app.git
git push -u origin mainStep 5: 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.
Step 6: Configure environment variables
For the backend service, add: DATABASE_URL, DJANGO_SECRET_KEY, FRONTEND_URL (pointing at the frontend's Deployxa URL). For the frontend service, add: VITE_API_URL (pointing at the backend's Deployxa URL). The pre-flight scanner will warn you about any that are clearly required but missing.
Step 7: 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.
Step 8: Add a custom domain
Add a custom domain for the frontend service. SSL is provisioned automatically. The backend service gets a subdomain, and the frontend's VITE_API_URL should point at it.
Step 9: 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.
Common Pitfalls and Troubleshooting
The first pitfall is static file serving. Django's collectstatic command collects static files into STATIC_ROOT, but in production, these files need to be served by a web server (Nginx, WhiteNoise, or a CDN). The fix is to use WhiteNoise, which integrates with Django to serve static files efficiently from the application server. Add whitenoise.middleware.WhiteNoiseMiddleware to your MIDDLEWARE setting, and configure STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'. The second pitfall is database migration timing. Migrations should run before the traffic swap, not after. The fix is to include python manage.py migrate in the build command (as shown above) or to run it as a pre-deployment step via the CLI. The third pitfall is CORS configuration. If you use separate origins for the frontend and backend, you need to configure CORS on the Django backend. The fix is to use django-cors-headers and set CORS_ALLOWED_ORIGINS to the frontend's URL. The fourth pitfall is environment variable propagation. The frontend's VITE_API_URL is a build-time variable (inlined at build time), so changing it requires a rebuild. The fix is to set the variable in the Deployxa dashboard before triggering the build. The fifth pitfall is Gunicorn worker count. The default Gunicorn worker count (1) is too low for production. The fix is to set --workers 3 (or more, depending on your container's CPU) in the start command.
When to Choose Django + React vs Other Stacks
The choice of stack depends on your app's requirements. Choose Django + React if you need a Python backend (for AI/ML features, data processing, or because your team knows Python) and a modern React frontend. Choose FastAPI + Next.js if you need async Python (for WebSockets, streaming, or high-concurrency APIs) and server-side rendering. Choose Next.js alone (with API routes) if your app is simple enough to fit in a single runtime. Choose Laravel + Octane if you prefer PHP. Deployxa's polyglot engine handles all of these stacks equally, so the choice depends on your team's expertise and your app's requirements, not on deployment constraints. For more on hardware sizing, see our article on SPA vs SSR hardware sizing.
Advanced Django + React Patterns
Beyond the basics, Django + React apps benefit from several advanced patterns. The first is Django REST Framework (DRF) for the API. DRF provides serializers, viewsets, and routers that make it easy to build a REST API. The fix is to install DRF (pip install djangorestframework), define serializers for your models, and use viewsets to handle CRUD operations. The second is JWT authentication. For SPA frontends, JWT (JSON Web Tokens) is the standard authentication mechanism. The fix is to use djangorestframework-simplejwt to issue JWTs, and to configure your React app to send the JWT in the Authorization header. The third is WebSocket support. Django's Channels library adds WebSocket support, which is useful for realtime features (e.g., chat, notifications). The fix is to install Channels (pip install channels), configure a Redis backend for channel layers, and define WebSocket consumers. The fourth is static file optimization. Django's collectstatic command collects static files, but in production, you should serve them via a CDN for better performance. The fix is to use django-storages with an S3-compatible backend (e.g., Cloudflare R2) to serve static files from a CDN. The fifth is database connection pooling. Django's default database configuration opens a new connection per request, which is inefficient. The fix is to use django-db-connection-pool or to configure PgBouncer as a connection pooler. For more on Django deployment, see our articles on the FastAPI + Next.js monorepo and database connection pooling.
Conclusion: Polyglot Without the Pain
The Django + React monorepo is a classic full-stack combination, 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 static file management. Stop fighting your deployment platform and start shipping.
Ready to deploy your Django + React app? 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 polyglot deployment, see our articles on the FastAPI + Next.js monorepo and the CORS trap. Learn about deploying Go Fiber APIs and running BullMQ background workers in our companion articles. Explore our free developer tools to speed up your workflow.