WallpaperMachine
당신이 사랑하는 배경화면, 맥에서 새롭게 만나보세요
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
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.