A web app and CLI for generating images with Cloudflare Workers AI and Google Gemini. Built with FastAPI, hand-rolled pastel design system, and deployable to Railway in one click.
| Studio | Gallery |
|---|---|
![]() |
![]() |
| Dashboard | Public share |
|---|---|
![]() |
![]() |
| Sign in | Create account |
|---|---|
![]() |
![]() |
- Studio UI with model selection, prompt history, image preview, and one-click download
- 13 models: 11 Cloudflare (6 free, 5 paid) + 2 Gemini (admin-only)
- Compare mode — race the same prompt across 2–3 models side by side
- Gallery with favorites, tags, filters, and lightbox modal
- Shareable public links for individual images
- Usage dashboard with per-day and per-model breakdowns
- Pastel agency design — Fraunces display + Plus Jakarta Sans body, soft cream/coral/lavender palette, Art the woodpecker mascot
- CLI scripts for one-off generation (Cloudflare and Gemini)
- Cloudinary-backed image storage (CDN-hosted, persistent across deploys)
- Self-service password reset via email reset links
- User authentication (bcrypt-hashed passwords, signed session cookies)
- Admin roles (Gemini-restricted, rate-limit exempt)
- CSRF protection on all mutations
- Rate limiting (5 generations / 5 minutes / user)
- Security headers (CSP, HSTS, X-Frame-Options, etc.)
- One-click Railway deployment
git clone https://github.com/nodelabstudio/gemini-n-cloudflare-imagegen-ai.git
cd gemini-n-cloudflare-imagegen-ai
pip install -r requirements.txtCreate a .env file in the project root:
# Cloudflare (free)
CF_ACCOUNT_ID=your-account-id
CF_API_TOKEN=your-api-token
# Gemini (optional)
GEMINI_API_KEY=your-gemini-key
# Cloudinary (image storage)
CLOUDINARY_CLOUD_NAME=your-cloud-name
CLOUDINARY_API_KEY=your-api-key
CLOUDINARY_API_SECRET=your-api-secretRun the web UI:
uvicorn app:app --reloadOpen http://localhost:8000 in your browser.
-
Push this repo to GitHub
-
Go to railway.com and create a new project from your repo
-
Click + New > Database > PostgreSQL to add a database
-
Railway auto-injects
DATABASE_URLinto your app -
Add your environment variables in the Railway dashboard under Variables:
CF_ACCOUNT_ID,CF_API_TOKEN(Cloudflare)GEMINI_API_KEY(Google, optional)SESSION_SECRET(generate withpython3 -c "import secrets; print(secrets.token_hex(32))")SMTP_HOST,SMTP_PORT,SMTP_USER,SMTP_PASS,FROM_EMAIL(for password reset emails — see below)CLOUDINARY_CLOUD_NAME,CLOUDINARY_API_KEY,CLOUDINARY_API_SECRET(image storage — see cloudinary.com)
-
Important: Link the Postgres service to your web service so
DATABASE_URLis auto-injected (or add it manually). Without this, the app falls back to SQLite which is wiped on every deploy. -
Railway auto-detects the
Procfileand deploys
Password reset emails are sent via SMTP. We use Resend (free tier: 100 emails/day).
- Sign up at resend.com and verify your sending domain
- Add these variables in Railway:
SMTP_HOST=smtp.resend.comSMTP_PORT=587SMTP_USER=resendSMTP_PASS=re_your_api_keyFROM_EMAIL=noreply@yourdomain.com
Without SMTP configured, the app still works — reset links are logged to the server console instead of emailed.
The database table is created automatically on first startup. Locally it uses SQLite (images.db) so you don't need PostgreSQL for development.
| Key | Model | Tier |
|---|---|---|
flux-schnell |
FLUX.1 Schnell (default) | Free |
sdxl |
Stable Diffusion XL | Free |
dreamshaper |
DreamShaper 8 LCM | Free |
sd-lightning |
SDXL Lightning | Free |
sd-img2img |
SD v1.5 Img2Img | Free |
sd-inpaint |
SD v1.5 Inpainting | Free |
flux-2-dev |
FLUX.2 Dev (best quality) | Paid |
flux-2-klein-4b |
FLUX.2 Klein 4B | Paid |
flux-2-klein-9b |
FLUX.2 Klein 9B | Paid |
phoenix |
Leonardo Phoenix | Paid |
lucid |
Leonardo Lucid Origin | Paid |
| Key | Model |
|---|---|
gemini-2.5-flash |
Gemini 2.5 Flash |
gemini-3.1-flash |
Gemini 3.1 Flash (Preview) |
You can also generate images from the command line:
# Cloudflare
python3 cloudflare_image_gen.py "A lighthouse at sunset, digital art"
python3 cloudflare_image_gen.py --model=dreamshaper "your prompt"
python3 cloudflare_image_gen.py --models
# Gemini
python3 gemini_image_gen.py "your prompt"
python3 gemini_image_gen.py --diagnose- Sign up at dash.cloudflare.com (no credit card)
- Copy your Account ID from the dashboard sidebar
- Create an API token at dash.cloudflare.com/profile/api-tokens using the "Workers AI" template
- Get an API key at aistudio.google.com/apikey
- For image generation, you may need to link a billing account (no minimum spend)
The UI is a hand-rolled pastel agency aesthetic — no UI kit, no component library beyond Tailwind utilities.
- Type: Fraunces (variable serif, with
opszandSOFTaxes) for display + Plus Jakarta Sans for body - Palette: cream surfaces, coral primary, lavender accents, soft mint and peach for state colors. Tokens live in
static/css/app.cssas CSS variables - Mascot: Art the woodpecker, generated via Gemini 3.1 Flash. Five poses (
art-{wave,paint,peek,sleep,logo}.pnginstatic/img/). Regenerate them withpython scripts/gen_mascots.py - Components: prefixed
cf-*to avoid Tailwind clashes —cf-btn,cf-card,cf-input,cf-mascot-frame,cf-tile,cf-stat, etc. - Screenshots:
python scripts/take_screenshots.py(requirespip install playwright && playwright install chromium) writes todocs/screenshots/
- Authentication: Username/password with bcrypt-hashed passwords stored in PostgreSQL
- Password Reset: Self-service forgot password via email (SMTP through Resend)
- Sessions: Signed cookies (7-day expiry, SameSite=Lax, Secure flag in production)
- CSRF: Token-based protection on all POST/DELETE endpoints
- Rate Limiting: 5 image generations per 5 minutes per user (slowapi/limits)
- Headers: CSP, X-Frame-Options DENY, X-Content-Type-Options, HSTS (in production), Referrer-Policy, Permissions-Policy
- Add a custom domain to your Railway app (Settings > Networking > Custom Domain)
- In Cloudflare DNS, add a CNAME record pointing to your Railway domain
- Enable the orange cloud (Proxy) for DDoS protection, WAF, and SSL termination
- Under Security > WAF, enable managed rulesets for additional protection
- Backend: FastAPI + Uvicorn
- Frontend: Tailwind CSS (CDN) + custom
app.cssdesign system - Type: Fraunces (display) + Plus Jakarta Sans (body), via Google Fonts
- Auth: passlib + bcrypt, Starlette sessions
- Email: Resend (SMTP)
- Database: PostgreSQL (Railway) / SQLite (local dev)
- Image Storage: Cloudinary (CDN)
- Providers: Cloudflare Workers AI, Google Gemini
- Deployment: Railway






