A modern Text-to-Image generation web application with multiple AI providers (Gitee AI, HuggingFace Spaces).
- Dark mode Gradio-style UI with frosted glass effects
- Multiple API providers: Gitee AI, HF Z-Image Turbo, HF Qwen Image
- Multiple aspect ratio presets (1:1, 16:9, 9:16, 4:3, 3:4, etc.)
- Adjustable inference steps and dimensions
- 4x image upscaling via RealESRGAN
- Real-time generation progress with timer
- Floating toolbar with blur, info, download, delete actions
- One-click image download (JPG)
- API key persistence in browser (AES-256-GCM encrypted)
- Settings persistence in localStorage (including blur state)
- Responsive design (mobile & desktop)
- Modular component architecture for maintainability
- [Experimental] Flow Mode: Visual canvas for batch image generation with React Flow
- Frontend: React 19, Vite, Tailwind CSS, shadcn/ui, React Flow
- Backend: Hono (TypeScript)
- Deployment: Cloudflare Pages + Functions
- API: Gitee AI (z-image-turbo)
- Architecture: Custom hooks, modular feature components
Flow Mode provides a visual canvas for batch image generation using React Flow.
Access: Click "Flow Mode" in the header or navigate to /flow
Features:
- Visual node-based canvas with drag-and-drop
- Batch generation (1-4 images per prompt)
- Floating input bar for quick prompts
- Session sidebar with history
- Per-image download and blur controls
- Auto-layout using dagre algorithm
Limitations:
⚠️ Session data is stored in memory only - refreshing the browser will lose all generated images- Settings (aspect ratio, resolution) persist in localStorage, but images do not
z-image/
├── apps/
│ ├── web/ # Frontend application
│ │ ├── src/
│ │ │ ├── pages/ # Page components (ImageGenerator, FlowPage)
│ │ │ ├── components/
│ │ │ │ ├── ui/ # shadcn/ui components
│ │ │ │ ├── feature/ # Feature components (Header, PromptCard, etc.)
│ │ │ │ └── flow/ # Flow Mode components (AIResultNode, etc.)
│ │ │ ├── hooks/ # Custom React hooks (useImageGenerator)
│ │ │ └── lib/ # Utilities (crypto, constants, flow-storage)
│ │ ├── functions/api/ # Cloudflare Pages Functions
│ │ └── dist/ # Build output
│ └── api/ # Hono API (shared with functions)
│ └── src/index.ts
├── CLAUDE.md # Project guidance for Claude Code
├── package.json
├── pnpm-workspace.yaml
└── turbo.json
- Node.js 18+
- pnpm 9+
- Gitee AI API Key (Get one here)
- Go to https://github.com/WuMingDao/zenith-image-generator
- Click Fork button in the top right corner
- Clone your forked repository:
git clone https://github.com/YOUR_USERNAME/zenith-image-generator.git
cd zenith-image-generatorpnpm installOption A: Full stack with Cloudflare Pages (Recommended)
cd apps/web
pnpm add wrangler -D
npx wrangler pages dev --port 5173 -- pnpm devOption B: Frontend only (requires separate API)
# Terminal 1: Start API
pnpm dev:api
# Terminal 2: Start Web (update .env first)
# Set VITE_API_URL=http://localhost:8787 in apps/web/.env
pnpm dev:webNavigate to http://localhost:5173
Deploy both frontend and API together with zero configuration.
-
Push your code to GitHub/GitLab
-
Go to Cloudflare Dashboard → Pages → Create a project
-
Connect your Git repository
-
Configure build settings:
Setting Value Root directory apps/webBuild command pnpm buildOutput directory dist -
Click Save and Deploy
-
Your app will be available at
https://your-project.pages.dev
# Install Wrangler globally
npm install -g wrangler
# Login to Cloudflare
wrangler login
# Deploy from apps/web directory
cd apps/web
pnpm build
wrangler pages deploy dist --project-name z-imagecd apps/api
# Update wrangler.toml with your CORS origins
# CORS_ORIGINS = "https://your-app.vercel.app"
wrangler deployNote your Workers URL: https://z-image-api.your-account.workers.dev
-
Go to Vercel Dashboard → New Project
-
Import your Git repository
-
Configure:
Setting Value Root Directory apps/webBuild Command pnpm buildOutput Directory dist -
Add Environment Variable:
Name Value VITE_API_URLhttps://z-image-api.your-account.workers.dev -
Deploy
Same as Option 2 above.
-
Go to Netlify Dashboard → Add new site
-
Import your Git repository
-
Configure:
Setting Value Base directory apps/webBuild command pnpm buildPublish directory apps/web/dist -
Add Environment Variable in Site settings → Environment variables:
Name Value VITE_API_URLhttps://z-image-api.your-account.workers.dev -
Trigger redeploy
Your Gitee AI API key is stored securely in the browser using AES-256-GCM encryption:
- The key is encrypted before being saved to localStorage
- Encryption key is derived using PBKDF2 (100,000 iterations) from browser fingerprint
- Even if localStorage is accessed, the API key cannot be read without the same browser environment
- Changing browsers or clearing browser data will require re-entering the API key
Implementation details (src/lib/crypto.ts):
- Uses Web Crypto API (native browser cryptography)
- AES-256-GCM for authenticated encryption
- Random IV for each encryption operation
- Browser fingerprint includes: User-Agent, language, screen dimensions
Note: While this provides protection against casual access and XSS attacks reading raw values, for maximum security in shared environments, consider:
- Using a private/incognito window
- Clearing browser data after use
- Self-hosting with server-side API key storage
| Variable | Description | Default |
|---|---|---|
VITE_API_URL |
API base URL. Leave empty for Cloudflare Pages deployment | `` |
| Variable | Description | Default |
|---|---|---|
CORS_ORIGINS |
Comma-separated allowed origins | http://localhost:5173,http://localhost:3000 |
Generate an image from text prompt.
Headers:
Content-Type: application/json
X-API-Key: your-gitee-ai-api-key
Request Body:
{
"prompt": "A beautiful sunset over mountains",
"negative_prompt": "low quality, blurry",
"model": "z-image-turbo",
"width": 1024,
"height": 1024,
"num_inference_steps": 9
}Response:
{
"url": "https://...",
"b64_json": "base64-encoded-image-data"
}Parameters:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
prompt |
string | Yes | - | Image description (max 10000 chars) |
negative_prompt |
string | No | "" |
What to avoid in the image |
model |
string | No | z-image-turbo |
Model name |
width |
number | No | 1024 |
Image width (256-2048) |
height |
number | No | 1024 |
Image height (256-2048) |
num_inference_steps |
number | No | 9 |
Generation steps (1-50) |
| Ratio | Dimensions |
|---|---|
| 1:1 | 256×256, 512×512, 1024×1024, 2048×2048 |
| 4:3 | 1152×896, 2048×1536 |
| 3:4 | 768×1024, 1536×2048 |
| 3:2 | 2048×1360 |
| 2:3 | 1360×2048 |
| 16:9 | 1024×576, 2048×1152 |
| 9:16 | 576×1024, 1152×2048 |
- Make sure your browser allows localStorage
- Check if you're in private/incognito mode
- For Cloudflare Pages: Should work automatically
- For separate deployments: Update
CORS_ORIGINSinapps/api/wrangler.toml
- Ensure Node.js 18+ and pnpm 9+ are installed
- Run
pnpm installto update dependencies
MIT