Part 1Marc de Batlle
0%
Part 1Marc de Batlle
All work07 / 11
Eight

WRDBAn AI virtual wardrobe for iOS, and the data machine behind it.

Chapter concepts
  1. 1Photograph your clothes; WRDB recognizes them, organizes the closet and recommends outfits from what you own. I wrote the first version, own the ML and the analytics, and built the marketing machine that promotes it.
  2. 2Role: Co-founder, CEO & CFO. Status: TestFlight.
  3. 3Stack: Swift, SwiftUI, Core ML, Supabase, Next.js, TypeScript, SQL.
  4. 4Key figure: 745 commits across Swift, SQL, TS and Python.
07
PeriodAug 2025 to present
RoleCo-founder, CEO & CFO
StatusTestFlight

The company

We wear about 20% of what we own. The rest is invisible: forgotten in a drawer, lost behind the decision fatigue of every morning. WRDB closes that gap. You photograph a garment, the app removes the background and tags it, and from then on it builds outfits for you from what is actually in your closet, with a social feed where friends post their outfit of the day.

Three founders: Alex Matos is CTO, Pep Bustamante is CMO, and I am CEO and CFO. In practice I own data, machine learning, analytics and growth, and I wrote the first version of the app myself. Legal entity WRDB SCP, Barcelona. The app is live on TestFlight and the App Store review is ongoing.

We wear about 20% of what we own. The rest is invisible.

The company
The product on 15 September 2026, production database
145
Accounts
+2 in September
2,129
Garments in production
+55 in September
351
Outfits created
+5 in September
9
Monthly active users, week of 14 September
Peak 47, week of 1 June
59%
Add a garment within 24 hours
85 of 145 accounts
16%
Any session after day 30, May and June cohorts
12 of 76 accounts
Exhibit 8-4
App signups by month
Accounts created, November 2025 to 15 September 2026
025506Nov16Dec3Jan23Feb4Mar10Apr42May34Jun2Jul3Aug2Sep

The first build

The repository starts on 29 July 2025 with my base code. The first working outfit generation landed on 2 August, the database schema and cost-tuned agents on 1 August, and a Clean Architecture rewrite on 26 August: Presentation, UseCases, Domain and Data layers with dependencies pointing inward, so use cases test without a network or a simulator.

I am the original author of the DI container, the app entry point, the domain entities and validators, twelve repository protocols and their remote implementations. Since then my co-founder has carried most of the later refactoring, social features and pre-launch hardening while I moved to the data side.

Exhibit 8-6
From photo to outfit
  1. 1.Photo
  2. 2.Background removal (PhotoRoom, edge function)
  3. 3.Tagging with gpt-4o-mini (edge function)
  4. 4.FashionCLIP embedding on-device (512-d)
  5. 5.Outfit generator scores combinations
  6. 6.Preference learner re-ranks

The ML

The embeddings run on the phone. I built the PyTorch-to-Core ML conversion pipelines for FashionCLIP (a CLIP ViT-B/32 fashion encoder): download, wrap, convert to an fp16 mlpackage, validate parity against PyTorch, and generate the Swift integration. The model unloads after sixty seconds of inactivity to save memory.

The outfit generator scores color harmony, style consistency, occasion fit, weather appropriateness from WeatherKit across eight temperature bands, and vector similarity, evaluating up to 500 combinations per session with a diversity pass so the five suggestions are not the same outfit five times. A linear preference learner updates eight-dimensional weights from what the user accepts, rejects, modifies and wears, batched with a five-second debounce. Occasion learning and custom occasions shipped in April 2026.

Product analytics

In March 2026 I audited the analytics gap and shipped the fix in one day across fourteen phases: TelemetryDeck with 33 consent-gated signals (sessions, screen time, onboarding, outfit accepted or rejected or worn, ads, image upload, API latency, errors), a Supabase cron warehouse for DAU, retention cohorts, churn, bounce and the activation funnel, and a Next.js dashboard to read it all.

The dashboard is 32 pages on Next.js 14, Recharts and TanStack Query. One page is genuinely realtime: a live activity feed that subscribes over Supabase Realtime to signups, garments added, outfits posted, follows and affiliate clicks. The rest queries the warehouse on demand. Alerts do not live in the dashboard at all; they go to Slack through 29 edge functions, including a slash command that turns a natural-language question into a database query.

Exhibit 8-9

Monthly active users by week
27 April to 14 September 2026, from the app metrics table
0255047, 1 Jun927 Apr25 May22 Jun20 Jul17 Aug14 Sep
Dashboard pages
  1. 1KPI overview: users, garments, outfits, 30-day deltas
  2. 2Live feed: Supabase Realtime, five tables
  3. 3Activation funnel: weekly cohorts
  4. 4Churn and bounce: reactivation tracking
  5. 5Outfit intelligence: generation analytics
  6. 6Social: follow growth, community health
  7. 7Ads and affiliate: impressions, conversions, revenue
  8. 8Performance: TTFI, API latency
  9. 9Marketing: 17 pages: calendar, queue, hooks, DNA, attribution

The growth machine

Marketing had to run without a marketing budget, so I built it as software. Six layers: a context brain of brand, audience and competitor documents; market intelligence; a strategy layer that writes a content calendar straight into Postgres; a content factory; publishing; and analytics that feed back into the brain. Total additional cost: 15 EUR of image credits, bought once, on subscriptions we already paid for.

Publishing is a cron every fifteen minutes that posts through the Meta Graph API and the TikTok Content Posting API with a UTM link per post. Daily pulls collect post and account metrics, detect anomalies (viral, underperformer, engagement drops, A/B winners) and score every post on a composite. Each post is tagged by hook style, emotion, call to action, visual style and trend, so the system learns which formula wins per platform. In June 2026 I added an auto-generator: a daily job that rotates a hook bank, renders reels from HTML with HyperFrames and Higgsfield, uploads them and queues them for an AI persona account. The first batch was twenty reels scheduled over two weeks.

Exhibit 8-12
Marketing machine, scheduled functions
FunctionScheduleDoes
publish-scheduled-postsevery 15 minPosts to Instagram, Facebook, TikTok
refresh-platform-tokensevery 6 hKeeps OAuth tokens alive
pull-post-analyticsdaily 08:00Metrics per post, anomaly detection
pull-account-snapshotsdaily 09:00Follower and reach snapshots
compute-weekly-summaryMondays 10:00Week over week summary
generate-context-digestMondays 11:00Feeds findings back to the brain
sync-attributiondaily 12:00Links installs to posts
*All eight functions run on Supabase edge functions and pg_cron. Alerts route to Slack.

The affiliate marketplace

The revenue model is affiliate commerce: recommend a product that fills a gap in someone's wardrobe, earn a commission when they buy it. I owned that side end to end, from the partnerships to the recommendation engine. In January 2026 I applied to the affiliate networks with a publisher profile and the pitch deck. CJ Affiliate blocked us because a promotional property needs a live App Store link; Awin España accepted the application on a refundable one-euro deposit. Inside Awin I applied programme by programme: thejewellershop.com ES joined on 29 January 2026, with a 16 percent conversion rate and 1.58 EUR earned per click on the network's own figures, then Bonheur Jewelry, Dooers and Zapatos OBI were accepted and Palomo Spain applied for.

A joined programme gives you a product feed and a tracked deep link per product. The jeweller's feed is a gzipped CSV of 14,274 products refreshed every four hours. A script downloads and parses it, a price filter from 2 to 150 EUR leaves 6,111, and a curation pass with category and brand exclusions, de-duplication on model number and a quality score selects the catalogue: 100 products at first, then 200 split evenly between women and men, and about 300 today across the programmes. Each product goes into the database with its affiliate link, its image with the background removed and its bounding box measured so it can sit in a flatlay next to the user's own clothes, tags from gpt-4o-mini for colour, style, material, season and occasion, a gender derived from the merchant category, and a 512-dimensional CLIP vector in a pgvector column, the same embedding the user's garments carry.

The marketplace has three tabs: For You, Missing in Wardrobe and Discover. One SQL function scores every product for the user in seven steps and returns a ranked page with a reason code. Two scores blend: a discovery score from global popularity, product quality, recency, click-through and a little exploration noise, and a personal score from CLIP similarity to the user's wardrobe, past interactions, wardrobe gaps by category, style, colour and price. How much of each depends on a richness score, a saturating function of how many garments, vectors, outfits and interactions the user has, so a new user sees discovery and a power user sees their own taste, with no threshold and no cold-start switch. Missing in Wardrobe raises the gap weight to 60 percent; Discover is the same feed for everyone. Dismissed products carry a penalty for thirty days, every page caps brands at three and categories at five, and every impression, view, click, save and dismissal is kept raw for training and rolled up by triggers and cron jobs into per-product and per-user statistics. Purchases arrive from Awin on a webhook that posts to Slack.

Exhibit 8-14
From merchant feed to a recommendation
  1. 1.Awin programme joined; feed and deep links unlocked
  2. 2.fetch-awin-feed: gzip CSV, 14,274 products
  3. 3.Price filter 2 to 150 EUR: 6,111
  4. 4.filter-feed: exclusions, dedup, quality score
  5. 5.Ingest: background removal, bounds, gpt-4o-mini tags, gender
  6. 6.CLIP vector, 512-d, pgvector
  7. 7.get_marketplace_feed scores and ranks per user
  8. 8.Tap: deep link out; purchase webhook to Slack
Exhibit 8-15
Marketplace scoring signals
TrackSignalWeight
DiscoveryGlobal popularity from engagement0.35
DiscoveryProduct quality score0.25
DiscoveryRecency0.20
DiscoveryGlobal click-through rate0.10
DiscoveryExploration noise0.10
PersonalCLIP similarity to the user's garments0.30
PersonalInteractions with similar products0.25
PersonalWardrobe gap by category0.15, 0.60 in Missing in Wardrobe
PersonalStyle match, behavioural taste, colour, price0.10, 0.10, 0.05, 0.05
PenaltyOpposite gender, dismissed in 30 days, already saved-0.6, -0.9, -0.1
*final score = (1 - richness) × discovery + richness × personal + penalties. Richness runs from 0 for a new account to about 1 for a power user.
Other revenue lines
  1. 1Native ads: AdMob with consent management, shipped Nov 2025
  2. 2UGC programme: 8 creator dossiers, 4 EUR CPM plus a tiered base fee
  3. 3Data as an asset: wardrobe-gap intent data for brands
At a glance
PlatformiOS 17.6+, Swift 5.9, SwiftUI
On-deviceFashionCLIP embeddings, outfit generation, preference learning
CloudSupabase: Postgres, auth, 59 edge functions, 179 migrations
Codebaseabout 157K lines: Swift, TypeScript, SQL
Tests133 unit tests, 279 RLS policies
My roleCo-founder, CEO & CFO; data, ML, analytics, growth
StatusTestFlight beta, App Store review ongoing
Continue