Skip to content

Datodia/ai-toolkit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mini AI Toolkit

Real-time AI image and text generation with async job processing, live status updates via SSE, and a full generation history. One command to run everything.

See claude-session.md for a full summary of the Claude Code session used to build this project.

How to start project

Run from the project root:

cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env
docker compose up --build -d

Screenshots

Main view — prompt form, active jobs, gallery Main view

Image lightbox — expanded job detail with metadata Image lightbox

Advanced parameters — width, height, seed, model selector Advanced parameters


Architecture

Browser
  │
  ├─ POST /api/jobs ──────────────────────────────────────────────────────┐
  │    Returns 202 in ~50ms. Job created as PENDING. Never blocks.        │
  │                                                                        │
  ├─ GET /api/jobs/:id/stream (SSE) ◄─────── DB poll every 1s ◄──────────┤
  │    Browser opens EventSource immediately after job creation.           │
  │    Auto-reconnects up to 3× on disconnect.                            │
  │                                                                        │
  └─ GET /api/jobs (poll every 5s) ◄── fallback for gallery/history       │
                                                                           │
Backend (Express)                                                          │
  ├─ Routes → validate (Zod) → Prisma → PostgreSQL                        │
  └─ BullMQ Queue ◄──────────────────────────────────────────────────────┘
       │
       ▼
  Worker (concurrency: 3)
  ├─ PENDING → GENERATING → calls Pollinations.ai (180s timeout)
  ├─ On success → COMPLETED, stores resultUrl / resultText
  └─ On failure → FAILED, stores errorMessage (BullMQ retries 2×)

State Machine

PENDING ──► GENERATING ──► COMPLETED
   │              │
   ▼              ▼
CANCELLED       FAILED ──► (retry) ──► PENDING

Key Design Decisions

Decision Rationale
202 Accepted on job creation API never blocks on AI generation. Client gets job ID immediately and subscribes to SSE stream for updates.
BullMQ + Redis Production-grade async queue. Survives restarts, supports priority, cancel, retry, and concurrency control.
SSE over WebSocket One-directional status push is all that's needed. SSE is simpler — native EventSource, no handshake, auto-reconnect built in.
Pollinations.ai Free, no auth, supports both image (Flux models) and text generation.
DB polling for SSE (1s) Simple, reliable. The improvement path is Redis pub/sub when scale demands it.
Prisma + PostgreSQL Type-safe ORM, strong schema, good for filtered pagination queries.
shadcn/ui + Tailwind Accessible, composable, no runtime CSS-in-JS overhead. Dark mode works out of the box.
Zod on both sides Same validation shapes on client and server. 400 errors include field-level messages.

Tech Stack

Layer Technology Version
Frontend Next.js + React 16 / 19
Styling Tailwind CSS v4 + shadcn/ui 4
Forms React Hook Form + Zod 7 / 4
Backend Express + TypeScript 4.21 / 5
Queue BullMQ 5
Cache / Queue store Redis 7
ORM Prisma 5
Database PostgreSQL 16
AI provider Pollinations.ai
Container Docker + Docker Compose

Features

Mandatory

  • Prompt submission UI with generation type selector (Image / Text)
  • Async job processing — API returns in <100ms, never blocks
  • Job state machine: PENDING → GENERATING → COMPLETED / FAILED
  • Real-time status updates via Server-Sent Events (SSE)
  • Gallery with completed images (click to open lightbox)
  • Full generation history with search and filter by status / type
  • Error handling: input validation, timeouts, graceful failure display

Bonus

  • Multiple generation types — Image (Flux models) and Text
  • Prompt enhancement — optional AI rewrite via Pollinations text API before generation
  • Real-time SSE — auto-reconnects up to 3× on disconnect
  • Cancel jobs — cancel any PENDING or GENERATING job
  • Retry jobs — retry any FAILED or CANCELLED job (preserves original enhance flag)
  • Priority queue — Low / Normal / High priority mapping to BullMQ numeric priority
  • User-defined parameters — width, height, seed, model (6 Flux variants + Turbo)
  • Docker Composedocker compose up --build starts everything
  • Paginated history — filterable table view with 20-per-page pagination
  • Stats bar — live count of total / done / active / failed jobs
  • Duration tracking — time from creation to completion shown per job

API Reference

Method Path Description
POST /api/jobs Submit job (returns 202 immediately)
GET /api/jobs List jobs — ?status=&type=&page=&limit=
GET /api/jobs/:id Get single job
GET /api/jobs/:id/stream SSE stream — pushes updates until terminal state
DELETE /api/jobs/:id Cancel PENDING or GENERATING job
POST /api/jobs/:id/retry Retry FAILED or CANCELLED job

POST /api/jobs

{
  "prompt": "A cyberpunk city at night, neon reflections on wet pavement",
  "type": "IMAGE",
  "enhance": true,
  "priority": 5,
  "parameters": {
    "width": 1024,
    "height": 1024,
    "seed": 42,
    "model": "flux-realism"
  }
}

Response 202:

{
  "id": "cm...",
  "status": "PENDING",
  "prompt": "...",
  "createdAt": "..."
}

Manual Setup

Prerequisites: Node 20+, PostgreSQL, Redis

# Backend
cd backend
cp .env.example .env        # edit DATABASE_URL and REDIS_URL if needed
npm install
npx prisma migrate deploy
npm run dev

# Frontend (separate terminal)
cd frontend
echo "NEXT_PUBLIC_API_URL=http://localhost:4000" > .env.local
npm install
npm run dev

Project Structure

ai-toolkit/
├── backend/
│   ├── prisma/
│   │   └── schema.prisma        # DB schema + indexes
│   └── src/
│       ├── index.ts             # Express app + worker bootstrap
│       ├── db/prisma.ts         # Prisma singleton
│       ├── middleware/validate.ts # Zod request validation middleware
│       ├── validation/
│       │   └── createJobSchema.ts # Zod schema for POST /api/jobs
│       ├── queue/
│       │   ├── queue.ts         # BullMQ queue + Redis connection
│       │   └── worker.ts        # Job processor + graceful shutdown
│       ├── routes/jobs.ts       # All /api/jobs endpoints
│       ├── services/
│       │   ├── ai.ts            # Pollinations.ai image + text generation
│       │   └── enhancer.ts      # Prompt enhancement via text API
│       └── types/index.ts
├── frontend/
│   ├── app/
│   │   ├── page.tsx             # Main page: form + gallery
│   │   └── layout.tsx
│   ├── components/
│   │   ├── PromptForm.tsx       # Submission form with advanced params
│   │   ├── Gallery.tsx          # Job card grid
│   │   ├── JobCard.tsx          # Individual card + lightbox + SSE
│   │   ├── StatusBadge.tsx      # Status indicator with animation
│   │   └── StatsBar.tsx         # Header counts
│   ├── hooks/
│   │   ├── useJobs.ts           # Poll all jobs with interval
│   │   └── useJobStream.ts      # SSE stream for single job
│   ├── lib/api.ts               # API client
│   └── types/index.ts           # type aliases (no interfaces)
└── docker-compose.yml           # postgres + redis + backend + frontend

AI Integration

Uses Pollinations.ai — free, no API key required.

  • Image: https://image.pollinations.ai/prompt/{prompt}?width=&height=&seed=&model=
    • Models: flux (default), flux-realism, flux-cablyai, flux-anime, flux-3d, turbo
    • Timeout: 180s
  • Text: https://text.pollinations.ai/{prompt}
    • Timeout: 180s
  • Prompt enhancement: sends a rewrite instruction to the text API before generation

Images are hosted by Pollinations.ai — the URL returned is stable as long as the same seed/params are used.


What I'd Improve With More Time

  1. Redis pub/sub for SSE — replace 1s DB polling with event-driven pub/sub. Worker publishes on status change, SSE handler subscribes. Eliminates N×polling at scale.

  2. Proper database migrations — replace prisma db push with versioned migration files (prisma migrate). Safe for production schema evolution.

  3. Image storage — download generated images to S3/R2 instead of relying on Pollinations.ai URL stability. Enables thumbnails, CDN delivery.

  4. Authentication — user accounts with per-user job isolation, API keys, and rate limits per identity.

  5. Rate limiting — per-IP rate limiting on job submission (e.g., express-rate-limit).

  6. Bull Board — mount the BullMQ dashboard for queue observability (job counts, failed jobs, retry from UI).

  7. Structured logging — replace console.* with Winston or Pino for JSON-structured logs with correlation IDs.

  8. WebSocket — upgrade from SSE to WS to push queue position and estimated wait time to all clients simultaneously.

  9. Image variations — generate N variants from one prompt in parallel, return best or let user pick.

  10. Test coverage — unit tests for worker logic, integration tests for API routes against a real test DB.

About

Real-time AI image and text generation with async job processing, live status updates via SSE, and a full generation history. One command to run everything.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages