# wardrowbe: a self-hosted wardrobe app that labels clothes with a vision model

> wardrowbe is an MIT licensed self-hosted application that photographs your clothes, has an AI vision model tag them, and suggests outfits by weather and occasion, built on Next.js, FastAPI, Postgres and Redis. The judgement is that the local-first story is real, since the AI provider is pluggable and can be Ollama on the same machine, and that the interesting engineering sits in the configuration layer rather than in the wardrobe features.

**Anyesh/wardrowbe** — Put your wardrobe in rows. Self-hosted AI-powered wardrobe management app.

- Repository: https://github.com/Anyesh/wardrowbe
- Website: https://wardrowbe.com
- Stars: 798 · Forks: 165
- Language: Python
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/anyesh-wardrowbe

## Photograph the clothes, let a model tag them, wear what it suggests

wardrowbe describes itself in three words, put your wardrobe in rows, followed by snap, organize, wear. The repository description is more specific: it is a self-hosted, AI-powered wardrobe management application, and the product site is wardrowbe.com.

The feature list explains the loop. You upload a photo of a garment and the AI extracts the clothing details, which means colours, patterns and styles. Recommendations are matched to weather, occasion and your stated preferences. Notifications are scheduled, delivered over ntfy, Mattermost or email, so a daily suggestion arrives without opening the application. A family mode manages wardrobes for several household members, wear tracking keeps the history with ratings and outfit feedback, and the analytics view shows what you wear, what you never wear and how your wardrobe is distributed by colour.

The stack badges give the shape of the thing: Next.js and TypeScript on the front, FastAPI and Python behind it, and a badge for having been built with Claude Code. The application is MIT licensed and published on the App Store, while the Google Play badge still reads coming soon, so the mobile story is one platform wide for now.

## Quick start is a clone, four compose commands and a migration

The requirements are stated without hedging. You need Docker with Docker Compose, about four gigabytes of memory if you run local Ollama models, and an AI service of some kind. The published images are multi-arch for linux/amd64 and linux/arm64, so the same stack runs on a Raspberry Pi 5.

The setup sequence is short enough to paste:

```bash
git clone https://github.com/Anyesh/wardrowbe.git
cd wardrowbe
cp .env.example .env    # then set the AI_* values, see AI Configuration below
docker compose pull
docker compose up -d
docker compose exec backend alembic upgrade head
curl http://localhost:8000/api/v1/health    # {"status":"healthy"}
```

The last line is the readiness check, and the database migration is a separate step because it runs inside the backend container through alembic rather than during image build.

Then you open http://localhost:3000 and click Login, and here the README delivers the warning that matters most: the default development login needs no password. Before exposing the application beyond your own machine you have to set SECRET_KEY and NEXTAUTH_SECRET in the .env file, generated with openssl rand -hex 32, and set up authentication properly.

For development with hot reload there is a second stack, docker-compose.dev.yml layered on top of the main file with docker compose -f.

## One OpenAI-compatible base URL, a vision model and a text model

The AI configuration is the part of the project that will decide whether it works for you, and it is designed around two model roles rather than around a single provider.

The vision model analyses clothing images to extract colours, patterns and styles. The text model generates outfit recommendations and descriptions. Any OpenAI-compatible API can serve them, and the README lists the working combinations.

For self-hosting it recommends Ollama, which is free, runs locally, needs no API key and works offline. The model to pull is:

```bash
ollama pull gemma3:latest    # 3.4GB
```

and the environment to point at it is:

```env
AI_BASE_URL=http://host.docker.internal:11434/v1
AI_API_KEY=not-needed
AI_VISION_MODEL=gemma3:latest
AI_TEXT_MODEL=gemma3:latest
```

The README explains why the host name is not localhost: containers reach the host machine through host.docker.internal, so a local Ollama is reachable from inside the stack.

For OpenAI the keys become AI_BASE_URL=https://api.openai.com/v1, an API key, and gpt-4o for both roles, while LocalAI is configured as a separate base URL with its own model names. One model can serve both roles if it handles images and text, and llama3.2-vision:11b is given as the example, with llama3:latest, qwen2.5:latest and mistral:latest named as text models that work.

## The internal AI can be switched off, capability by capability

An application that calls a model is usually an application that cannot start without one. wardrowbe handles this by making the internal AI optional and by separating the two capabilities.

Setting AI_INTERNAL_ENABLED=false runs the backend with no internal AI provider at all. It boots and serves without AI_BASE_URL, AI_API_KEY or any model names configured, and the tagging, suggestion and pairing features are deferred to an external agent instead. In other words, the application becomes a normal wardrobe tracker with a documented interface for an agent to drive, and the agent can live anywhere.

The same file also allows one capability to be disabled while the other stays on. AI_VISION_ENABLED=false turns off the automatic tagging of uploaded photos, and AI_TEXT_ENABLED=false turns off the suggestions, which is the pair to use when you would rather fill in the attributes by hand but still want the daily outfit prompt.

The rest of the AI settings follow the same pattern of fine control. There is a timeout, a maximum retry count, a tagging concurrency limit, a retry cooldown in seconds and a reasoning effort setting, and the maximum image size is capped by MAX_IMAGE_MEGAPIXELS, which defaults to 50.

## The compose file treats configuration as one shared block

The docker-compose file contains a comment that explains more about the project than any feature list would. Every process built from the backend image loads the same Settings object, so they all merge one shared block of environment variables, and a key added to a single service never reaches the others. The worker that sends notifications therefore needs APP_URL and the SMTP settings as much as the API does, and the fix for that is to add the key to the shared block rather than to one service.

The block itself is long and reveals the shape of the application. Storage path is /data/wardrobe. The database URL is a postgresql+asyncpg connection and Redis is used alongside it. The container user is configurable through PUID and PGID so that bind-mounted directories keep sane ownership on the host. Notification settings cover both an ntfy server with a token and a full SMTP set with TLS and a sender name.

The database service is postgres:15-alpine with the container named wardrobe-db, and there are separate compose files for development and production, an nginx directory, a Caddyfile.dev for local TLS, a k8s directory for Kubernetes deployments and a docs directory.

## The dev login is convenient and the backend knows it

Authentication deserves a section of its own, because the default is deliberately open and the documentation is precise about when it closes.

The .env.example file is annotated rather than bare. It carries the database and Redis settings, the backend port and a secret key with a placeholder value, change-me-in-production, and a comment telling you to replace it with a value from openssl rand -hex 32. It also explains that the secret can be changed even in development, because the dev login no longer depends on the default value being left in place.

The dev credential login is activated whenever DEBUG is true and no OIDC provider is configured. That is the mechanism behind the passwordless login on first run, and it is tied to the debug flag rather than to the secret, which is the safer of the two designs.

The important sentence is the one about refusal. The backend refuses to start with the default secret once OIDC or FORWARD_AUTH_SECRET is set, even with DEBUG=true, because at that point it is signing real user tokens. So a deployment that adds an identity provider cannot accidentally keep the placeholder key, and a deployment that stays on DEBUG with no identity provider is a development instance by definition.

That is a small amount of care in a place where most self-hosted applications leave the default in place.

## Eight languages, family wardrobes and releases every few weeks

Two smaller things round out the picture.

The interface ships in eight languages, English, Simplified and Traditional Chinese, Korean, Japanese, French, German and Italian. You pick one in Settings or let it follow the browser, and the contributing guide has a section on internationalisation for adding or improving a translation, which means the strings are treated as a shared resource rather than as an afterthought in one language.

The release history shows a project shipping steadily. Version 1.10.2 was published on 2026-09-30, 1.10.3 on 2026-10-03 and 1.11.0 on 2026-10-11, with the last push on 2026-10-22. The release tooling is release-please, with a manifest and a configuration file at the repository root, and there is a pre-commit configuration alongside a changelog and a security policy.

Those are the details that matter for anyone running their own copy. The features are pleasant, but the operational picture, an Alembic migration on every upgrade, a shared configuration block, a placeholder secret that the backend will not accept in production, is what decides whether a self-hosted wardrobe survives a year of use.

## Conclusion

wardrowbe fits a household that wants clothing photos and outfit history stored on its own hardware and wants the tagging and suggestion step to run against a local model rather than a hosted API, because the whole AI layer is addressed through an OpenAI-compatible base URL and can point at Ollama on the same machine. It is the wrong choice if you want a mobile-first application today, since the Google Play badge still reads coming soon and only the iOS build is published, and it is the wrong choice if you cannot give the stack roughly four gigabytes of memory and a container runtime. Before you expose it beyond your own machine, generate the secrets with openssl rand -hex 32 and set SECRET_KEY and NEXTAUTH_SECRET, because the development login needs no password, and decide whether the internal AI is enabled at all, since AI_INTERNAL_ENABLED=false hands tagging, suggestions and pairings to an external agent instead.

## FAQ

### How do I run wardrowbe on my own machine?

Clone the repository, copy .env.example to .env, set the AI values, then run docker compose pull, docker compose up -d and docker compose exec backend alembic upgrade head. The health check is curl http://localhost:8000/api/v1/health and the interface is on http://localhost:3000.

### Can wardrowbe use a local AI model instead of OpenAI?

Yes. It works with any OpenAI-compatible API, so Ollama or LocalAI can serve it. For Ollama the README suggests pulling gemma3:latest and pointing AI_BASE_URL at http://host.docker.internal:11434/v1, which is the address a container uses to reach the host machine.

### Does wardrowbe work without an AI provider configured?

It runs. Setting AI_INTERNAL_ENABLED=false boots the backend with no AI_BASE_URL, API key or model names, and defers tagging, suggestions and pairings to an external agent. Individual capabilities can be switched off as well with AI_VISION_ENABLED and AI_TEXT_ENABLED.

### Is the default wardrowbe login secure?

The default development login needs no password and works while DEBUG is true with no OIDC provider configured. The README says to set SECRET_KEY and NEXTAUTH_SECRET, generated with openssl rand -hex 32, and to set up authentication before exposing the application.

## Sources

- [Anyesh/wardrowbe on GitHub](https://github.com/Anyesh/wardrowbe)
- [License: MIT](https://github.com/Anyesh/wardrowbe/blob/main/LICENSE)
- [Project website](https://wardrowbe.com)
- [README](https://github.com/Anyesh/wardrowbe/blob/main/README.md)
- [Releases](https://github.com/Anyesh/wardrowbe/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/anyesh-wardrowbe
