A production-ready text-to-image generation application built with FastAPI (backend) and Next.js 14+ (frontend). The backend uses the Tongyi-MAI/Z-Image-Turbo model for high-performance image generation.
- Backend: FastAPI running on GPU machine with model loaded once at startup
- Frontend: Next.js 14+ with App Router, TypeScript, Tailwind CSS, and shadcn/ui
- Model: Tongyi-MAI/Z-Image-Turbo (bfloat16, CUDA)
- Connection: Reverse SSH tunnel from GPU machine to public server (frontend)
Note: The backend and frontend run on different machines. Use reverse SSH tunneling to connect them. See REVERSE_SSH_SETUP.md for detailed setup instructions.
- ✅ Single model load at startup (reused for all requests)
- ✅ Concurrent request limiting (max 2 simultaneous generations)
- ✅ CUDA cache clearing after each generation
- ✅ Health check endpoint
- ✅ CORS support
- ✅ Optional image saving to disk
- ✅ Production-ready with Gunicorn + Uvicorn
- ✅ Beautiful, modern UI with dark/light mode
- ✅ Large prompt textarea with character counter
- ✅ Collapsible negative prompt section
- ✅ Resolution presets (1024×1024, 768×1152, 1152×768, etc.)
- ✅ Custom width/height inputs
- ✅ Seed input with random seed generator
- ✅ Steps slider (6-12, default 9)
- ✅ Real-time image display from base64
- ✅ Gallery of last 12 generated images
- ✅ Copy prompt/seed, download image buttons
- ✅ Toast notifications
- ✅ Fully mobile-responsive
- ✅ API health monitoring
- Python 3.11+
- CUDA-capable GPU with sufficient VRAM (recommended: 24GB+)
- NVIDIA drivers and CUDA toolkit
- PyTorch with CUDA support
- Node.js 18+ and npm
-
Navigate to backend directory:
cd backend -
Create virtual environment (recommended):
python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate
-
Install dependencies:
pip install -r requirements.txt
-
Run the server:
# Development python main.py # Or with uvicorn directly uvicorn main:app --host 0.0.0.0 --port 8000 # Production (with Gunicorn) gunicorn main:app -w 1 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000 --timeout 300
The backend will be available at http://localhost:8000
Important: The backend is wrapped as a pure API - the model loading happens in main.py via the lifespan context manager, not in run.py. The run.py file is just a server runner.
Since the backend runs on a GPU machine (possibly behind a firewall) and the frontend runs on a public server, you need to set up a reverse SSH tunnel.
Quick Setup:
-
On GPU machine (backend):
cd backend # Edit setup_reverse_ssh.sh with your public server details chmod +x setup_reverse_ssh.sh ./setup_reverse_ssh.sh
-
On public server (frontend):
# Verify tunnel is working curl http://localhost:8000/health
See REVERSE_SSH_SETUP.md for complete instructions.
-
Navigate to frontend directory:
cd frontend -
Install dependencies:
npm install
-
Create
.env.localfile:cp .env.example .env.local
-
Update
.env.localwith your backend URL:# If using reverse SSH tunnel (frontend on same server as tunnel endpoint): NEXT_PUBLIC_API_URL=http://localhost:8000 # Or if using a public domain with Nginx reverse proxy: # NEXT_PUBLIC_API_URL=http://api.yourdomain.com
-
Run development server:
npm run dev
The frontend will be available at http://localhost:3000
-
Build and run with docker-compose:
docker-compose up -d
Or build manually:
cd backend docker build -t text2image-backend . docker run --gpus all -p 8000:8000 text2image-backend
Note: Docker deployment requires NVIDIA Container Toolkit for GPU access.
The frontend can be deployed to:
- Vercel (recommended for Next.js)
- Netlify
- Any static hosting service
- Push your code to GitHub
- Import project in Vercel
- Set environment variable:
NEXT_PUBLIC_API_URL=https://your-backend-url.com - Deploy
-
Build the project:
cd frontend npm run build -
Deploy the
.nextfolder or connect to Git repository -
Set environment variable:
NEXT_PUBLIC_API_URL=https://your-backend-url.com
Root endpoint with API information.
Health check endpoint. Returns:
{
"status": "healthy",
"model_loaded": true,
"cuda_available": true,
"cuda_device": "NVIDIA GeForce RTX 4090"
}Generate an image from a text prompt.
Request Body:
{
"prompt": "A beautiful landscape with mountains",
"negative_prompt": "blurry, low quality",
"height": 1024,
"width": 1024,
"seed": -1,
"num_inference_steps": 9,
"guidance_scale": 0.0
}Response:
{
"image_base64": "data:image/png;base64,...",
"seed": 12345,
"generation_time_ms": 842,
"width": 1024,
"height": 1024,
"image_id": "uuid-here"
}Create a .env file in the backend directory:
SAVE_IMAGES=false
# Set to true to save generated images to disk
# CORS Origins (comma-separated)
# CORS_ORIGINS=http://localhost:3000,https://yourdomain.comCreate a .env.local file in the frontend directory:
NEXT_PUBLIC_API_URL=http://localhost:8000-
SSH into your GPU server
-
Clone the repository
-
Set up Python environment and install dependencies
-
Run with Gunicorn:
gunicorn main:app -w 1 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000 --timeout 300
-
Use a process manager (recommended):
- systemd (Linux)
- PM2 (Node.js process manager)
- Supervisor
Create /etc/systemd/system/text2image.service:
[Unit]
Description=Text-to-Image API
After=network.target
[Service]
Type=simple
User=your-user
WorkingDirectory=/path/to/Text2Image/backend
Environment="PATH=/path/to/venv/bin"
ExecStart=/path/to/venv/bin/gunicorn main:app -w 1 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000 --timeout 300
Restart=always
[Install]
WantedBy=multi-user.targetEnable and start:
sudo systemctl enable text2image
sudo systemctl start text2imageExample nginx configuration for backend:
server {
listen 80;
server_name api.yourdomain.com;
location / {
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_read_timeout 300s;
proxy_connect_timeout 300s;
}
}- Model is loaded once at startup (shared across requests)
- Concurrent generations limited to 2 (prevents OOM)
- CUDA cache cleared after each generation
- Uses
torch.inference_mode()andtorch.no_grad()for efficiency
Uncomment in backend/main.py:
# pipe.transformer.compile() # Faster after first run
# pipe.enable_model_cpu_offload() # For <24GB VRAMCUDA out of memory:
- Reduce
MAX_CONCURRENT_GENERATIONSinmain.py - Enable CPU offloading:
pipe.enable_model_cpu_offload() - Reduce image resolution
Model loading fails:
- Check CUDA availability:
python -c "import torch; print(torch.cuda.is_available())" - Verify GPU drivers are installed
- Check available VRAM
API connection errors:
- Verify
NEXT_PUBLIC_API_URLis correct - Check CORS settings on backend
- Ensure backend is running and accessible
Build errors:
- Clear
.nextfolder:rm -rf .next - Reinstall dependencies:
rm -rf node_modules && npm install
This project is provided as-is for educational and development purposes.
- Model: Tongyi-MAI/Z-Image-Turbo
- Built with FastAPI and Next.js