WallpaperMachine
The wallpapers you love. A new home on your Mac.
Upload clothing photos and get instant AI styling feedback.
Translation pending
LifestyleTypeScript · DockerfileGitHub @pranavraju24OnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Your AI personal stylist. Upload photos of your clothes to get instant styling feedback, build a searchable digital wardrobe, and generate complete outfits from pieces you already own — powered by Google Gemini vision.
| Layer | Choice |
|---|---|
| Framework | Next.js 16 (App Router) + TypeScript |
| Styling | Tailwind CSS v4 |
| AI / vision | Google Gemini (gemini-3.6-flash) via @google/genai |
| Database / Auth / Storage | Supabase (Postgres + Auth + Storage) |
The AI layer sits behind a provider-agnostic AIStylist interface
(src/lib/ai/), so the underlying model can be swapped without touching the
rest of the app.
flowchart LR
Browser(["User's browser"])
subgraph app["Next.js app (Vercel)"]
direction TB
Pages["Pages / SSR<br/>landing · analyze · closet · outfits · profile"]
Proxy["proxy.ts<br/>refresh session · guard routes"]
Server["Server Actions<br/>+ /api/analyze"]
AI["AIStylist interface<br/>→ GeminiStylist"]
end
Gemini["Google Gemini<br/>vision + text"]
subgraph sb["Supabase"]
direction TB
Auth["Auth"]
DB[("Postgres + RLS<br/>garments · profiles")]
Store["Storage<br/>private images"]
end
Browser -->|every request| Proxy
Browser -->|load page| Pages
Browser -->|submit form| Server
Server --> AI
AI -->|images + prompts| Gemini
Server -->|scoped by RLS| DB
Server --> Store
Proxy --> Auth
Server --> Auth
/api/analyze; wardrobe uploads and outfit
suggestions run through Server Actions.AIStylist
interface (src/lib/ai/). Swapping Gemini for another model means writing one
new class — the rest of the app is untouched — and it makes the AI layer easy to
unit-test by mocking the client.429/503 errors retry with
exponential backoff, while real errors fail fast. This is covered by tests.auth.uid()), not just in app
code — and an integration test proves user A can't read user B's data.git clone https://github.com/pranavraju24/outfitmax.git
cd outfitmax
npm install
Copy the example file and fill in your own values:
cp .env.example .env.local
| Variable | Where to find it |
|---|---|
GEMINI_API_KEY | Google AI Studio → Create API key |
NEXT_PUBLIC_SUPABASE_URL | Supabase → Project Settings → Data API |
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY | Supabase → Project Settings → API Keys (publishable) |
SUPABASE_SECRET_KEY | Supabase → Project Settings → API Keys (secret) |
.env.localis git-ignored — your real keys never get committed.
supabase/schema.sql. This creates the garments and
profiles tables with Row-Level Security and the required grants.garments
(Storage → New bucket → uncheck "Public bucket").npm run dev
Open http://localhost:3000.
The app ships a multi-stage Dockerfile (Next.js standalone output) and a
docker-compose.yml. With your env values in .env.local:
docker compose --env-file .env.local up --build
Supabase itself runs separately (your hosted project, or npx supabase start
for a local stack).
| Command | Description |
|---|---|
npm run dev | Start the development server |
npm run build | Production build |
npm run start | Serve the production build |
npm run lint | Run ESLint |
npm run typecheck | Type-check with tsc |
npm test | Run unit tests (Vitest) |
npm run test:integration | Run RLS integration tests (needs local Supabase) |
npm test) cover the AI layer: schema-validated output,
retry/backoff on transient errors, and the swappable-provider factory. The
Gemini client is mocked, so they're fast and need no network.npm run test:integration) run against a local
Supabase (npx supabase start) and prove Row-Level Security keeps each user's
wardrobe private.src/
├── app/
│ ├── page.tsx # Landing page
│ ├── analyze/ # Styling feedback (public)
│ ├── closet/ # Wardrobe: upload, grid, actions
│ ├── outfits/ # Outfit suggestions from your closet
│ ├── login/ # Auth screens + server actions
│ ├── profile/ # Account details + log out
│ ├── api/analyze/ # Styling feedback route handler
│ └── _components/ # Shared UI (header, marquee)
├── lib/
│ ├── ai/ # Provider-agnostic AIStylist (Gemini impl)
│ ├── supabase/ # Browser / server / admin clients
│ ├── auth/ # Data access layer (session gate)
│ └── wardrobe/ # Garment types + image storage helpers
└── proxy.ts # Route protection (Next.js 16 "proxy")
supabase/schema.sql # Database schema + RLS policies
This is a personal learning project. Secrets are read from environment variables and never committed; the Supabase secret key is used only in server-side code and never reaches the browser.