Aluvi — Product Requirements Document
Version: v1.8
Product: Aluvi iOS App
Platform: Swift (iOS)
MVP Scope: v1.0
Product Owner: Ardho
Date: April 2026
Last Updated: June 2, 2026
Status: Approved
Document Structure
| # | Section |
|---|---|
| 01 | Overview, Problem Statement & User Personas |
| 02 | Goals, Success Metrics & Out of Scope |
| 03 | Feature Specifications & User Stories |
| 04 | UX Flows & Screen Structure |
| 05 | Copywriting Per Screen |
| 06 | Technical Requirements & Constraints |
| 07 | Open Questions & Decisions Log |
Section 01 — Overview
Aluvi is an AI-powered skincare routine builder for iOS. It takes a user's skin type, concerns, budget, and products they already own — and generates a clear, personalized AM & PM routine in under 60 seconds. The app also flags ingredient conflicts, recommends missing products with affiliate links, and helps users stay consistent with their routine.
This PRD covers the MVP v1.0 scope, intended for handoff to the iOS (Swift) development team. Android is out of scope for MVP. The MVP targets the US market, English language only.
Section 01 — Problem Statement
The problem we're solving
US skincare consumers are overwhelmed. They watch TikTok tutorials, read Reddit threads, buy recommended products — and still don't know how to build a routine that works. The core problem is not lack of information. It's too much unstructured information with no clear, personalized path to action.
Market context
| Signal | Data | Source |
|---|---|---|
| US skincare market size | $24B+ | Statista, 2025 |
| US women using 3+ products daily | 68% | Industry data |
| AI-first routine builders in US App Store (iOS) | 0 | Competitive audit, April 2026 |
| Proven willingness to pay | $9.99/month | Comparable apps |
"Spent $200 on products and my skin is still breaking out."
— Common sentiment across r/SkincareAddiction, r/beauty, r/acne
Five core pain points (validated by Reddit research)
Pain 01 — Routine order confusion
Users don't know what order to apply products in, or whether AM and PM routines should differ. This is the single most common recurring question across skincare subreddits.
Pain 02 — Product overload
Users buy products based on TikTok and Reddit recommendations but can't figure out how to combine them into a coherent system. Information abundance does not equal confidence.
Pain 03 — Ingredient conflict anxiety
Fear of mixing actives incorrectly — retinol + AHA, vitamin C + niacinamide — and damaging the skin barrier. Users want reassurance, not just ingredient lists.
Pain 04 — Budget constraints
Especially acute among 18–28 users. They need the shortest path to an effective routine — not another shopping list that requires more spending.
Pain 05 — Desire for simplicity over complexity
Simplified routines are consistently recommended across beauty communities over complex ones. Consistency matters more than novelty. Fewer steps = easier to maintain.
Section 01 — Competitive Landscape
Existing alternatives and their limitations
| Tool | Job it does | What it misses |
|---|---|---|
| Yuka / Think Dirty | Ingredient safety scanning | No routine building |
| INCI Decoder / CosDNA | Ingredient lookup & analysis | No personalization or routine |
| SkinCarisma | Product & ingredient compatibility | No AM/PM routine generation |
| Curology | Personalized prescriptions | Requires medical framing, prescription |
| Halo (Aug 2025) | AI skin analysis | No "use products you already own" angle |
| Charm (3M users) | Skincare tracking | No AI routine builder |
Aluvi's white space
Existing tools cluster around one of: ingredient lookup, barcode scanning, toxic/clean labeling, routine logging, or product database reference.
Aluvi's most defensible position: Turn a user's current products, goals, and budget into a clear AM & PM routine with conflict awareness — in 60 seconds. No other app in the US App Store does this as its primary function.
Aluvi's strongest wedge is not "AI skincare expert."
It's routine clarity from chaos.
Section 01 — User Personas
Three primary personas for MVP v1. All share the same core frustration: they have products, they've done research, but they still don't have a clear routine.
Persona 01 — Sophia, 23 · "The Overwhelmed Beginner"
- Location: New York
- Occupation: College student
- Skin type: Acne-prone, combination
- Tags: Budget-conscious · TikTok-influenced · Has too many products
Background:
Sophia discovered skincare through TikTok. She's bought 6–8 products over the past year based on creator recommendations — The Ordinary niacinamide, CeraVe cleanser, a vitamin C serum, a retinol. She doesn't know what order to use them, whether to use all of them, or if some of them are canceling each other out.
Goals:
- Understand what to use in the morning vs at night
- Know which products to stop using together
- Keep her routine simple — she won't stick to anything with more than 4–5 steps
Frustrations:
- "I've watched so many videos and I still don't know what I'm doing"
- Scared to mix the wrong actives and break out worse
- Can't afford to keep buying new products every time an influencer recommends something
How Aluvi helps:
Aluvi takes her existing products, organizes them into a clear AM/PM order, and tells her what not to combine. She gets a routine she can actually follow — without buying anything new.
Persona 02 — Maya, 31 · "The Informed Overthinker"
- Location: Chicago
- Occupation: Marketing manager
- Skin type: Dry, early signs of aging
- Tags: Ingredient-aware · Reddit power user · Anti-aging focus
Background:
Maya has been into skincare for 3+ years. She reads r/SkincareAddiction regularly and knows the difference between AHA, BHA, and PHAs. She has a well-curated product shelf but second-guesses her routine constantly — "Am I using retinol too often? Should vitamin C go before or after moisturizer?"
Goals:
- Confirm her current routine is safe and optimized
- Get confidence around active ingredient scheduling (retinol on alternating nights, etc.)
- Understand the "why" behind each step
Frustrations:
- Information overload from conflicting Reddit advice
- Spends too much time validating routine decisions she should already be confident about
- Doesn't want a dumbed-down app — she wants substance
How Aluvi helps:
Aluvi validates her existing routine, flags any real conflicts, and gives her a structured schedule (which actives on which days). She gets clarity and confidence — not a lecture.
Persona 03 — James, 26 · "The Practical Minimalist"
- Location: Austin
- Occupation: Software engineer
- Skin type: Oily, occasional breakouts
- Tags: Complete beginner · Wants minimal steps · Efficiency-driven
Background:
James has never had a real skincare routine. He picked up a CeraVe cleanser and a moisturizer after a breakout last year, but he's not sure if he's using them correctly or if he needs anything else. He doesn't follow skincare content — he just wants to know what to do in the least number of steps.
Goals:
- A simple 3-step routine he can stick to every day
- Know if he actually needs sunscreen (he doesn't think he does)
- Not have to think about skincare more than 5 minutes a day
Frustrations:
- Everything online feels either too basic ("just wash your face") or too complex (10-step routines)
- Doesn't want to spend a lot of money on something he's not sure about
- Skeptical of beauty apps that feel too "girly" or overly aesthetic
How Aluvi helps:
Aluvi builds him the simplest possible routine from what he already owns, explains why each step matters in plain language, and gently educates him on sunscreen. No overwhelm. No judgment.
Section 01 — Brand Alignment Summary
| Dimension | Definition |
|---|---|
| Brand positioning | "The anti-overwhelm skincare app" |
| Core promise | Aluvi turns skincare into a simple daily habit that fits you, your skin, and your goals |
| Tone of voice | Friendly · Supportive · Clear · Empowering — "speak like a smart friend" |
| Design principles | One action per screen · Reduce decision fatigue · Fast comprehension (<3s) · Encourage consistency |
| Core values | Simple · Personal · Calm · Trustworthy |
| What we are NOT | An AI dermatologist · A medical advice platform · A product upsell engine · A Reddit replacement |
Microcopy rules (from brand guideline)
- Speak like a helpful friend
- Focus on benefits, not features
- Be specific and actionable
- Avoid jargon and complex words
- Always be supportive and positive
End of Section 01. Next: Section 02 — Goals, Success Metrics & Out of Scope.
Section 02 — Goals & Success Metrics
Product goals for MVP v1.0
Three goals, in priority order:
Goal 1 — Validate product-market fit Prove that users will complete the onboarding quiz, receive a routine, and find it useful enough to return. This is the core hypothesis Aluvi is testing with MVP.
Goal 2 — Establish the habit loop Get users to open the app and check their routine at least 3 times in the first 7 days. A skincare app only works if it becomes part of daily behavior.
Goal 3 — Generate early revenue signal Validate willingness to pay via freemium conversion and affiliate click-through, before committing to full feature build.
Success metrics
Primary metrics (go/no-go for v1.1 investment)
| Metric | Definition | MVP Target | Timeframe |
|---|---|---|---|
| Onboarding completion rate | % of users who complete the full quiz and receive a routine | ≥ 65% | Day 7 |
| Day 7 retention | % of users who open the app at least once on day 7 | ≥ 30% | Day 7 |
| Routine satisfaction score | In-app prompt: "Is this routine right for you?" (Yes/No) | ≥ 70% Yes | Day 1 |
| Free trial → paid conversion | % of trial users who do not cancel before day 7 (auto-convert to paid) | ≥ 25% | Day 7 |
Secondary metrics (directional, inform v1.1 priorities)
| Metric | Definition | Target |
|---|---|---|
| Affiliate click-through rate | % of users who tap a product recommendation link | ≥ 15% |
| Routine save rate | % of users who save their routine (free tier) | ≥ 50% |
| Ingredient conflict alert engagement | % of users who tap to learn more on a conflict alert | ≥ 40% |
| Average session length | Time spent per session | ≥ 2 min |
| Day 30 retention | % of users still active on day 30 | ≥ 15% |
North star metric
Routines completed per active user per week. This captures whether Aluvi is actually changing behavior — not just whether people downloaded the app.
Launch criteria (definition of "ready to ship")
All of the following must be true before MVP v1.0 goes to App Store submission:
- All Must Have features pass QA on iPhone 14 and iPhone 16 (minimum device targets)
- Onboarding quiz completes end-to-end without crash on iOS 16+
- AI routine generation returns result in ≤ 10 seconds on standard WiFi
- Paywall displays correctly and IAP (In-App Purchase) flow completes successfully
- Affiliate links open correctly in Safari / in-app browser
- App Store listing approved (screenshots, description, privacy policy)
- Analytics events firing correctly for all primary metric tracking
- Crash-free rate ≥ 99% on TestFlight with ≥ 50 internal testers
Section 02 — Scope
In scope — MVP v1.0
| Feature | Description | Priority |
|---|---|---|
| Sign in with Apple | Authentication. Apple only. No email/password, no Google. | Must Have |
| Onboarding quiz | 5–7 questions: skin type, concerns, budget, products owned | Must Have |
| AI routine generator | Personalized AM & PM routine based on quiz input | Must Have |
| Product recommendations | Recommended products + affiliate links (Sephora, Amazon) | Must Have |
| Ingredient conflict alert | Warning when user's products contain conflicting actives | Must Have |
| Save routine | User can save and revisit their routine | Must Have |
| Share routine | User can share routine as image or link | Must Have |
| Hard paywall / free trial | Shown after first routine is generated. 7-day full-feature free trial → auto-converts to paid. Weekly / Monthly / Annual pricing. Founding member tier. | Must Have |
| Progress tracking (basic) | Simple streak / completion tracker | Must Have |
Out of scope — MVP v1.0
| Feature | Reason | Target version |
|---|---|---|
| Android app | iOS-first. Android after PMF validation. | v2.0 |
| EU / international markets | US market only for MVP. | v2.0 |
| Skin photo analysis / camera | Adds ML complexity, not core to MVP hypothesis. | v1.1 |
| Product barcode scanning | Text input sufficient for MVP. | v1.1 |
| Social / community features | Out of brand scope. Aluvi is personal, not social. | v2.0+ |
| Push notifications | Deprioritized for MVP build speed. | v1.1 |
| Brand partnership / sponsored placements | Requires user base first. | Post-PMF |
| Routine history & trend analysis | Requires longitudinal data. | v1.1 |
| Dermatologist referral flow | Outside Aluvi's cosmetic-only positioning. | Never |
Subscription model
No free tier. User downloads the app and immediately enters a 7-day free trial with full feature access. On day 7, subscription auto-starts unless cancelled.
Pricing options presented at paywall:
Three subscription tiers. Final pricing TBD — pending ad campaign CPL and conversion data.
| Plan | Price | Notes |
|---|---|---|
| Weekly | TBD | Highest price per unit, targets impulse converters |
| Monthly | TBD | Standard tier |
| Annual | TBD | Best value. Highlighted as recommended. |
| Founding Members | TBD (discounted) | Special rate for users who sign up before app launch. One-time offer, shown on pre-launch waitlist / landing page. Locks in discounted rate for life or for a defined period. |
Pricing will be finalized after ad campaign data (current CPL and conversion signals from Meta campaign) is reviewed. Founding member pricing should be set before app launch announcement.
All features are available to all subscribers (no feature tiering):
| Feature | Trial (7 days) | Paid subscriber |
|---|---|---|
| Onboarding quiz | ✅ | ✅ |
| AI routine (AM + PM) | ✅ | ✅ |
| Full product recommendations + affiliate links | ✅ | ✅ |
| Ingredient conflict alert + full explanation | ✅ | ✅ |
| Ingredient explanations | ✅ | ✅ |
| Save & share routine | ✅ | ✅ |
| Routine refresh (re-run anytime) | ✅ | ✅ |
| Progress tracking + history | ✅ | ✅ |
| Routine analysis | ✅ | ✅ |
The paywall is shown at first launch, before onboarding. User selects a plan (or starts free trial) before using the app. This is a hard paywall — there is no persistent free tier.
Section 02 — Assumptions & Risks
Key assumptions
- Users are willing to manually input the products they own (no barcode scan in MVP).
- Sign in with Apple / Google is sufficient — no email/password needed.
- AI routine generation (via Anthropic API) returns results in ≤ 10 seconds under normal conditions.
- US users are familiar enough with Sephora and Amazon affiliate links to convert.
- A hard paywall with 7-day free trial will not significantly suppress install-to-onboarding completion, as the trial provides full access with no upfront charge.
Risks
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Users drop off during quiz (too long) | Medium | High | Cap quiz at 7 questions. Test 5 vs 7 variants post-launch. |
| AI routine feels generic | Medium | High | Invest in prompt quality. Add "does this feel right?" on Day 1. |
| Trial cancellation rate too high | Medium | High | Ensure trial delivers clear value by day 3. Consider a day-6 cancel reminder with annual plan discount. |
| App Store rejection (health claims) | Low | High | All copy is cosmetic-only. No medical claims. Disclaimer in place. |
| Affiliate CTR too low | Medium | Medium | Track carefully. If <10%, revisit product rec UI before v1.1. |
End of Section 02. Next: Section 03 — Feature Specifications & User Stories.
Section 03 — Feature Specifications & User Stories
How to read this section
Each feature is written as a user story in the format:
"As a [user], I want to [action], so that [outcome]."
Each story includes acceptance criteria — the specific conditions that must be true for the feature to be considered done. These are the dev handoff checkpoints.
Feature 01 — Authentication (Sign in with Apple)
User story:
As a new user, I want to sign in with Apple so that I can create an account quickly without a password.
Acceptance criteria:
- Sign in with Apple is the only authentication option
- No email/password, no Google sign-in
- On successful auth (first launch), user is directed to onboarding quiz
- On successful auth (returning user), user is directed to home screen
- User's name from Apple is used to personalize the greeting ("Good morning, Sarah")
- Auth token is stored securely in iOS Keychain
- If sign-in fails, a clear error message is shown: "Something went wrong. Please try again."
- Returning users are auto-signed in on app reopen (no re-auth required unless token expires)
Feature 02 — Paywall & Free Trial
User story:
As a new user who has just seen my personalized routine, I want to unlock full access so that I can keep using Aluvi beyond the trial.
Acceptance criteria:
- Paywall screen is shown after the user receives their first routine result — not before onboarding
- User flow: Sign in → Onboarding quiz → AI generation → Routine result (preview) → Paywall → Full access
- The routine result screen shows enough to demonstrate value (e.g. AM routine step 1–2 visible), then paywall appears to unlock the full routine
- Screen clearly communicates: "7 days free, then [price]. Cancel anytime."
- Three subscription options are displayed: Weekly, Monthly, Annual
- Annual plan is visually highlighted as "Best value"
- Founding member pricing is shown if user is in the pre-launch cohort (flag set server-side)
- "Start free trial" CTA is the primary action — one tap to begin
- Tapping any plan shows the native iOS subscription confirmation sheet (StoreKit)
- Trial start date and auto-renewal date are shown before confirmation
- On trial start, user is returned to their full routine result immediately
- If user dismisses paywall without subscribing, app closes (hard paywall — no bypass)
- Subscription state is validated on every app launch via StoreKit
- Expired or cancelled subscriptions redirect to paywall on next open
StoreKit notes for dev:
- Use StoreKit 2 (iOS 15+)
- Product IDs to be configured in App Store Connect before build:
com.aluvi.weekly,com.aluvi.monthly,com.aluvi.annual,com.aluvi.founding - Handle
Transaction.currentEntitlementsto validate active subscription on launch - Restore purchases button must be accessible (App Store guideline requirement)
Feature 03 — Onboarding Quiz
User story:
As a new user, I want to answer a few quick questions about my skin and scan the products I already own, so that Aluvi can build a routine that's actually right for me.
Quiz structure (7 questions):
| Step | Question | Input type | Options |
|---|---|---|---|
| Q1 | What's your skin type? | Single select | Dry · Oily · Combination · Normal · Sensitive |
| Q2 | What are your main skin concerns? | Multi-select (max 3) | Acne · Dark spots · Anti-aging · Dryness · Oiliness · Redness · Uneven texture · Brightening |
| Q3 | How would you describe your skin sensitivity? | Single select | Not sensitive · Mildly sensitive · Very sensitive |
| Q4 | What's your skincare budget per month? | Single select | Under $20 · $20–$50 · $50–$100 · $100+ |
| Q5 | Do you currently use sunscreen daily? | Single select | Yes, every day · Sometimes · No, not really |
| Q6 | What products do you already own? | Barcode scan (primary) + free text fallback | See product input spec below |
| Q7 | What's your #1 skin goal right now? | Single select | Clear skin · Even tone · Anti-aging · Hydration · Simpler routine |
Q6 — Product input spec (barcode scan + fallback)
This is the most technically complex question in the quiz. It uses a dual-input approach.
Primary flow — barcode scan:
- User taps "Scan a product" → camera opens (AVFoundation / native iOS camera)
- User points camera at product barcode
- App sends barcode to Open Beauty Facts API:
GET https://world.openbeautyfacts.org/api/v2/product/{barcode}.json - If product found → product name + brand appears as a chip: "CeraVe Moisturizing Cream ✓"
- User can scan another product (loop until done)
- User taps "Done scanning" to proceed
Fallback flow — free text:
- If camera permission denied → show text input only, no scan option
- If product barcode not found in Open Beauty Facts → show message: "We couldn't find that product. Type the name instead." → free text field appears
- Free text input also always available alongside scan (user can mix both)
Product data handling:
- If barcode matched in Open Beauty Facts → store:
{ name, brand, barcode, ingredients[], source: "openbeautyfacts" } - If free text only → store:
{ name, source: "user_input" }— AI will infer ingredient profile from product name - If product name is unrecognizable (e.g. gibberish or clearly fake) → AI skips that product when generating routine. A notice is shown on Screen 11 (Routine Result) listing the skipped products — see Screen 11 spec for display details
- Maximum 10 products per quiz (UX limit — more than 10 is overwhelming)
Open Beauty Facts integration notes for dev:
- SDK: use official Swift SDK —
openfoodfacts/openfoodfacts-swifton GitHub - Required HTTP header on all API calls:
User-Agent: Aluvi/1.0 (iOS; contact@aluviapp.com) - Terms: 1 API call = 1 real user scan. No batch scraping. License: ODbL (attribution required in app's data/legal page)
- API is free, no rate limit for this use case
- Handle 404 (product not found) and timeout (>5s) gracefully with fallback to free text
Acceptance criteria:
- Each question occupies its own screen (one question per screen)
- Progress indicator visible at top (e.g. "3 of 7")
- User can go back to previous question without losing answers
- Q6: camera opens on tap of "Scan a product" button
- Q6: barcode detected within 2 seconds of pointing at product under normal lighting
- Q6: successful scan shows product name as a chip with green checkmark
- Q6: user can scan multiple products sequentially without leaving the screen
- Q6: user can manually remove a scanned product (tap × on chip)
- Q6: free text input is always available as alternative or supplement to scan
- Q6: unrecognized barcodes fall back to free text gracefully — no crash, no blocking error
- Q6: camera permission prompt uses clear copy: "Aluvi needs camera access to scan your products"
- Q6: if camera permission denied, scan button is hidden and only text input is shown
- All 7 questions must be answered before proceeding (Q6 requires at least 1 product)
- Answers are saved locally and sent to AI generation endpoint on quiz completion
- If user force-quits mid-quiz, progress is saved and quiz resumes from last answered question
- Quiz completion triggers transition to AI loading screen
Feature 04 — AI Routine Generator
User story:
As a user who has completed the quiz, I want to receive a personalized AM and PM routine so that I know exactly what to use and in what order every day.
How it works: Quiz answers are sent to the Anthropic API. The prompt instructs Claude to generate a structured AM/PM routine based on the user's skin type, concerns, products owned, budget, and goals. The response is parsed into a structured routine object and displayed on the routine screen.
Acceptance criteria:
- AI generation begins immediately after quiz completion
- Loading screen is shown during generation with reassuring microcopy (e.g. "Analyzing your skin data…")
- Generation completes in ≤ 10 seconds on standard WiFi. If > 10 seconds, a secondary message appears: "Almost there…"
- If generation fails (API error / timeout), user sees an error screen with a "Try again" button — quiz answers are preserved
- Routine output includes: product name, step number, brief usage instruction (1–2 sentences), and AM/PM designation
- Products the user already owns are prioritized in the routine
- If a product the user owns creates an ingredient conflict, it is flagged (see Feature 06)
- Recommended new products (with affiliate links) are shown separately below the routine — not mixed into the core routine steps
- Routine is structured as: AM routine (ordered list) + PM routine (ordered list)
- Each step shows: step number, product name, product type (e.g. "Cleanser"), brief instruction
- Routine is automatically saved to the user's account on generation
AI prompt requirements (for backend / prompt engineering):
- Output must be structured JSON parseable by the iOS client
- Output schema:
{
"personalized_intro": "string",
"am": [{ "step": "", "product": "", "type": "", "instruction": "" }],
"pm": [{ "step": "", "product": "", "type": "", "instruction": "" }],
"conflicts": [{ "product_a": "", "product_b": "", "reason": "", "fix": "" }],
"recommendations": [{ "product": "", "reason": "", "affiliate_url": "" }]
}
- Prompt must enforce: cosmetic-only recommendations, no medical claims, no diagnosis language
- Routine should default to simplicity — 4–5 steps per session unless user's product list justifies more
Personalized intro block
personalized_intro is a 2–3 sentence block written based on the combination of the user's Q2 (skin concerns), Q3 (sensitivity), and Q7 (primary goal) answers. This block appears on the routine result screen before the paywall, beneath the main headline.
Prompt instructions for personalized_intro
- Write in second person ("your skin", "you") — not like a brand, but like a knowledgeable friend who understands the user's situation
- Never mention age, never use medical language, never use fear or scare tactics
- Must reflect one specific insight about the user's concern + goal combination — so it feels like Aluvi genuinely understands their situation, not a generic template
- Close with a sentence that connects back to the routine that was just built — reinforcing that this routine was made specifically for them
- Maximum 60 words
- Tone: warm, grounded, quietly reassuring — not hypey, not judgmental
Example outputs per concern combination
Anti-aging + sensitive skin + goal: anti-aging
"Skin that's starting to change in texture and elasticity needs a different approach — not more products, but the right ones in the right order. A lot of people over-layer at this stage and end up with skin that's more reactive, not better. This routine is designed to be simple but targeted, built around exactly what your skin needs right now."
Acne + not sensitive + goal: clear skin
"Your skin actually has more capacity to recover than you might think. The problem is almost never the products themselves — it's the order they're used in, and when. This routine fixes that, so nothing you already own is working against you."
Dryness + very sensitive + goal: hydration
"Skin that stays dry even with moisturizer almost always has one root cause: products applied in the wrong order, so the active ingredients never fully absorb. This routine corrects that sequence — and accounts for how easily your skin reacts."
Oiliness + not sensitive + goal: clear skin
"Oily skin that keeps breaking out despite a full routine is often actually under-hydrated, not over-producing oil. This routine is built to rebalance that — not just suppress sebum."
Multiple concerns + very sensitive + goal: simpler routine
"With skin that reacts easily, less is almost always more. This routine removes the steps that aren't earning their place and keeps only what genuinely works for your skin — no unnecessary experimentation."
Feature 05 — Routine Screen (Home)
User story:
As a returning user, I want to see my routine clearly on the home screen so that I know exactly what to do this morning or tonight.
Acceptance criteria:
- Home screen shows today's AM or PM routine depending on time of day (AM default before 12pm, PM after)
- User can toggle between AM and PM manually
- Each step is shown as a tappable list item with product name, type, and instruction
- Tapping a step expands it to show full usage details and ingredient notes (premium feature)
- Each step has a "Mark as done" checkbox — completing all steps triggers a positive feedback moment (animation + message)
- Progress bar shows how many steps are completed today
- Header shows personalized greeting: "Good morning, [name]" with current streak
- "Edit routine" or "Refresh routine" CTA is accessible from this screen
- Bottom navigation: Home · Routine · Progress · Profile
Feature 06 — Ingredient Conflict Notice
User story:
As a user with potentially conflicting active ingredients, I want to know that Aluvi has spotted the issue and already sorted it out, so I can use my products safely without having to figure it out myself.
How it works:
- Conflict detection runs automatically as part of AI routine generation
- If a conflict is detected, AI incorporates a safe alternating schedule directly into the routine — the fix is baked into the routine steps, not a separate action required from the user
- A one-time informational notice is shown on Screen 11 (Routine result preview) after generation, reassuring the user that the conflict has been handled
- The notice is not a warning — it is a trust signal: "We spotted something and already built your schedule around it"
- No persistent alert, no badge, no separate action required from user
- If no conflict is detected, nothing is shown — silence is the signal
Acceptance criteria:
- Conflict detection runs as part of AI routine generation
- If conflict detected, AI adjusts the routine schedule to safely alternate conflicting products — this is reflected in the step instructions
- A one-time informational notice is shown on Screen 11 if a conflict was detected and handled — see Screen 11 spec for display details
- Notice is shown once only — not persistent, not shown again after user continues to Screen 13
- No conflict badge on bottom nav, no persistent banner on Screen 13
- No conflict = nothing shown. Do not show "no conflicts found" message
- Conflict data is included in the AI JSON output and rendered client-side
- Screen 14 remains accessible from Screen 11 notice as an optional detail view — not a required step
Feature 07 — Product Recommendations
User story:
As a user whose current products have gaps, I want to see what to add to my routine so that I can complete it without spending more than my budget.
How it works — curated catalog approach:
Recommendations are not generated ad-hoc from the web. They are pulled from a pre-built internal catalog of 200–300 curated US skincare products. Claude selects the best matches from this catalog based on the user's skin type, concerns, budget, and routine gaps.
Catalog build process (pre-launch, one-time):
- Use Claude to define top 200–300 skincare products by category (cleanser, moisturizer, serum, SPF, toner, retinol, AHA/BHA, eye cream) — prioritize products popular in US market
- Use Openclaw to scrape product details + direct URLs from Sephora and Amazon
- Claude structures output into JSON catalog per product using agreed schema
- Cross-reference with Open Beauty Facts for ingredient enrichment where available
- Store in Supabase/Postgres as the recommendation database
- Update catalog quarterly (or when major products launch/discontinue)
Catalog testing findings (April 24, 2026): Initial scrape of 36 products completed using Openclaw. Key findings:
- Sephora data quality is strong —
skin_type_fit,concerns,ingredients, andsephora_urlall populated correctly - Amazon data is sparse —
skin_type_fit,concerns, andingredientsall empty due to generic listing format - Amazon product names are too long (raw listing titles) — need cleaning before use in UI
notesfield is auto-generated and generic — needs rewrite per product before launch- AHA/BHA category has 0 products — critical gap, must be filled before launch
Required fixes before launch:
- Enrich Amazon products — use Claude to fill
skin_type_fit,concerns, and cleannamefor all 16 Amazon products - Rewrite
notesfield for all 36 products using Claude — 1 natural sentence per product - Add AHA/BHA category — minimum 5–6 products (e.g. The Ordinary AHA 30%, Paula's Choice BHA 2%)
- Add moisturizer products — currently only 3, target 8–10
- Add serum products — currently only 3, target 8–10
- Fill
affiliate_tagfor all products after Amazon Associates + Sephora affiliate accounts are approved
Catalog schema per product:
{
id, name, brand, category,
skin_type_fit: [], // e.g. ["oily", "combination"]
concerns: [], // e.g. ["acne", "brightening"]
price_usd: number,
price_tier: "budget" | "mid" | "premium",
sephora_url: string, // direct product page
amazon_url: string, // direct product page
affiliate_tag: string,
ingredients: [], // from Open Beauty Facts if available
notes: string // 1-sentence "why this works" — written manually or AI-generated
}
Recommendation logic:
- Claude receives user's skin profile + current products + quiz answers
- Claude queries catalog (passed as context) and selects 2–3 products that fill routine gaps
- Budget filter: only recommend products within user's stated price tier (Q4)
- Exclude products the user already owns (matched by name or barcode)
- Prioritize products with both Sephora and Amazon URLs for flexibility
Acceptance criteria:
- Recommendations section is labelled "You might also need" — shown below routine result
- Maximum 3 recommendations shown (avoid overwhelming)
- Each recommendation shows: product image (from catalog), name, brand, 1-sentence reason, price, and CTA button ("View on Sephora" or "View on Amazon")
- Recommendations respect user's budget tier from Q4
- Products the user already scanned/entered are never recommended
- Affiliate links are direct product page URLs (not search pages)
- Links open in SFSafariViewController (in-app browser)
- Affiliate link taps are tracked as analytics events:
recommendation_tapped { product_id, source } - If routine is complete with no gaps, recommendations section is NOT hidden — instead show a positive completion state: "You're all set. Your current products are everything you need for this routine." No CTA, no upsell, no product shown.
- Tone of recommendations must feel like a friend suggesting, not a store pushing. Copy: "You might also like..." not "Complete your routine with..." or "Upgrade your routine."
- Never show more than 3 recommendations regardless of how many gaps exist
- Recommendations section label: "One thing that might help" (singular framing feels less pushy than a list)
- No urgency language anywhere in this section — no "limited", "popular", "trending", "best seller" labels
- Catalog must contain minimum 50 products at launch across all major categories
Feature 08 — Save & Share Routine
User story:
As a user who loves my routine, I want to save it and share it so that I can reference it anytime and show friends.
Acceptance criteria:
- Routine is auto-saved to the user's account on generation (no manual save required)
- User can access saved routine from the Routine tab at any time
- Share button generates a clean image card of the routine (AM + PM steps, Aluvi branding)
- Share sheet uses native iOS UIActivityViewController
- Shared image includes Aluvi logo and "aluviapp.com" as attribution
- Share does not expose personal quiz answers — only the routine steps
Feature 09 — Progress Tracking
User story:
As a consistent user, I want to track my daily routine completion so that I can see my streak and stay motivated.
Acceptance criteria:
- Each day a user completes all steps in AM or PM routine, a completion is logged
- Current streak is shown on home screen header
- Progress screen shows: current streak, weekly completion chart (7-day bar), total days completed
- Completing a full routine (all steps checked) triggers a positive feedback animation + message
- Streak resets if user misses a full day (no completion logged)
- Data is stored in user's account (not local only) so it persists across device changes
Feature 10 — Add Product to Routine
User story:
As a returning user who bought a new product, I want to add it to my routine without retaking the full quiz, so that Aluvi can update my routine to include it.
How it works:
- Accessible from Screen 13 (Full routine result) via an "Edit products" CTA
- User scans barcode or enters product name manually — same dual-input flow as Q6 in the onboarding quiz
- After adding, user taps "Update routine" CTA to trigger re-generation
- AI receives: existing quiz answers (stored) + existing product list + newly added product(s)
- Routine is re-generated in full — same AI generation flow as initial quiz
- Loading screen (Screen 10) is shown during re-generation
- Updated routine replaces the previous routine on completion
Entry point: Screen 13 (Full routine result) → "Edit products" CTA
Exit points:
- "Update routine" tapped → AI loading screen → Updated routine result (Screen 13)
- Cancelled → back to Screen 13, no changes
Key UI elements:
- "Edit products" CTA — accessible from Screen 13, positioned below the routine steps list
- Product input sheet (bottom sheet modal): same barcode scan + free text fallback as Q6
- Added product appears as chip in the sheet — user can add multiple before confirming
- "Update routine" primary CTA — triggers re-generation
- "Cancel" link — dismisses sheet, no changes
States:
- Default: empty input, "Update routine" CTA disabled
- Product added: chip(s) visible, "Update routine" CTA enabled
- Loading: AI re-generation in progress (Screen 10)
- Success: updated routine shown on Screen 13
Notes:
- Quiz answers (Q1–Q5, Q7) are never re-asked — they are stored and reused as-is
- Existing product list is preserved; new products are appended and removed products are excluded
- If the new product is unrecognized by AI → same behavior as initial quiz: skipped silently, notice shown on result screen
- Re-generation uses identical AI prompt as initial routine generation — no special handling needed
- "Update routine" tap is the only trigger for re-generation — no auto-update on product add
- Streak is preserved after routine re-generation — editing products is not a break in habit. Streak only resets if user misses a full day with no routine completion logged.
Acceptance criteria:
- "Edit products" button (
+ Edit products) is visible on Screen 13 (Full routine result) for active subscribers, inline below the routine steps list - Tapping "Edit products" opens Screen 17 bottom sheet
- Bottom sheet pre-loads all existing products (from Q6) as removable chips on open
- User can remove existing product chips — removed products are excluded from re-generation
- "Update routine" CTA is enabled by default (existing products present); disabled only if all chips are removed
- Bottom sheet camera uses same Open Beauty Facts barcode scan flow as Q6
- User can add multiple new products before tapping "Update routine"
- New product chips appear alongside existing chips — no visual distinction
- Tapping "Update routine" triggers AI loading screen (Screen 10)
- AI receives the final chip list as the complete product list
- Updated routine replaces previous routine on completion
- If user cancels without updating, existing routine and product list are unchanged
- Analytics event fired on update:
routine_updated { user_id, products_added: n, products_removed: n }
End of Section 03. Next: Section 04 — UX Flows & Screen Structure.
Section 04 — UX Flows & Screen Structure
How to read this section
Each screen is documented with:
- Purpose — what this screen exists to do (one job only)
- Entry point — what triggers navigation to this screen
- Exit points — where the user can go from this screen
- Key UI elements — components that must be present
- States — all possible states the screen can be in
- Notes — UX decisions and rationale
Master user flow
App launch
└── Returning user (has active subscription)
└── Home screen
└── New user / logged out
└── Welcome screen
└── Sign in with Apple
└── [First time] Onboarding quiz
└── Q1 → Q2 → Q3 → Q4 → Q5 → Q6 (scan) → Q7
└── AI loading screen
└── Routine result (preview)
└── Paywall
└── [Subscribed] Full routine result
└── Home screen
└── [Dismissed] App closes
└── [Returning, active sub] Home screen
└── [Returning, expired sub] Paywall
Screen 01 — Splash / App launch
Purpose: Brand moment. Check auth + subscription state. Route user to correct destination.
Entry point: App opens
Exit points:
- Active subscriber → Home screen (auto, no interaction)
- New / logged out → Welcome screen (auto)
- Expired subscription → Paywall
Key UI elements:
- Aluvi logo centered
- Warm White background (#FAFAF8)
- No buttons, no text other than logo
States:
- Default: logo visible, checking auth in background
- Duration: max 2 seconds before routing
Notes:
- No loading spinner — keep it clean
- Auth check and subscription validation happen silently here
Screen 02 — Welcome screen
Purpose: First impression. One job: get user to sign in.
Entry point: New user or logged-out user after splash
Exit points:
- Sign in with Apple → success → Onboarding quiz (new) or Home (returning)
Key UI elements:
- Aluvi logo + wordmark
- Hero headline (H1)
- Supporting subtext (Body 1)
- "Continue with Apple" button (primary, full width)
- Legal footnote: "By continuing, you agree to our Terms and Privacy Policy"
States:
- Default
- Loading (after Apple tap, waiting for auth response)
- Error (auth failed — show inline message, keep button active)
Notes:
- No "Sign up" vs "Log in" distinction — Apple handles both in one flow
- Keep copy minimal — this is not a sales page, the landing page already did that job
Screen 03–09 — Onboarding quiz (Q1–Q7)
Each question is a separate screen. Shared layout across all 7 screens.
Purpose: Collect the data needed to generate a personalized routine.
Entry point: First sign-in (new user only). Never shown again after completion.
Exit points:
- "Next" → next question
- Back chevron → previous question
- Q7 "Done" → AI loading screen
Shared UI elements (all quiz screens):
- Progress bar at top (e.g. step 3 of 7) — Aluvi Green fill
- Back chevron (top left) — except Q1 where back returns to Welcome
- Question text (H1)
- Supporting hint text (Body 2, muted) where needed
- Answer options (tappable cards or chips)
- "Next" CTA button (primary, sticky bottom) — disabled until selection made
- Q7 uses "Build my routine →" instead of "Next"
Per-screen specifics:
Q1 — Skin type
- Input: single select, 5 options as large tappable cards with icon
- Options: Dry · Oily · Combination · Normal · Sensitive
- Hint: "Not sure? Choose Combination if your T-zone gets oily."
Q2 — Skin concerns
- Input: multi-select chips, max 3 selections
- Options: Acne · Dark spots · Anti-aging · Dryness · Oiliness · Redness · Uneven texture · Brightening
- Counter shows: "1 of 3 selected" — turns to "3 of 3 — that's enough!" at max
- Hint: "Pick up to 3. Focus on what bothers you most."
Q3 — Skin sensitivity
- Input: single select, 3 options
- Options: Not sensitive · Mildly sensitive · Very sensitive
- Hint: "Sensitive skin reacts easily to new products or strong actives."
Q4 — Budget
- Input: single select, 4 options
- Options: Under $20 · $20–$50 · $50–$100 · $100+
- Hint: "This helps us recommend products you'll actually buy."
- Note: this is monthly skincare spend, not per-product
Q5 — Sunscreen habit
- Input: single select, 3 options
- Options: Yes, every day · Sometimes · No, not really
- No hint — question is self-explanatory
- Note: answer informs whether SPF is added to AM routine or gently introduced
Q6 — Products owned (barcode scan + text)
- This screen is different from Q1–Q5. See Feature 03 spec for full detail.
- Key UI: camera viewfinder area (top 60% of screen) + scanned product chips below + "Add manually" text link + "Done" CTA
- States:
- Default: camera active, no products scanned yet. CTA disabled.
- Scanning: brief flash/highlight on successful scan
- Product added: chip appears below viewfinder with product name + × to remove
- Not found: inline message below viewfinder: "Product not found — type the name instead"
- Camera denied: viewfinder replaced with text input field
- Min 1 product required to enable "Done" CTA
- Hint at top: "Scan the barcode on each product you own. We'll build your routine around what you already have."
Q7 — Primary skin goal
- Input: single select, 5 options as tappable cards
- Options: Clear skin · Even tone · Anti-aging · Hydration · Simpler routine
- No hint
- CTA: "Build my routine →" (not "Next")
- This is the emotional peak of the quiz — copy and interaction should feel like a commitment
Wireframe — Quiz screens Q1–Q5, Q7 (single/multi-select template, showing Q2):
Wireframe — Q6 (product scan, dual input):
Screen 10 — AI loading screen
Purpose: Manage expectation during AI generation (up to 10 seconds). Maintain excitement, not anxiety.
Entry point: Q7 completed
Exit points:
- Generation complete → Routine result screen (auto)
- Generation failed → Error state with "Try again" button
Key UI elements:
- Centered Aluvi spark icon (animated — gentle pulse)
- Rotating microcopy messages (swap every 2.5s):
- "Analyzing your skin profile…"
- "Checking your products for conflicts…"
- "Building your morning routine…"
- "Putting together your evening routine…"
- "Almost ready…" (shown after 7s if still loading)
- No progress bar — duration is unpredictable, a stuck progress bar causes anxiety
States:
- Loading (default)
- Long load (>7s): swap to "Almost ready…" message
- Error (API fail / timeout >15s): show "Something went wrong. Your answers are saved — tap to try again." with retry button
Notes:
- Never show a blank screen — even on error, keep the calm visual
- Quiz answers must be preserved in local storage before this screen loads
Screen 11 — Routine result (preview + paywall gate)
Purpose: Show enough of the routine to demonstrate clear value, then present paywall.
Entry point: AI loading complete
Exit points:
- "Start free trial" → Paywall → Full routine
- Paywall dismissed → App closes
Key UI elements:
- Personalized headline using first name from Apple sign-in (H1): "[Name], your routine is ready." — e.g. "Sarah, your routine is ready."
- Fallback if Apple returns no name: display "Your routine is ready." — do not show a blank or "[Name]" placeholder
- Dev note: Apple may return empty name if user selects "Hide My Email" or has no name set on Apple ID. Always check for nil/empty before rendering name.
- [NEW] Personalized intro block: output from
personalized_introfield in the AI response — displayed below the subtext, before the AM routine preview. Body text, no card or container. Max 60 words; truncate at last complete sentence within limit. If empty or API error, element is not shown — no placeholder, no error state. - Unrecognized product notice: if AI skipped one or more products during generation, show an inline notice below the personalized intro block (above AM routine preview). Format: "We couldn't identify [product name] — it wasn't included in your routine." One line per skipped product. Muted text style, no icon, no error state — informational only. If no products were skipped, this element is not shown.
- Conflict notice (if conflicts detected) — informational only, not an alert. One-time, shown on this screen only. Reassurance tone: AI has already built a safe schedule. Tappable to open Screen 14 for detail. Not shown on Screen 13 or anywhere else after this.
- Sticky bottom sheet: paywall CTA — "Unlock your full routine — 7 days free"
Element order:
- Personalized headline: "[Name], your routine is ready."
- Subtext: "Built around your products. Personalized for your skin."
- [NEW] Personalized intro block
- [NEW] Unrecognized product notice (if applicable)
- Conflict notice (if applicable) — informational, one-time
- AM routine preview (first 2 steps visible, remaining steps blurred)
- Sticky bottom sheet: paywall CTA
States:
- Default: preview visible, paywall bottom sheet present
- No "skip" or "later" — hard gate
Notes:
- Show real content in the preview (step 1 and 2 of AM routine) — not a mockup
- Conflict notice on this screen is intentional — it signals Aluvi has already done the thinking for the user, increasing trust and conversion
- Do not blur the product names in preview — user should recognize their own products to feel the personalization
Screen 12 — Paywall
Purpose: Convert trial. Present 3 plan options clearly. Remove friction.
Entry point: Routine result preview (first time), or expired subscription
Exit points:
- Plan selected + confirmed → StoreKit sheet → success → Full routine result
- Dismissed (X button or swipe) → App closes (hard paywall)
Key UI elements:
- Brief value recap (2 lines max): "Your personalized AM & PM routine, built around your products."
- 3 plan cards: Weekly · Monthly · Annual
- Annual card visually highlighted: "Best value" badge
- Founding member card: shown only if pre-launch cohort flag is true
- "Start free trial" primary CTA (maps to selected plan)
- Fine print: "7 days free, then [price]. Cancel anytime in Settings."
- Restore purchases link (required by App Store)
States:
- Default: Annual pre-selected
- Plan selected: selected card highlighted in Aluvi Green
- Loading: after tap, show spinner while StoreKit initializes
- Success: brief success animation → route to full routine
- Error: StoreKit error → show "Purchase failed. Please try again." inline
Notes:
- No feature comparison table — keep it simple, not a feature matrix
- Founding member pricing is a separate card, not a toggle
- Annual plan pre-selected by default to anchor perception
Screen 13 — Full routine result
Purpose: Deliver the full value. This is the "wow" moment.
Entry point: Paywall completed (first time) or Home → Routine tab
Exit points:
- Step detail → expand inline (no new screen)
- Product recommendation card → opens Sephora or Amazon in in-app browser (SFSafariViewController)
- Home tab → Home screen
- Share → iOS share sheet
Key UI elements:
- AM / PM toggle (top)
- Recommendations section — always visible directly below the AM/PM toggle, above the routine steps list
- Routine steps as ordered list — each step: number, product name, type, brief instruction
- Conflict notice entry point — if the routine has ingredient conflicts, a subtle tappable row is shown at the bottom of the routine steps list (above the "+ Edit products" button). Format: "Some products in this routine are scheduled to avoid clashes. See details →". Tapping opens Screen 14.
- "+ Edit products" button — inline, below the routine steps list. Icon + label. Secondary style (not primary/filled — should not compete with "Start routine"). Tapping opens Screen 17 (Edit products bottom sheet).
- Share button (top right)
- Sticky bottom CTA: "Start routine" → marks steps as in-progress
Screen 13 content order (top to bottom):
- AM / PM toggle
- Recommendations section
- Routine steps list
- Conflict notice entry point (if applicable)
- "+ Edit products" button (inline, below steps)
- Sticky bottom CTA: "Start routine"
Notes:
- Conflict notice on Screen 13 is a permanent, low-key entry point — not a warning, just an informational link for users who want to understand their schedule
- Replaces the old note that Screen 14 was only accessible from Screen 11
States:
- AM view (default before 12pm)
- PM view (default after 12pm)
- Step expanded: tapping a step shows full usage instruction inline
- Step completed: checkbox ticked, step grays out with strikethrough
- All steps done: celebration moment — green checkmark animation + "Great job! Routine complete."
Recommendations section — display conditions:
Recommendations are always visible on this screen, directly below the AM/PM toggle and above the routine steps. They are not triggered by step completion — they are the first content-level element the user sees after the toggle. This maximises affiliate exposure while the user is most engaged. Display logic is determined by routine gaps detected during AI generation:
| Condition | Display |
|---|---|
| Routine has gaps (missing product category for user's skin profile) | Show up to 3 product cards with "One thing that might help" label |
| Routine is complete (user's existing products cover all needs) | Show "You're all set" state — no product cards, no CTA |
This means:
- Recommendations are visible from the first time the user opens their routine, not after completing steps
- The section is always present (never hidden) — it either shows product cards or the completion state
- Max 3 product cards regardless of how many gaps exist
- Products always respect user's budget tier (Q4 answer)
- Products the user already owns are never shown
Screen 14 — Ingredient conflict detail
Purpose: Let users understand the conflict Aluvi detected and how the routine already handles it. Informational only — no action required.
Entry point:
- Tap on conflict notice on Screen 11 (Routine result preview — first time)
- Tap on conflict notice entry point on Screen 13 (Full routine — permanent access post-subscribe)
Exit points:
- Back → Screen 11 or Screen 13 (depending on entry)
- "Got it" → Screen 11 or Screen 13 (depending on entry)
Key UI elements:
- Conflict summary: "[Product A] + [Product B]"
- Plain-language explanation (2–3 sentences max) — what the potential conflict is and why it matters
- "Here's what we did" section — shows the safe alternating schedule AI already built into the routine (e.g. "Retinol on Mon · Wed · Fri, AHA on Tue · Thu")
- "Got it" CTA (primary)
Notes:
- No severity badge — framing is not about danger level, it's about the solution
- Tone: smart friend who already sorted it out, explaining what they did and why
- No action required from user — the schedule is already in the routine
Screen 15 — Progress screen
Purpose: Show consistency and motivate the habit loop.
Entry point: Bottom nav → Progress tab
Exit points:
- Back to any tab via bottom nav
Key UI elements:
- Current streak (large, prominent)
- 7-day completion chart (bar chart, Aluvi Green)
- Total days completed (since account creation)
- Motivational microcopy tied to streak (see copywriting section)
- Skin improvement indicators (if 14+ days data available): Oil control · Pores · Brightness · Acne — each showing "Improving / Stable"
States:
- Empty (day 1, no data): "Start your first routine today. Your progress will show here."
- Active (has streak): full view
- Streak broken: gentle message — "You missed a day — no worries. Start fresh today."
Screen 16 — Profile / Settings
Purpose: Account management. Minimal — not a feature dump.
Entry point: Bottom nav → Profile tab
Key UI elements:
- User avatar (tappable) + user name — avatar tap opens photo picker sheet (see below)
- Subscription status + renewal date
- "Manage subscription" → opens iOS subscription management (external)
- "Retake quiz" → restarts onboarding, generates new routine
- "Restore purchases" (required)
- App version
- Links: Privacy Policy · Terms of Use · Data sources (Open Beauty Facts attribution — required by ODbL license)
Avatar / photo profile sheet: Tapping the avatar opens a bottom sheet modal with two options:
- "Take photo" → opens native iOS camera (UIImagePickerController, camera source)
- "Choose from library" → opens native iOS photo library (UIImagePickerController, photo library source)
- "Cancel" link — dismisses sheet Photo is cropped to a circle on selection (1:1 ratio, center crop). Stored in Supabase storage per user account. Replaces the Apple ID avatar on the profile screen only — does not affect Apple ID.
States:
- Active subscriber: shows plan name + next renewal date
- Trial: shows "Trial ends [date]"
- Expired: shows "Subscription ended" + "Renew" CTA → Paywall
- Avatar not set: shows initials from Apple ID name as placeholder (e.g. "A" for Ardho)
Bottom navigation structure
Present on all post-onboarding screens. (Screens 13–16)
| Tab | Icon | Destination |
|---|---|---|
| Home | Home icon | Today's routine overview + streak |
| Routine | List icon | Full AM/PM routine detail |
| Progress | Chart icon | Streak + completion history |
| Profile | Person icon | Account + settings |
Notes:
- 4 tabs maximum — consistent with brand principle of reducing decision fatigue
- Active tab uses Aluvi Green
Screen 17 — Edit products (bottom sheet)
Purpose: Let returning users add new products to their existing routine without retaking the full quiz.
Entry point: Screen 13 (Full routine result) → "Edit products" CTA
Exit points:
- "Update routine" tapped → AI loading screen (Screen 10) → updated Screen 13
- "Cancel" or swipe to dismiss → Screen 13, no changes
Key UI elements:
- Bottom sheet modal (not a full screen)
- Camera viewfinder (top portion of sheet) for barcode scan — same as Q6
- Existing product chips — all products from the user's quiz (Q6) are pre-loaded as chips below the viewfinder, each with × to remove. These are editable — user can remove an existing product from here, and it will be excluded from the re-generated routine
- New scanned/typed products also appear as chips in the same area, visually identical to existing chips
- "Add manually" text link — opens text field inline
- "Update routine" primary CTA — enabled by default (existing products already present); disabled only if all chips are removed
- "Cancel" link (top left of sheet)
States:
- Default: camera active, all existing products shown as chips, "Update routine" enabled
- Product added: new chip appears alongside existing chips
- Product removed: chip disappears; if all chips removed, "Update routine" disabled with hint "Add at least one product"
- Not found: inline message "Product not found — type the name instead"
- Camera denied: viewfinder replaced with text input only
Notes:
- Sheet dismisses on "Cancel" or background tap — no changes saved
- After "Update routine" is tapped, sheet dismisses and Screen 10 (loading) is shown
- AI receives the final chip list as the complete product list — existing chips that were removed are excluded from re-generation
- Same barcode + free text logic as Q6 — no new dev work beyond reusing the component
- No visual distinction between existing and new product chips — they are treated equally
Screen 18 — Home
Purpose: Single entry point for daily routine execution. User opens the app, knows exactly what to do right now, and starts. One job only.
Entry point:
- App launch (returning user with active subscription)
- Bottom nav → Home tab
- After completing paywall (first time)
Exit points:
- "Start routine" / "Continue routine" CTA → Screen 13 (Full routine result)
- Tapping weekly calendar strip → Screen 15 (Progress)
- Bottom nav → Routine · Progress · Profile tabs
Key UI elements:
Greeting header— time-based personal greeting (H1)
Before 12pm: "Good morning, [Name]"
- After 12pm: "Good evening, [Name]"
- Fallback (no name): "Good morning" / "Good evening"
UV Index badge — displayed inline to the right of the greeting. Format: "UV [n] · wear SPF" — amber tone. Only shown when location permission is granted and UV data is available. If UV is 0–2 (low), badge is hidden. If location unavailable, badge is hidden — no error state shown. Tapping does nothing (informational only).
Weekly calendar strip — 7-day horizontal strip showing M–S with completion status per day. Replaces streak badge. Each day shows: day letter, date number, and a filled green circle (done), outlined green circle (today, not yet done), or muted circle (missed/future). Tapping the strip navigates to Screen 15 (Progress). Shown below the greeting row.
AM/PM toggle — manual toggle to switch between Morning and Evening routine view. Auto-defaults to AM before 12pm, PM after.
Today's routine card— prominent card, auto-switched by time of day. Contains:
Routine label: "Morning routine" / "Evening routine"
- Step count + estimated time: "5 steps · ~3 min"
- Progress bar: today's completion progress
- First-step preview — shows Step 1 inline: step number circle, product type, product name, chevron. Gives user immediate context before tapping. Tapping the preview row navigates directly to Screen 13.
- "Start routine" primary CTA
Skin tip — one personalized tip per day, shown below the routine card. Rotates daily, derived from the user's skin profile (type + concerns from quiz). Label: "Today's tip". See copywriting section for format.
Milestone banner — shown only on streak milestone days (day 7, 14, 30). Calm, not celebratory. Disappears after user starts their routine that day.
Completion state — if all steps already done today, routine card shows completion message instead of CTA.
Screen element order (top to bottom):
- Greeting + UV Index badge
- Weekly calendar strip
- AM/PM toggle
- Today's routine card (with first-step preview)
- Skin tip
- Milestone banner (if applicable)
States:
- Routine not started today: default card, progress bar at 0, "Start routine" CTA, first-step preview visible
- Routine in progress: progress bar partially filled, CTA changes to "Continue routine"
- Routine complete today: completion message, no CTA — calm, not over-the-top
- Streak broken (missed yesterday): gentle notice below greeting — "You missed a day — no worries. Start fresh today." Disappears once user starts routine.
- Location permission denied: UV badge hidden — no error, no prompt. Screen functions normally.
- UV data unavailable (offline / API fail): UV badge hidden silently.
Notes:
- Home is intentionally minimal — no recommendations, no conflict info, no feed. Those live on Screen 13 and Screen 15.
- Weekly calendar strip replaces streak number badge — more visual, less gamified, same information density
- First-step preview makes the routine feel personal before user even taps — they recognize their own product immediately
- UV badge is a lightweight daily hook; SPF reminder is directly actionable within the routine
- AM/PM auto-switch threshold is 12pm — same as Screen 13
End of Section 04. Next: Section 05 — Copywriting Per Screen.
Section 05 — Copywriting Per Screen
Copywriting principles (from brand guideline)
Before reading the copy below, internalize these rules. Every line of copy in Aluvi must pass all five:
- Speak like a smart friend — not a brand, not a doctor, not a salesperson
- Focus on benefits, not features — "know exactly what to use" not "AI-powered routine generation"
- Be specific and actionable — "Apply 2–3 drops to clean skin" not "Use as directed"
- Avoid jargon — "conflicts" not "contraindicated actives", "morning" not "AM"
- Always supportive and positive — even errors should feel calm, not alarming
Screen 01 — Splash
No copy. Logo only.
Screen 02 — Welcome screen
| Element | Copy |
|---|---|
| Headline (H1) | Stop guessing. Start glowing. |
| Subtext (Body 1) | Answer 7 quick questions. Get a personalized skincare routine built around products you already own — in 60 seconds. |
| Primary CTA | Continue with Apple |
| Legal footnote | By continuing, you agree to our Terms of Use and Privacy Policy. |
Rationale: Headline is benefit-first and punchy — mirrors the pain point ("guessing") and the payoff ("glowing") in 5 words. Subtext handles the "what is this" question before the user even asks.
Screen 03 — Q1 Skin type
| Element | Copy |
|---|---|
| Question (H1) | What's your skin type? |
| Hint (Body 2) | Not sure? Pick Combination if your T-zone gets oily but your cheeks feel dry. |
| Options | Dry · Oily · Combination · Normal · Sensitive |
| CTA | Next → |
Screen 04 — Q2 Skin concerns
| Element | Copy |
|---|---|
| Question (H1) | What bothers you most about your skin? |
| Hint (Body 2) | Pick up to 3. Focus on what you want to fix first. |
| Counter (empty) | Choose up to 3 |
| Counter (1–2 selected) | [n] of 3 selected |
| Counter (3 selected) | That's enough — let's work with these. |
| Options | Acne · Dark spots · Anti-aging · Dryness · Oiliness · Redness · Uneven texture · Brightening |
| CTA | Next → |
Rationale: "What bothers you most" is more emotionally resonant than "What are your skin concerns" — it mirrors how users actually think and talk about their skin.
Screen 05 — Q3 Skin sensitivity
| Element | Copy |
|---|---|
| Question (H1) | How does your skin react to new products? |
| Hint (Body 2) | Sensitive skin tends to get red, itchy, or irritated easily — especially with strong ingredients. |
| Options | Rarely reacts · Sometimes reacts · Reacts easily |
| CTA | Next → |
Rationale: Reframed from "How sensitive is your skin?" to "How does your skin react?" — more concrete and easier to self-assess. Options rewritten from technical labels to behavioral descriptions.
Screen 06 — Q4 Budget
| Element | Copy |
|---|---|
| Question (H1) | What's your monthly skincare budget? |
| Hint (Body 2) | We'll only suggest products that fit what you're comfortable spending. |
| Options | Under $20 · $20–$50 · $50–$100 · $100+ |
| CTA | Next → |
Rationale: Hint reassures user this won't be used to upsell them. Addresses the implicit anxiety of "is this app going to tell me to spend $300?"
Screen 07 — Q5 Sunscreen habit
| Element | Copy |
|---|---|
| Question (H1) | Do you use sunscreen every day? |
| Hint | (none) |
| Options | Yes, always · Sometimes · Honestly, not really |
| CTA | Next → |
Rationale: "Honestly, not really" feels non-judgmental — it gives permission to be truthful. This matters because sunscreen data directly shapes the AM routine output.
Screen 08 — Q6 Products owned (scan)
| Element | Copy |
|---|---|
| Question (H1) | What products do you already own? |
| Hint (Body 2) | Scan the barcode on each one. We'll build your routine around what you have. |
| Camera prompt | Point at a barcode |
| Success scan toast | Added ✓ |
| Not found message | We couldn't find that one. Type the name instead. |
| Manual add link | Add manually |
| Chip remove tooltip | Remove |
| Camera permission prompt | Aluvi needs camera access to scan your products. We don't store photos. |
| Camera denied state | No camera access — type your products below instead. |
| Min product hint (CTA disabled) | Scan or add at least one product to continue. |
| CTA (active) | Done — build my routine |
| CTA (disabled) | Add at least one product |
Rationale: "We don't store photos" in the camera permission prompt is a trust builder — users are increasingly wary of apps accessing camera. Addressing it proactively reduces drop-off at this permission gate.
Screen 09 — Q7 Primary goal
| Element | Copy |
|---|---|
| Question (H1) | What's your #1 skin goal right now? |
| Hint (Body 2) | Be honest — there's no wrong answer. This shapes everything. |
| Options | Clear skin · Even tone · Anti-aging · Hydration · Simpler routine |
| CTA | Build my routine → |
Rationale: "Build my routine →" instead of "Next" — this is the commitment moment. The arrow signals forward momentum. "There's no wrong answer" removes performance anxiety at the final step.
Screen 10 — AI loading screen
Rotating messages, swap every 2.5 seconds:
| Sequence | Copy |
|---|---|
| Message 1 | Analyzing your skin profile… |
| Message 2 | Checking your products for conflicts… |
| Message 3 | Building your morning routine… |
| Message 4 | Putting together your evening routine… |
| Message 5 (>7s) | Almost ready — just a few more seconds… |
Error state:
| Element | Copy |
|---|---|
| Headline | Something went wrong |
| Body | Your answers are saved. Tap below to try again — it usually works on the second go. |
| CTA | Try again |
Rationale: Loading copy is active and specific — each message tells the user what's happening right now, not a generic "loading." Error message is honest and casual ("it usually works on the second go") — this reduces frustration by normalizing the hiccup.
Screen 11 — Routine result preview (pre-paywall)
| Element | Copy |
|---|---|
| Headline (H1) — with name | [Name], your routine is ready. |
| Headline (H1) — fallback | Your routine is ready. |
| Subtext (Body 1) | Built around your products. Personalized for your skin. |
| [NEW] Personalized intro block | (AI-generated — see personalized_intro field in Feature 04) |
| [NEW] Unrecognized product notice | We couldn't identify [product name] — it wasn't included in your routine. |
| Conflict notice (if applicable) | Some of your products can clash — we've already built your schedule to keep things safe. Tap to see how. |
| Preview label | Morning routine — preview |
| Locked steps label | Unlock to see all [n] steps |
| Paywall bottom sheet headline | 7 days free, then [price]/week |
| Paywall bottom sheet subtext | See your full routine, unlock conflict details, and track your progress. Cancel anytime. |
| Paywall CTA | Start my free trial → |
Rationale: Conflict notice is reassurance-first — "we've already sorted it" not "warning: danger." User does not need to take any action; the schedule is already in their routine. Tapping is optional for those who want to understand the detail.
Screen 12 — Paywall
| Element | Copy |
|---|---|
| Headline (H1) | Your skin. Your routine. |
| Subtext | Personalized AM & PM routine, ingredient conflict alerts, and progress tracking — all built around products you already own. |
| Plan label — Weekly | Weekly |
| Plan label — Monthly | Monthly |
| Plan label — Annual | Annual · Best value |
| Plan label — Founding member | Founding Member · Lifetime deal |
| Trial CTA | Start 7-day free trial |
| Fine print | 7 days free, then [price]. Renews automatically. Cancel anytime in your iPhone Settings. |
| Restore link | Restore purchases |
Microcopy below plans:
"No charge today. Cancel before day 7 and you won't be billed."
Rationale: "Your skin. Your routine." is the most personal possible headline for a paywall — it reframes the purchase as ownership, not a subscription. The microcopy "No charge today" directly addresses the #1 paywall anxiety and is proven to increase trial starts.
Screen 13 — Full routine result
Recommendations section copy:
| State | Element | Copy |
|---|---|---|
| Gaps exist | Section label | One thing that might help |
| Gaps exist | Product card reason | "Your routine doesn't have a moisturizer yet. This one works well for [skin type] skin and fits your budget." |
| Gaps exist | CTA | View on Sephora / View on Amazon |
| No gaps | Section label | About your products |
| No gaps | Headline | You're all set. |
| No gaps | Body | Your current products cover everything your skin needs for this routine. No need to buy anything new. |
Rationale: "You're all set" with zero CTA is a trust-building moment. It signals that Aluvi is not trying to sell — increasing long-term loyalty and reducing churn.
AM / PM toggle:
| Element | Copy |
|---|---|
| Toggle option 1 | Morning |
| Toggle option 2 | Evening |
Step item copy format:
Step [n] · [Product type] [Product name] [1–2 sentence instruction]
Example AM step:
Step 1 · Cleanser CeraVe Hydrating Cleanser Massage onto damp skin for 30 seconds, then rinse with lukewarm water. Do this every morning.
Example PM step:
Step 3 · Treatment The Ordinary Retinol 0.5% Apply a few drops to clean, dry skin. Use every other evening — your skin needs time to adjust.
Completion states:
| State | Copy |
|---|---|
| Routine started | [n] of [total] steps done |
| All steps done | Great job, [Name]! Routine complete. 🌿 |
| All steps done — fallback | Routine complete — well done! 🌿 |
Share button tooltip: Share my routine
Conflict notice entry point (if applicable):
| Element | Copy |
|---|---|
| Notice row | Some products in this routine are scheduled to avoid clashes. See details → |
Edit products button:
| Element | Copy |
|---|---|
| Button label | + Edit products |
Screen 14 — Ingredient conflict detail
Example (Retinol + AHA):
| Element | Copy |
|---|---|
| Headline (H2) | Retinol + AHA — here's how we handled it |
| Explanation | These two work better on different nights. Using them together can over-sensitize your skin, so we've spaced them out in your routine. |
| Schedule headline | Here's what we built for you |
| Schedule detail | Retinol on Monday, Wednesday, Friday evenings. AHA on Tuesday, Thursday. |
| CTA | Got it |
Example (Vitamin C + Niacinamide):
| Element | Copy |
|---|---|
| Headline (H2) | Vitamin C + Niacinamide — actually fine together |
| Explanation | You may have heard these two don't mix — but newer research shows they work fine for most people. We've kept both in your routine. |
| CTA | Got it |
Rationale: Tone is "here's what we did for you" not "here's a warning." User comes to this screen to understand, not to take action — so copy leads with the solution, not the problem.
Screen 15 — Progress screen
Streak copy by milestone:
| Streak | Headline | Subtext |
|---|---|---|
| Day 1 | Great start. | One day down. Consistency is everything. |
| Day 3 | 3 days in a row. | You're building a real habit. Keep going. |
| Day 7 | One full week. | Your skin is already adapting. Stay with it. |
| Day 14 | Two weeks strong. | Real results start around now. |
| Day 30 | 30 days. | This is what consistent skincare looks like. |
| Streak broken | It happens. | Miss a day, not a week. Start fresh today. |
Empty state (day 1, no data):
| Element | Copy |
|---|---|
| Headline | Your progress starts today. |
| Body | Complete your first routine and it'll show up here. |
| CTA | Go to my routine |
Screen 16 — Profile / Settings
| Element | Copy |
|---|---|
| Subscription — active | [Plan name] · Renews [date] |
| Subscription — trial | Free trial · Ends [date] |
| Subscription — expired | Your subscription ended |
| Manage subscription CTA | Manage in Settings |
| Retake quiz CTA | Rebuild my routine |
| Restore purchases | Restore purchases |
| Data sources note | Ingredient data provided by Open Beauty Facts (ODbL license) |
| App version | Version [x.x.x] |
| Avatar placeholder | Initials from Apple ID name |
Photo picker sheet:
| Element | Copy |
|---|---|
| Option 1 | Take photo |
| Option 2 | Choose from library |
| Cancel | Cancel |
Retake quiz confirmation sheet:
| Element | Copy |
|---|---|
| Headline | Start over? |
| Body | We'll ask you the same questions and build a new routine. Your current routine will be replaced. |
| Confirm CTA | Yes, rebuild |
| Cancel | Keep my current routine |
Error & empty states (global)
| Scenario | Headline | Body | CTA |
|---|---|---|---|
| No internet on launch | You're offline | Check your connection and try again. | Try again |
| No internet during AI generation | Can't reach Aluvi right now | Your answers are saved. Come back when you're connected. | OK |
| StoreKit purchase failed | Purchase didn't go through | This usually fixes itself. Try again or check your payment method in Settings. | Try again |
| Subscription expired | Your trial has ended | Choose a plan to keep your routine and progress. | See plans |
| Generic API error | Something went wrong | We're on it. Try again in a moment. | Try again |
Screen 17 — Edit products (bottom sheet)
| Element | Copy |
|---|---|
| Sheet headline | Add a product |
| Hint | Scan the barcode or type the name. |
| Camera prompt | Point at a barcode |
| Success scan toast | Added ✓ |
| Not found message | We couldn't find that one. Type the name instead. |
| Manual add link | Add manually |
| Update CTA (active) | Update my routine |
| Update CTA (disabled) | Add a product to update |
| Cancel | Cancel |
Rationale: Copy is minimal — user has already been through this flow in the quiz. No need to re-explain. "Update my routine" (not "Regenerate") feels like a natural continuation, not a reset.
Screen 18 — Home
Greeting copy:
| Time | Element | Copy |
|---|---|---|
| Before 12pm — with name | Greeting (H1) | Good morning, [Name]. |
| Before 12pm — fallback | Greeting (H1) | Good morning. |
| After 12pm — with name | Greeting (H1) | Good evening, [Name]. |
| After 12pm — fallback | Greeting (H1) | Good evening. |
UV Index badge copy:
| UV Level | Copy | Shown? |
|---|---|---|
| 0–2 (Low) | — | Hidden |
| 3–5 (Moderate) | UV [n] · wear SPF | Yes |
| 6–7 (High) | UV [n] · wear SPF | Yes |
| 8–10 (Very high) | UV [n] · wear SPF | Yes |
| 11+ (Extreme) | UV [n] · wear SPF | Yes |
Routine card copy:
| State | Element | Copy |
|---|---|---|
| AM, not started | Routine label | Morning routine |
| PM, not started | Routine label | Evening routine |
| Step count | Subtext | [n] steps · ~[n] min |
| First-step preview | Step type | [product type, e.g. Cleanser] |
| First-step preview | Step name | [product name, e.g. CeraVe Hydrating Cleanser] |
| Not started | CTA | Start routine |
| In progress | CTA | Continue routine |
| Complete | Headline | Done for today. |
| Complete — AM done | Subtext | Come back tonight. |
| Complete — PM done | Subtext | See you tomorrow morning. |
Streak broken notice:
| Element | Copy |
|---|---|
| Notice | You missed a day — no worries. Start fresh today. |
Skin tip format:
| Element | Copy |
|---|---|
| Label | Today's tip |
| Tip body | One sentence, personalized to skin type/concern. Max 20 words. Plain language, actionable. Example: "Apply vitamin C on dry skin — waiting 60 seconds after cleansing helps it absorb better." |
Milestone banner copy:
| Streak | Headline | Subtext |
|---|---|---|
| Day 7 | 7-day streak. | Your skin is already adapting. Stay with it. |
| Day 14 | Two weeks in. | Real results start around now. |
| Day 30 | 30 days. | This is what consistent skincare looks like. |
Rationale: UV badge copy is kept minimal — just the number and one clear action. No "danger" language, no alarmism. First-step preview uses the actual product name so the user immediately recognizes their own routine. Milestone copy is understated by design — patronizing celebrations feel hollow on repeat use.
End of Section 05. Next: Section 06 — Technical Requirements & Constraints.
Section 06 — Technical Requirements & Constraints
iOS requirements
| Requirement | Spec |
|---|---|
| Platform | iOS only (MVP) |
| Language | Swift |
| Minimum iOS version | iOS 16.0 |
| Target devices | iPhone only (no iPad optimization in MVP) |
| Orientation | Portrait only |
| Xcode version | Xcode 15+ |
Authentication
| Requirement | Detail |
|---|---|
| Provider | Sign in with Apple only |
| Framework | AuthenticationServices (native iOS) |
| Token storage | iOS Keychain |
| Session | Auto-renew on app open, re-auth only on token expiry |
| Fallback | If Apple auth unavailable, show: "Sign in with Apple is required. Please check your device settings." |
In-app purchases & subscriptions
| Requirement | Detail |
|---|---|
| Framework | StoreKit 2 (iOS 15+) |
| Plans | Weekly · Monthly · Annual · Founding Member |
| Product IDs | com.aluvi.weekly · com.aluvi.monthly · com.aluvi.annual · com.aluvi.founding |
| Trial | 7-day free trial configured per product in App Store Connect |
| Validation | Transaction.currentEntitlements checked on every app launch |
| Restore purchases | Must be accessible from paywall and profile screen (App Store requirement) |
| Founding member flag | Server-side boolean per user account — checked at paywall render |
AI routine generation
| Requirement | Detail |
|---|---|
| Provider | Anthropic API (Claude) |
| Endpoint | POST /v1/messages |
| Model | claude-sonnet-4-6 |
| Timeout | 15 seconds — show error state if exceeded |
| Target response time | ≤ 10 seconds on standard WiFi |
| Output format | Structured JSON (see schema in Feature 04) |
| Error handling | Preserve quiz answers locally — allow retry without re-answering quiz |
| API key | Server-side only — never exposed in iOS client |
| Call architecture | iOS client → Aluvi backend → Anthropic API (never direct client-to-API) |
Important: The Anthropic API key must never be bundled in the iOS app or called directly from the client. All AI calls must go through Aluvi's own backend to protect the key and allow server-side prompt management.
Open Beauty Facts integration
| Requirement | Detail |
|---|---|
| SDK | openfoodfacts-swift (official, GitHub) |
| API endpoint | https://world.openbeautyfacts.org/api/v2/product/{barcode}.json |
| Required header | User-Agent: Aluvi/1.0 (iOS; contact@aluviapp.com) |
| Timeout | 5 seconds — fallback to free text input if exceeded |
| License | ODbL — attribution required in app's legal/data sources page |
| Usage constraint | 1 API call = 1 real user scan. No batch calls. |
| Camera framework | AVFoundation (native iOS barcode scanning) |
| Supported barcode types | EAN-13, EAN-8, UPC-A, UPC-E, QR (standard product barcodes) |
Product recommendation catalog
| Requirement | Detail |
|---|---|
| Database | Supabase (Postgres) |
| Catalog size | Minimum 50 products at launch, target 200–300 |
| Build process | Pre-launch: Claude + Exa crawl → structured JSON → import to Supabase |
| Enrichment | Cross-reference with Open Beauty Facts for ingredient data |
| Update cadence | Quarterly, or when major products launch/discontinue |
| Query | Claude selects from catalog passed as context during routine generation |
| Affiliate links | Direct product page URLs — Amazon Associates + Sephora affiliate |
Data storage & backend
| Requirement | Detail |
|---|---|
| Backend | Supabase (auth, database, edge functions) |
| Local storage | UserDefaults for quiz progress, SwiftData or CoreData for routine cache |
| Quiz answers | Saved locally before AI generation call — prevents data loss on crash or timeout |
| Routine data | Stored in Supabase per user account — syncs across devices |
| Progress data | Stored in Supabase — streak, completion history |
| Offline behavior | App loads last cached routine if offline. AI generation requires connection. |
Analytics
All events below must fire correctly before App Store submission.
| Event | Trigger | Properties |
|---|---|---|
app_open |
App launches | user_id, subscription_status |
quiz_started |
Q1 screen shown | user_id |
quiz_step_completed |
Each question answered | user_id, step |
quiz_completed |
Q7 submitted | user_id |
product_scanned |
Barcode successfully matched | user_id, product_name, source: "openbeautyfacts" |
product_added_manual |
Free text product added | user_id |
routine_generated |
AI returns routine result | user_id, duration_ms |
paywall_shown |
Paywall screen displayed | user_id, context: "first_time" / "expired" |
trial_started |
StoreKit trial confirmed | user_id, plan |
subscription_started |
Trial converts to paid | user_id, plan, price |
subscription_cancelled |
User cancels | user_id, plan, days_active |
routine_step_completed |
Step marked as done | user_id, step, routine_type: "am"/"pm" |
routine_completed |
All steps done in a session | user_id, routine_type |
conflict_alert_tapped |
User taps conflict banner | user_id, conflict_type |
recommendation_tapped |
User taps product recommendation | user_id, product_id, destination: "sephora"/"amazon" |
retake_quiz |
User confirms rebuild routine | user_id |
Analytics provider: TBD — Mixpanel or PostHog recommended. Must support iOS SDK and funnel analysis.
UV Index integration
| Requirement | Detail |
|---|---|
| Provider | Open-Meteo (free, no API key required) |
| Endpoint | GET https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}&hourly=uv_index&forecast_days=1 |
| Location source | iOS CLLocationManager — "when in use" permission only |
| Call architecture | iOS client → Aluvi backend → Open-Meteo API. API key not required but call must go through backend to allow caching |
| Cache strategy | Per user per day — fetch once on first app open, cache result for the day. Do not re-fetch on every Home screen load. |
| Fallback | If location denied, unavailable, or API fails → UV badge is hidden silently. No error state shown to user. |
| Display threshold | UV Index 0–2 → badge hidden. UV Index 3+ → badge shown with copy "UV [n] · wear SPF" |
| Privacy policy | Location usage must be disclosed in privacy policy — "used only to fetch UV Index, not stored or shared" |
| Metric | Target |
|---|---|
| App launch to Welcome screen | ≤ 1.5 seconds |
| Auth (Sign in with Apple) | ≤ 3 seconds |
| Barcode scan recognition | ≤ 2 seconds under normal lighting |
| Open Beauty Facts API response | ≤ 5 seconds (timeout → fallback) |
| AI routine generation | ≤ 10 seconds (show "Almost ready" after 7s) |
| Routine screen load (cached) | ≤ 0.5 seconds |
| UV Index fetch (Open-Meteo) | ≤ 3 seconds — fetched once on first open, cached for the day. If exceeded, badge hidden silently. |
| Crash-free rate | ≥ 99% (monitored via Crashlytics or Sentry) |
Security requirements
| Requirement | Detail |
|---|---|
| API keys | Never in iOS client. All sensitive keys server-side only. |
| Auth tokens | Stored in iOS Keychain only — never UserDefaults |
| HTTPS | All network calls over HTTPS. No HTTP. |
| Privacy policy | Required before App Store submission — cover camera, Apple sign-in, subscription data |
| App Transport Security | Enforced (iOS default) — no ATS exceptions |
| Camera permission string | NSCameraUsageDescription: "Aluvi uses your camera to scan product barcodes. No photos are stored." |
| Location permission string | NSLocationWhenInUseUsageDescription: "Aluvi uses your location to show today's UV Index so you know when to wear SPF." |
App Store requirements
| Requirement | Detail |
|---|---|
| Bundle ID | com.aluvi.app |
| App category | Health & Fitness (primary) |
| Age rating | 4+ |
| Privacy policy URL | Required — must be live before submission |
| Sign in with Apple | Required when any third-party login is offered |
| Subscription disclosure | Must show price, duration, and cancellation terms before purchase |
| Restore purchases | Must be present on paywall screen |
| Disclaimer | "Aluvi provides cosmetic skincare suggestions only. This is not medical advice. Consult a dermatologist for skin conditions." — shown in app settings and onboarding |
| Screenshots | Required: iPhone 6.7" (iPhone 15 Pro Max) and iPhone 5.5" (iPhone 8 Plus) minimum |
End of Section 06. Next: Section 07 — Open Questions & Decisions Log.
Section 07 — Open Questions & Decisions Log
This section tracks decisions still pending, plus all key decisions already made during PRD development. Use this as a living log — update status as decisions are resolved.
Pending decisions
| # | Question | Context | Owner | Target date |
|---|---|---|---|---|
| OQ-01 | Final pricing for Weekly, Monthly, Annual, and Founding Member tiers | Waiting on ad campaign CPL and conversion data from current Meta campaign. Founding member price should be set before app launch announcement. | Ardho | Post-campaign |
| OQ-02 | Analytics provider | Mixpanel vs PostHog. Mixpanel has better mobile funnel analysis. PostHog is open-source and cheaper at low volume. | Dev | Before build starts |
| OQ-03 | Retake quiz behavior — replace or archive? | When user rebuilds routine, does the old routine get permanently replaced or archived? Archiving adds complexity but gives user a safety net. | Ardho | Before Section 04 build |
| OQ-04 | Founding member cohort mechanism | How is a user identified as a founding member? Options: (a) email list from landing page pre-launch, (b) special promo code, (c) time-based (first N users). Needs to be decided before paywall build. | Ardho | Pre-launch |
| OQ-05 | Backend infrastructure | Supabase recommended in this PRD. Confirm with dev team if this is aligned with their preference or if another backend (Firebase, custom) is preferred. | Dev | Before build starts |
| OQ-06 | Crash reporting provider | Crashlytics (Firebase) vs Sentry. Both work well for iOS. Sentry has better error context. | Dev | Before build starts |
| OQ-07 | Minimum iOS version | PRD sets iOS 16 minimum. Confirm with dev — StoreKit 2 requires iOS 15, but some SwiftUI features used in design system may require 16. | Dev | Before build starts |
Decided — recorded for reference
| # | Decision | Rationale | Date |
|---|---|---|---|
| D-01 | iOS only for MVP, no Android | iOS-first strategy. Android after PMF validation. | Apr 2026 |
| D-02 | Sign in with Apple only, no Google | Cleaner for iOS-native. Google adds complexity with no meaningful conversion benefit on iOS. | Apr 2026 |
| D-03 | Hard paywall with 7-day free trial — no free tier | Stronger revenue signal. User gets full value during trial. More sustainable than feature-limited freemium. | Apr 2026 |
| D-04 | Paywall shown after routine result, not at launch | User experiences value first (quiz + AI generation + routine preview), then is asked to pay. Higher conversion than cold paywall. | Apr 2026 |
| D-05 | Barcode scan (Open Beauty Facts) as primary product input, free text as fallback | Improves ingredient conflict accuracy. Better UX than typing product names. Open Beauty Facts is free, ODbL licensed, has Swift SDK. | Apr 2026 |
| D-06 | Curated product catalog (200–300 products) for recommendations, not real-time AI search | Stable affiliate links, accurate ingredient data, budget-filtered. Built pre-launch using Claude + Exa. Updated quarterly. | Apr 2026 |
| D-07 | Recommendation UX — natural, not pushy | Max 3 recommendations. Label: "One thing that might help." If routine is complete: "You're all set." No urgency language. | Apr 2026 |
| D-08 | Nutrition feature deferred to v2.0 | Scientifically valid but out of MVP scope. Adds complexity, risks diluting positioning. Framing for v2.0: "foods that support your skin goals" — skincare-first, not nutrition-first. Idea credited to Dr. [name]. | Apr 2026 |
| D-09 | Anthropic API called server-side only, never from iOS client | Security requirement. API key must never be in iOS binary. All AI calls via Aluvi backend. | Apr 2026 |
| D-10 | Annual plan pre-selected on paywall | Anchoring effect — increases annual conversion. User can switch to weekly or monthly. | Apr 2026 |
v1.1 roadmap candidates
Features explicitly deferred from MVP but confirmed as next priorities:
| Feature | Rationale for deferral | Notes |
|---|---|---|
| Push notifications | Important for retention habit loop but adds build time. | Day 3 and Day 7 nudges most valuable. |
| Product barcode scan → photo fallback | Camera already in app for scan. Photo recognition (vision AI) adds cost and complexity. | Validate scan usage first. |
| Routine history & trend analysis | Requires longitudinal data — not available at launch. | Unlock after 30+ days of user data. |
| Skin improvement tracking (photo) | High wow factor but significant ML complexity. | Revisit after PMF. |
| Android app | iOS PMF first. | Reuse API layer. Native Kotlin build. |
v2.0 roadmap candidates
| Feature | Rationale | Notes |
|---|---|---|
| Nutrition for skin | Scientifically grounded. Strong differentiator. Framing: "foods that support your skin goals." Quiz → food suggestions + basic nutrition context. Not a meal planner. | Credited to Dr. [name] — consider as a brand story / credibility asset. |
| EU market expansion | Requires localization, GDPR compliance, EU-specific ingredient regulations awareness. | |
| Brand partnerships | Sponsored product placement once user base established. Natural fit: The Ordinary, CeraVe, Paula's Choice. | |
| Dermatologist referral network | Out of MVP scope. Only viable with large, engaged user base. |
End of Section 07.
Document status
| Section | Status | Last updated |
|---|---|---|
| 01 — Overview, Problem Statement & Personas | ✅ Complete | Apr 25, 2026 |
| 02 — Goals, Success Metrics & Scope | ✅ Complete | Apr 25, 2026 |
| 03 — Feature Specifications & User Stories | ✅ Complete | June 2, 2026 |
| 04 — UX Flows & Screen Structure | ✅ Complete | June 2, 2026 |
| 05 — Copywriting Per Screen | ✅ Complete | June 2, 2026 |
| 06 — Technical Requirements & Constraints | ✅ Complete | June 2, 2026 |
| 07 — Open Questions & Decisions Log | ✅ Complete | Apr 25, 2026 |
Product Owner: Ardho
Last updated: June 2, 2026
Changelog
| Version | Date | Changes |
|---|---|---|
| v1.8 | June 2, 2026 | Dev Q&A resolved — Screen 13: conflict detail entry point added (permanent access post-subscribe); Screen 14: entry points updated; Screen 16: photo profile feature added with picker sheet spec and copywriting; Feature 10: streak preservation on routine re-generation documented |
| v1.7 | June 2, 2026 | Screen 18 (Home) improved — streak badge replaced with weekly calendar strip; UV Index badge added (Open-Meteo integration); first-step preview added to routine card; skin tip and milestone banner added; Section 04 spec, Section 05 copywriting, and Section 06 technical requirements updated |
| v1.6 | June 2, 2026 | Screen 18 (Home) added — Section 04 spec and Section 05 copywriting |
| v1.5 | June 2, 2026 | Conflict model reworked — Feature 06 reframed from alert to informational notice; conflict fix now baked into routine by AI, not user action; persistent banner and nav badge removed; Screen 11 notice tone shifted to reassurance; Screen 14 rewritten; bottom nav badge removed |
| v1.4 | June 2, 2026 | "Add product" button renamed to "+ Edit products" throughout; Screen 17 updated — existing product chips pre-loaded and editable on sheet open |
| v1.3 | June 2, 2026 | Unrecognized product notice added to Screen 11; Feature 10 (Edit products) added with Screen 17 spec and copywriting |
| v1.2 | June 2, 2026 | Personalized intro block added — Feature 04 output schema updated, Screen 11 element order updated, copywriting added (Section 05) |
| v1.1 | Apr 25, 2026 | Wireframes added per screen (Sections 04 & 05) |
| v1.0 | Apr 2026 | Initial PRD — full MVP scope: overview, problem statement, personas, goals, features 01–09, UX flows (screens 01–16), copywriting, technical requirements, open questions |