AI-powered image and video generation platform with real-time progress, social features, and a built-in creator economy.
Pixel Studio is a full-stack web app where users generate images across many state-of-the-art models (OpenAI gpt-image-1, Stable Diffusion 3.5, Flux Pro / Dev / Schnell, Ideogram, FAL, Black Forest, Together, Replicate) and produce short videos via Runway, Luma, and Stability. It ships with collections, a following feed, comments and likes, achievements, a prompt marketplace, creator tipping, print-on-demand, an admin console, and a Tailwind-based design system with a persisted light/dark theme.
Built on Remix + Vite + React 18 + TypeScript, backed by PostgreSQL + Prisma, with Upstash QStash powering the async generation queue and WebSockets streaming live progress to the client.
A tour of the redesigned UI (PR #150, June 2026). All captures come from the live app β see pr-screenshots/ for the full historical set.
| Landing | Explore |
|---|---|
| Create β Image | Create β Video |
|---|---|
| Following Feed | Profile |
|---|---|
| What's New | Admin Overview |
|---|---|
- πΌοΈ Images across 8 providers β OpenAI (
gpt-image-1withdall-e-3fallback), Stable Diffusion 3.5 (Large / Turbo / Medium), Stable Image Core & Ultra, Flux Pro 1.1 / Dev / Schnell, Ideogram, FAL, Black Forest, Replicate, Together - π¬ Video generation β Runway ML, Luma AI, Stability AI, with automatic thumbnail extraction
- π Multi-model comparison β run one prompt across multiple models and compare the results side-by-side
- π± Image remixing β fork any image, track lineage through
Image.parentId - β‘ Async pipeline β Upstash QStash queues jobs, workers process them, WebSockets stream live progress to the UI
- ποΈ Collections β public, private, and premium (paid) collections of images
- π₯ Following feed β see new work from creators you follow
- π¬ Comments, likes, replies β full nested-comment system on images and videos
- π Achievements & login streaks β gamified engagement
- π Prompt marketplace β sell and review high-quality prompts with built-in payouts
- π° Tipping β send credits directly to other creators
- π¨οΈ Print on demand β order physical prints of generated images
- π³ Stripe-powered credits with full ledger (
CreditTransaction) - π Analytics dashboards for users and admins, plus per-prompt performance and "style fingerprint" analysis
- π‘οΈ Admin console β users, credits, models, external services, tokens, deletion audit logs, engagement, blog management
- π Blog / tutorials with SEO metadata
- π Light & dark themes persisted on the
Userrecord - π± Mobile-first redesign β sidebar collapses into a bottom nav + slide-up sheet on small screens
| Layer | Technology |
|---|---|
| Framework | Remix 2.16 + React 18 + TypeScript 5 + Vite 5 |
| Styling | TailwindCSS 3, custom design tokens (app/globals.css), Radix UI primitives, shadcn/ui, Lucide icons |
| Database | PostgreSQL + Prisma ORM 5 (43 models) |
| Auth | Remix Auth + Google OAuth; Supabase v2 auth migration in progress |
| State | Zustand (client) + React Context (generation progress) |
| Queue | Upstash QStash (default) β Apache Kafka pipeline available but on hold |
| Cache | Upstash Redis |
| Storage | AWS S3 |
| Real-time | Native WebSocket server |
| AI (Images) | OpenAI, Hugging Face, FAL, Ideogram, Replicate, Together, Black Forest Labs, Stability |
| AI (Video) | Runway ML, Luma AI, Stability AI |
| Payments | Stripe |
| Logging | Winston + OpenTelemetry (OTLP HTTP) |
| Monitoring | Sentry, Vercel Analytics, PostHog |
| Testing | Vitest 4, Playwright |
| Tooling | Husky + lint-staged, ESLint (Airbnb-ish), Prettier |
| Deploy | Vercel (primary), Express production server (server.js) |
- Node.js β₯ 20
- PostgreSQL (local or hosted β Supabase, Neon, RDS, etc.)
- Upstash account for Redis + QStash
- API keys for at least one image provider (OpenAI is enough to get started)
Kafka and Docker are not required in the default configuration. QStash handles async generation out of the box.
git clone https://github.com/kevinreber/pixel-studio.git
cd pixel-studio
npm installcp env.example .env
# Edit .env β see "Environment Variables" belowAt minimum, fill in DATABASE_URL, SESSION_SECRET, GOOGLE_CLIENT_ID/SECRET, OPENAI_API_KEY, UPSTASH_REDIS_REST_*, QSTASH_*, and the AWS S3 keys.
npx prisma generate
npx prisma db pushnpm run devThe app boots at http://localhost:5173. Image jobs flow through QStash and progress updates stream via WebSocket β no extra processes needed.
npm run stripe:listenKafka is fully wired up but parked to save infrastructure cost. To turn it on, set QUEUE_BACKEND=kafka and the KAFKA_* vars in .env, then run:
docker-compose -f infrastructure/kafka/docker-compose.kafka.yml up -d
npm run kafka:create-topics
npm run kafka:consumer # workers
npm run kafka:websocket # progress streamSee env.example for the full annotated template. The required groups are:
# Database
DATABASE_URL=
DIRECT_URL=
# Auth
SESSION_SECRET=
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
SUPABASE_URL=
SUPABASE_ANON_KEY=
# Image providers (at least one)
OPENAI_API_KEY=
HUGGINGFACE_API_KEY=
FAL_KEY=
REPLICATE_API_TOKEN=
IDEOGRAM_API_KEY=
TOGETHER_API_KEY=
BFL_API_KEY=
# Video providers
RUNWAY_API_KEY=
LUMAAI_API_KEY=
STABILITY_API_KEY=
# Cache & queue
UPSTASH_REDIS_REST_URL=
UPSTASH_REDIS_REST_TOKEN=
QSTASH_TOKEN=
QSTASH_CURRENT_SIGNING_KEY=
QSTASH_NEXT_SIGNING_KEY=
QUEUE_BACKEND=qstash # "qstash" (default) or "kafka"
# Storage
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_REGION=us-east-1
S3_BUCKET_NAME=
# Payments
STRIPE_PUBLIC_KEY=
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=
# Monitoring (optional but recommended)
SENTRY_ORG=
SENTRY_PROJECT=
SENTRY_AUTH_TOKEN=npm run dev # Vite dev server (http://localhost:5173)
npm run build # Production build (remix vite:build)
npm run start # Start production server (remix-serve)
npm run typecheck # TypeScript checks
npm run lint # ESLintnpm run test # Vitest watch mode
npm run test:run # Vitest single run
npm run test:coverage # Vitest with v8 coverage
npm run test:e2e # Playwright E2E suite
npm run test:e2e:ui # Playwright UI modenpx prisma studio # Visual DB browser
npx prisma db push # Push schema
npx prisma generate # Generate client
npx prisma migrate dev # Create migrationnpm run kafka:create-topics
npm run kafka:consumer
npm run kafka:websocket
npm run kafka:health
npm run kafka:monitornpm run stripe:listen # Stripe webhook forwarding β localhost:5173/webhook
npm run video:backfill-thumbnails # Backfill thumbnails for existing videosgraph TD
A["Create form"] --> B["Remix action"]
B --> C["QStash publish"]
C --> D["/api/queue/process-image"]
D --> E["Provider SDK call"]
E --> F["S3 upload"]
F --> G["Postgres update"]
G --> H["WebSocket broadcast"]
H --> I["Live UI progress"]
I --> J["Redirect to results"]
pixel-studio/
βββ app/
β βββ components/ # 55 UI components (incl. shadcn primitives + ps/* design system)
β βββ config/ # Models, pricing, breakpoints, build logs
β βββ contexts/ # Generation progress context
β βββ hooks/ # Custom React hooks
β βββ pages/ # Page-level components
β βββ routes/ # 96 Remix routes (pages + 47 API endpoints)
β βββ schemas/ # Zod validation
β βββ server/ # Server-only utilities (74 files)
β βββ services/ # Business logic (35 files)
β βββ utils/ # Shared utilities
β βββ client/ # Client-only utilities
βββ infrastructure/kafka/ # Optional Kafka deployment (Docker, AWS MSK)
βββ prisma/ # Schema (43 models) + migrations
βββ scripts/ # Background workers + maintenance scripts
βββ tests/ # Playwright E2E suite
βββ docs/images/screenshots/ # README screenshots
βββ pr-screenshots/ # Historical UI snapshots
The app supports three queue back-ends, toggled via QUEUE_BACKEND:
| Mode | Setting | When to use |
|---|---|---|
| QStash (default) | QUEUE_BACKEND=qstash |
Production and local dev. Zero-ops async pipeline with retries + signed webhooks. Local dev simulates QStash without an account. |
| Kafka (on hold) | QUEUE_BACKEND=kafka + KAFKA_* vars |
High-throughput scale-out. Requires the Kafka consumers and WebSocket workers to be running. |
| Synchronous (legacy) | ENABLE_KAFKA_IMAGE_GENERATION=false, no QStash config |
Debugging only β blocks the request until the model finishes. |
Multi-model comparison is supported in both async modes via the ComparisonRequest / ComparisonGeneration models.
- Unit tests (Vitest 4) β colocated as
*.test.ts(x). 21+ files across server, services, utils, components, contexts. Run withnpm run test. - E2E (Playwright) β in
tests/, 12 specs covering pages, create flows, notifications, streaks, admin audit, sets, video, and the progress toaster. Run withnpm run test:e2e. - Coverage β
npm run test:coverage(v8 reporter).
| Document | Purpose |
|---|---|
ARCHITECTURE.md |
High-level system architecture |
TECHNICAL_IMPLEMENTATION_GUIDE.md |
Deep dive into how things are wired up |
API.md |
API endpoint reference |
DEVELOPMENT.md |
Local dev setup |
TESTING.md |
Testing guide |
CACHING_STRATEGY.md |
Redis caching strategy |
KAFKA_ENVIRONMENT_SETUP.md |
Kafka config (when re-enabling) |
infrastructure/kafka/README.md |
Kafka deployment details |
CHANGELOG.md |
Version history |
BUGFIXES.md |
Bug-fix log with root-cause notes |
CONTRIBUTING.md |
Contribution guidelines |
IMPROVEMENT_STRATEGY.md |
Roadmap |
REDESIGN_FOLLOWUPS.md |
Outstanding tasks from PR #150 |
- Fork the repo
- Create a feature branch:
git checkout -b feat/short-description npm installand configure.env- Make your change. Run the pre-commit gate:
npm run lint && npm run typecheck && npm run test:run && npm run build
- Add an entry to
CHANGELOG.md. If you fixed a notable bug, add a root-cause note toBUGFIXES.md. - Open a PR. Husky + lint-staged will keep your commits clean automatically.
See CONTRIBUTING.md for the long form.
Database connection errors
echo $DATABASE_URL
npx prisma db push # also validates the connectionQStash jobs not firing locally
- Confirm
QSTASH_TOKENand both signing keys are set. - Watch the dev server logs for
[qstash]lines β local dev simulates QStash when keys are absent.
WebSocket connection failures (Kafka mode)
curl -I http://localhost:3001/health
lsof -i :3001Image generation errors
- Verify the provider API key for the model you selected (
OPENAI_API_KEY,FAL_KEY, etc.). - Check S3 permissions for
S3_BUCKET_NAME. - Look at the request in
GenerationLogfor the failure reason.
Pixel Studio is deployed primarily to Vercel using the @vercel/remix preset. The Express server (server.js) is available for non-Vercel hosts.
npm i -g vercel
vercelIn the Vercel dashboard:
- Add every variable from your
.env(seeenv.example). - Keep
QUEUE_BACKEND=qstashβ QStash works natively on serverless without long-running workers.
Use server.js as the entry point (node server.js) with PM2 or systemd. If you turn Kafka back on, run scripts/startConsumers.ts and scripts/startWebSocketServer.ts as separate services.
- All required env vars present in the target environment
-
DATABASE_URLreachable from the deploy host - S3 bucket exists and credentials have
PutObject/GetObjectpermissions - Stripe webhook secret matches the configured endpoint
- QStash signing keys match the dashboard
- Sentry DSN configured if you want error tracking
MIT β see LICENSE.
Remix Β· OpenAI Β· Hugging Face Β· Stability AI Β· Runway Β· Luma Β· Tailwind CSS Β· Prisma Β· Radix UI Β· Upstash Β· Vercel
Built with β€οΈ by Kevin Reber