A full-stack application that generates a clothing preview from a photo of the user and an image of a clothing item. A React/TypeScript client handles uploads and displays results, while a Node.js/Express backend sends the images to Gemini.
The Gemini prompt attempts to preserve the person, pose, facial features, and background while changing the clothing. These details are not guaranteed to remain unchanged in the generated image.
| Input images | Generated try-on |
|---|---|
![]() |
![]() |
Try-on gallery
- The user selects a person photo and a clothing image, with previews before submission.
- The client sends two multipart image uploads to
POST /api/upload/userandPOST /api/upload/clothing. - The client submits the returned image paths to
POST /api/try-on. - The backend reads both files and sends a base64 multimodal request to Gemini through the Google Gen AI SDK, using
gemini-3-pro-image-preview. - The backend saves the generated image and session metadata. The client displays the result and includes completed try-ons in the gallery.
- Separate person and clothing uploads with previews and removal controls.
- Gemini-generated clothing previews from both image inputs.
- Uploading and processing indicators.
- A gallery showing completed results alongside their original inputs.
- Reuse of a person photo or generated result for another try-on.
- Local image and JSON session persistence across server restarts.
- Client: React 19, TypeScript, Vite 7, Tailwind CSS 4, DaisyUI, and Heroicons.
- Backend: Node.js, TypeScript, Express 4, Multer, dotenv, and nanoid.
- AI integration: Google Gen AI SDK (
@google/genai) and Gemini. - Development: concurrently, nodemon, and tsx.
React client → Express API → Gemini
↓
Local images and session JSON
client/src/components/: upload interface, processing modal, navigation, and gallery.client/src/services/api.ts: backend HTTP requests.server/src/routes/andserver/src/controllers/: upload and try-on endpoints.server/src/services/gemini.ts: multimodal request construction and response handling.server/uploads/: uploaded inputs and generated images, served through/uploads.server/data/sessions.json: session metadata managed byserver/src/data/tryOnSessions.ts.
Use Node.js 22.12 or later and npm. You need a Gemini API key with access to the configured image model.
From the repository root, install root, client, and server dependencies:
npm run install:allCopy the environment template if you do not already have server/.env:
cp server/.env.example server/.envSet your Gemini API key in server/.env, then start both development servers from the repository root:
npm run devOpen the URL printed by Vite (normally http://localhost:5173). The backend runs at http://localhost:3000.
Set these values in server/.env, replacing the API key placeholder locally:
GEMINI_API_KEY=your_gemini_api_key_here
PORT=3000GEMINI_API_KEY is required for generation. PORT is optional and defaults to 3000; use this port with the current client. Keep the key on the server and never commit it. The root .gitignore excludes environment files, uploads, and session data, with an exception for server/.env.example.
Results depend on the Gemini model. This is a visual preview, not a physical sizing tool. Images and sessions are stored locally for demonstration purposes.


