Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PixelForge Studio

A self-hosted text-to-image and image-to-image generation studio built on Stable Diffusion XL, FastAPI, and React. Deployed and tested end-to-end on a single T4 GPU using Lightning AI Studios, with a full write-up of the build process linked below.


Table of Contents


Overview

PixelForge Studio is a personal image generation tool built to explore the full stack of running a diffusion model as a real application, not just a notebook demo. It consists of a FastAPI backend that loads Stable Diffusion XL (base 1.0) once at startup and serves both text-to-image and image-to-image requests, and a React (Vite) frontend that exposes generation controls, a live preview, and a persistent gallery of past generations.

The project was built and deployed on a Lightning AI Studio using a single NVIDIA T4 (16GB) GPU, with the goal of keeping the entire workflow usable within a free monthly compute allowance for personal/demo usage(s).

Example Outputs

Example outputs collage

A collage of outputs generated using this app across different prompts, schedulers, and quality presets. Individual examples with details:

Prompt theme Scheduler Notes
Ninja Bear DPM++ 2M High quality preset, 16:9
Fractal Girl Euler Ancestral Standard preset, 4:3
Mountain Panaroma DDIM Standard preset, 16:9

See the full gallery in docs/examples/ for more outputs across prompts, schedulers, and quality presets.

Demo

Demo

A walkthrough of prompt entry, parameter selection, generation, and the gallery view.

Features

  • Text-to-image generation using Stable Diffusion XL base 1.0, served through a single always-loaded FastAPI pipeline.
  • Image-to-image generation with adjustable denoising strength, using the same underlying weights (no duplicate model in memory).
  • Quality presets (draft, standard, high) mapping to tuned step count and guidance scale combinations, with optional manual overrides.
  • Aspect ratio presets covering common ratios (1:1, 4:3, 3:4, 16:9, 9:16, 3:2, 2:3), each using dimensions that are valid multiples of 8 for SDXL's latent space.
  • Scheduler selection at request time (Euler Ancestral, DPM++ 2M, DDIM) without reloading the model.
  • Generation history / gallery, persisted to disk (backend/data/history.json) and viewable in the frontend's Gallery tab, with delete support.
  • Basic per-client rate limiting on the generation endpoints to avoid accidental GPU overuse.
  • Configurable CORS, so the deployed frontend origin can be locked down in production instead of left wide open.

Architecture

High Level Diagram

The backend and frontend run as two separate processes on the same GPU-backed host during development and personal use. The SDXL weights are loaded exactly once at process startup and reused across every request; no per-request model loading occurs.

Tech Stack

Backend

  • Python, FastAPI, Uvicorn
  • Hugging Face diffusers, transformers, accelerate
  • PyTorch (CUDA), xformers for memory-efficient attention
  • Pillow for image I/O

Frontend

  • React 18, Vite
  • React Router

Infrastructure

  • NVIDIA T4 (16GB) GPU via Lightning AI Studios
  • Hugging Face Hub for model weight distribution and local caching

Getting Started

Prerequisites

  • Python 3.10+
  • Node.js 18+ and npm
  • make (optional, only needed if you want to use the provided Makefile shortcuts)
  • An NVIDIA GPU with at least 16GB VRAM (a T4 is sufficient for SDXL base in fp16)
  • A Hugging Face account and access token if the model requires authenticated download

Clone the Repository

git clone <your-repository-url>.git
cd <your-repository-name>

Backend Setup

cd backend
python -m venv venv
source venv/bin/activate        # On Windows: venv\Scripts\activate

pip install -r requirements.txt

cp .env.example .env            # then fill in the values, see Environment Variables below

uvicorn main:app --host 0.0.0.0 --port 4000

On first run, the backend downloads the SDXL base 1.0 weights (~7GB) from Hugging Face and caches them locally under the path set in HF_HOME. Subsequent restarts load from the local cache and skip the download.

Confirm the backend is healthy:

curl http://localhost:4000/api/health

Frontend Setup

cd frontend
npm install

cp .env.example .env             # set VITE_API_URL to your backend's address

npm run dev

The frontend expects the backend URL in VITE_API_URL (for example http://localhost:4000, or your GPU host's public forwarded URL when deployed remotely).

Optional: Running Both with the Makefile

Instead of running the backend and frontend in two separate terminals, a Makefile is included at the repository root with shortcuts for common tasks:

cd pixelforge-sdxl/
make install    # installs backend and frontend dependencies
make        # runs backend and frontend together in one terminal

This is entirely optional — running each service manually as shown above works the same way.

Environment Variables

Backend (backend/.env)

Variable Description Example
CORS_ORIGINS Comma-separated list of allowed frontend origins. Use * only for local testing. https://your-frontend.example.com
RATE_LIMIT_PER_MINUTE Max generation requests allowed per client IP per minute. 20
HF_HOME Local path used to cache downloaded Hugging Face model weights. /data/.cache/huggingface
HF_TOKEN Hugging Face access token, if required for the model repository. hf_xxxxxxxxxxxx

Frontend (frontend/.env)

Variable Description Example
VITE_API_URL Base URL of the running backend. http://localhost:4000

API Reference

Method Endpoint Description
GET /api/health Returns service status plus the available quality presets and aspect ratios.
POST /api/generate1 Text-to-image generation. Body: prompt, quality, aspect ratio, scheduler.
POST /api/generate2 Image-to-image generation. Body: prompt, quality, scheduler, base64-encoded init image.
GET /api/history Returns the full generation history.
GET /api/history/{id} Returns a single history record by ID.
DELETE /api/history/{id} Deletes a history record and its associated image files.

Generated and uploaded images are served as static files under /generated/* and /uploads/* respectively.

Generation Parameters

Quality presets (steps, guidance scale):

Preset Steps Guidance Scale Use case
draft 30 5.0 Fast iteration on prompt wording and composition
standard 40 7.0 Balanced default for most generations
high 50 8.5 Final output quality, slower

Aspect ratios (width x height, SDXL-valid dimensions):

Ratio Dimensions
1:1 1024 x 1024
4:3 1152 x 896
3:4 896 x 1152
16:9 1344 x 768
9:16 768 x 1344
3:2 1216 x 832
2:3 832 x 1216

Schedulers: Euler Ancestral, DPM++ 2M, DDIM. Switching schedulers does not reload the model, so it can be changed freely between requests.

Learnings

Measured observations from running this app end-to-end on a single T4 (16GB) GPU:

  • Generation time scales roughly linearly with step count. At 1024x1024 with DPM++ 2M, inference cost was approximately 0.3-0.4 seconds per step once the model was warm. This put draft (30 steps) at roughly 10-12 seconds per image, standard (40 steps) at roughly 14-16 seconds, and high (50 steps) at roughly 18-20 seconds. Doubling steps roughly doubles latency, so step count is the primary lever for the speed-versus-quality trade-off, not guidance scale.
  • Guidance scale affects prompt adherence more than visual fidelity. Moving from a guidance scale of 5.0 to 8.5 with the same step count did not meaningfully change render time, but produced noticeably closer alignment to the literal prompt text at the cost of some naturalness in lighting and texture at the higher end. This is why quality presets pair a higher guidance scale with higher steps rather than treating them as independent controls.
  • Scheduler choice changed the steps needed for comparable output quality. DPM++ 2M produced results at 25-30 steps that were visually comparable to Euler Ancestral at 35-40 steps, an effective 25-30 percent reduction in generation time for similar perceived quality, since DPM++ 2M converges faster per step.
  • VRAM headroom on a T4 was sufficient for single-image batches with margin to spare. SDXL base 1.0 in fp16 with xformers enabled used approximately 7.5-8GB of the 16GB available at 1024x1024. This left enough headroom for a batch size of 2 in most cases, but batch size 3 or more at 1024x1024 pushed close to the VRAM ceiling and risked out-of-memory errors.
  • Cold start cost is dominated by download, not by loading from cache. The first run downloaded approximately 6.9GB of fp16 weights, taking 3-4 minutes depending on network conditions. Every subsequent process start loaded the same weights from the local Hugging Face cache in under 30 seconds, confirming that model loading is a one-time-per-process cost, not a per-request one, provided the pipeline is instantiated at application startup rather than inside a request handler.
  • img2img strength has a narrow effective range for controlled edits. Strength values below approximately 0.4 preserved most of the input image's structure with only stylistic changes. Values above approximately 0.75 produced outputs that were largely indistinguishable from a fresh text-to-image generation, with only a loose compositional influence from the input image. The useful range for recognizable-but-modified edits sat roughly between 0.4 and 0.7.

Future Improvements

  • Add the SDXL refiner stage as an optional second pass for higher-fidelity final outputs.
  • Support LoRA loading for style-specific fine-tunes without needing a full model swap.
  • Add ControlNet support for pose, depth, or edge-guided generation.
  • Introduce a job queue so long-running generations do not block the request thread, with a polling or websocket-based status endpoint for the frontend.
  • Move from in-memory rate limiting and history storage to a proper database and shared cache (for example Redis) to support multiple concurrent users or instances.

Full Tutorial

The complete step-by-step write-up, covering environment setup, model selection reasoning, backend and frontend implementation, and the deployment process on Lightning AI, is available here:

link

License

This project is licensed under the License. See LICENSE for details.

Stable Diffusion XL base 1.0 is distributed by Stability AI under the CreativeML Open RAIL++-M License. Review its terms before any commercial use of generated outputs.

Acknowledgments

About

Self-hosted text-to-image and image-to-image generation studio built with Stable Diffusion XL, FastAPI, and React -- deployed on a single T4 GPU.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages