UIWiz is the backend service for an AI-powered UI generator. It lets users describe or show UIs (via text or images), and returns production-ready React + Tailwind code generated by Google’s Gemini API. The backend handles authentication, chat sessions, code generation (with streaming and failover), and persistence.
- Authentication: Email/password registration and Google Sign-In via Firebase; issues JWT tokens for API access.
- User profiles: Store per-user Gemini API key (users bring their own) and avatar URL from Google.
- Chat sessions: Create, list, and delete chat sessions; each session has a title (auto-generated from the first prompt), messages, and code versions.
- Code generation: Send a text prompt and optionally an image (base64); receive multi-file React + Vite + Tailwind + TypeScript code. Supports:
- Streaming (SSE) or blocking response
- Iterative refinement (send previous code + new prompt)
- Automatic failover across multiple Gemini models on rate limits (429)
- Persistence: User messages and generated code versions are stored per session in PostgreSQL.
The frontend (not in this repo) talks to this API to power a conversational UI builder: describe or upload a design, get runnable React code, then refine with follow-up prompts.
| Layer | Technology |
|---|---|
| Framework | Django 5.x |
| API | Django REST Framework + Simple JWT |
| Database | PostgreSQL (e.g. Neon, Supabase for free tier) |
| Auth | Firebase Admin (Google ID token verification) + JWT |
| AI | Google Gemini (user-provided API key) |
| Static | WhiteNoise |
| Deployment | Vercel serverless (see DEPLOY_VERCEL.md) |
uiwiz-backend/
├── api/
│ └── wsgi.py # Vercel entry: mounts backend, exposes WSGI app as `app`
├── backend/
│ ├── api/ # Main API app
│ │ ├── models.py # UserProfile, ChatSession, ChatMessage, CodeVersion
│ │ ├── views.py # Auth, sessions, profile, health, code generation
│ │ ├── urls.py # API routes
│ │ ├── serializers.py # DRF serializers
│ │ ├── signals.py # Auto-create UserProfile on User creation
│ │ └── migrations/
│ ├── lumina_backend/ # Django project
│ │ ├── settings.py # Loads config.properties + env overrides
│ │ ├── config_reader.py # config.properties + env (KEY_NAME → KEY_NAME)
│ │ ├── urls.py # Root URLconf (admin, api/, root)
│ │ └── wsgi.py
│ ├── manage.py
│ ├── config.properties # Local config (create from example; not in git)
│ ├── firebase-service-account.json # Firebase creds (local; use env in prod)
│ └── requirements.txt
├── requirements.txt # Mirrored for Vercel install
├── vercel.json # Vercel: install deps, route all to api/wsgi.py
├── DEPLOY_VERCEL.md # Step-by-step Vercel + free DB deployment
└── README.md # This file
Settings are read from backend/config.properties with environment variables overriding (key format: django.secret_key → DJANGO_SECRET_KEY).
Create backend/config.properties (and optionally use a .env for env vars). Example:
# Django
django.secret_key=your-secret-key
django.debug=True
django.allowed_hosts=localhost,127.0.0.1
# Database (PostgreSQL)
db.engine=django.db.backends.postgresql
db.name=uiwiz
db.user=myuser
db.password=example
db.host=localhost
db.port=5432
db.sslmode=prefer
# CORS (frontend origin)
cors.allowed_origins=http://localhost:5173
# Optional: default Gemini (users can still use their own key in profile)
gemini.api_key=
gemini.model=gemini-2.0-flash
# Optional: Firebase (path to service account JSON for Google login)
firebase.service_account_path=firebase-service-account.jsonFor production (e.g. Vercel) you set env vars only (no file); see DEPLOY_VERCEL.md for the full list (DJANGO_SECRET_KEY, DB_*, CORS_ALLOWED_ORIGINS, FIREBASE_SERVICE_ACCOUNT_JSON, etc.).
-
Python: Use a venv and Python 3.10+.
-
Install dependencies (from repo root or
backend/):pip install -r requirements.txt
(Root
requirements.txtis kept in sync for Vercel.) -
PostgreSQL: Create a database and user, then set
db.*inconfig.properties(orDB_*env vars). -
Config: Create
backend/config.propertiesas above. For Google login, placefirebase-service-account.jsoninbackend/and setfirebase.service_account_path(or useFIREBASE_SERVICE_ACCOUNT_JSONwith minified/base64 JSON). -
Migrations:
cd backend python manage.py migrate -
Run server:
python manage.py runserver
- Root:
http://localhost:8000/ - API health:
http://localhost:8000/api/health/
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| GET | / |
No | Root message + health/version info |
| GET | /api/health/ |
No | Health check; gemini_configured when user has API key |
| POST | /api/register/ |
No | Email/password registration |
| POST | /api/login/ |
No | JWT obtain (email/password) |
| POST | /api/google-login/ |
No | Firebase ID token → JWT + user create/update |
| POST | /api/token/refresh/ |
No | Refresh JWT |
| GET/POST/DELETE | /api/profile/ |
JWT | Get/update profile; delete Gemini API key |
| GET/POST | /api/sessions/ |
JWT | List/create chat sessions |
| GET/DELETE | /api/sessions/<id>/ |
JWT | Get/delete a session |
| POST | /api/generate/ |
JWT | Generate code (prompt, optional image, optional previousCode, sessionId; stream or blocking) |
Generate request body (POST /api/generate/)
prompt(required): Text description (and/or refinement instruction).sessionId(required): ID of the chat session (must belong to the user).image(optional): Base64 image (e.g. data URL or raw base64) for “replicate this design”.previousCode(optional): Current code for iterative refinement.stream(optional, defaulttrue): Iftrue, response is SSE withtype: chunkandtype: done(ortype: error).
- Model: Primary model is from config (
gemini.model), with a fallback list inviews.py(e.g.gemini-2.0-flash,gemini-2.0-flash-lite, …) if the primary returns 429/unavailable. - System instruction: Asks Gemini to act as a frontend engineer and output only a JSON object: keys = file paths (e.g.
/App.tsx,/components/Header.tsx), values = file contents. No markdown, no conversational text. Stack: React, Vite, Tailwind, TypeScript, lucide-react, framer-motion, recharts, react-router-dom, etc. - User API key: Each user stores their own Gemini API key in their profile; the backend uses that key for generation. If missing, the API returns a 400 asking the user to add it in settings.
- Vercel: Use the repo root as the project root;
vercel.jsonrunspip install -r requirements.txtand routes all traffic toapi/wsgi.py. No build output directory; the serverless function serves the app. - Database: Use a hosted Postgres (e.g. Neon, Supabase). Run
python manage.py migrateonce against the production DB (seeDEPLOY_VERCEL.md). - Secrets: Set
DJANGO_SECRET_KEY,DB_*,CORS_ALLOWED_ORIGINS, and optionallyFIREBASE_SERVICE_ACCOUNT_JSON(minified or base64) andGEMINI_*in the Vercel project.
Full steps, env var table, and troubleshooting: DEPLOY_VERCEL.md.
- Firebase: Google login uses Firebase Admin to verify the client’s ID token; do not expose the service account JSON. In production, use
FIREBASE_SERVICE_ACCOUNT_JSON(env) only. - Gemini API key: Stored per user in the database; the backend never logs it. Users should use their own key from Google AI Studio.
- CORS: Set
CORS_ALLOWED_ORIGINSto your frontend origin(s) in production; avoid wildcards for authenticated APIs. - DEBUG: Set
DEBUG=Falseand a strongDJANGO_SECRET_KEYin production.
See the repository license file (if present).