Skip to content

riya-chauhan12/Skinwise

Repository files navigation

✨ Skinwise

Your skin deserves better than a 10-step routine you found at 2am. 💅

AI-powered skin analysis that actually listens — to your photo, your questionnaire answers, your lifestyle — and gives back something real.

FastAPI React MongoDB PyTorch Vite


What is Skinwise?

You know that feeling when you buy a serum because a very confident stranger on the internet said it changed their life — and then your skin absolutely hates it? Yeah. Skinwise exists so that doesn't happen to you anymore.

Skinwise is a full-stack skincare analysis MVP that combines a CNN acne detection model with an adaptive questionnaire and a rule-based recommendation engine to give you a personalized, science-backed skin report in under five minutes. No AI hallucinations, no fake promises, no "San Francisco, CA" placeholder text. Just your skin, analyzed properly.

Here's what it actually does:

  • 📸 Analyses your photo using a custom-trained EfficientNet CNN to detect acne severity
  • 📋 Walks you through a smart questionnaire that adapts based on your concerns (if you don't have acne, it doesn't ask you about acne — revolutionary, we know)
  • 🧠 Weighs questionnaire answers at 70%, CNN output at 30% so your self-knowledge matters
  • 🧪 Generates ingredient guidance — what to use, what to avoid, and what to approach with caution
  • 🌅 Builds personalized AM/PM routines based on your actual skin type and concerns
  • 📊 Tracks your progress across assessments so you can see if anything is actually working
  • 🔐 Supports magic-link authentication so your history follows you across devices

Educational tool only. Skinwise is not a substitute for professional dermatological advice. When in doubt, see a dermatologist.


Tech Stack

Layer Technology
Frontend React 18, Vite 5, Tailwind CSS 3, Framer Motion, React Router v6
Backend FastAPI 0.111, Python 3.11+, Uvicorn
Database MongoDB Atlas (Motor async driver)
ML Model PyTorch 2.3, EfficientNet CNN (3-class acne severity)
Auth JWT via python-jose, magic-link email flow
Image Processing Pillow 10
Deployment Vercel (frontend) + Render (backend)

Project Structure

Skinwise/
├── frontend/                     # React + Vite application
│   ├── src/
│   │   ├── components/
│   │   │   ├── assessment/       # Adaptive questionnaire UI
│   │   │   ├── dashboard/        # Progress, history, insights cards
│   │   │   ├── results/          # Analysis result sections
│   │   │   ├── layout/           # Navbar, Footer, MainLayout
│   │   │   └── ui/               # Shared design system components
│   │   ├── context/
│   │   │   ├── AssessmentContext.jsx   # Questionnaire state
│   │   │   ├── DashboardContext.jsx    # Real-time dashboard state
│   │   │   └── UserContext.jsx         # Auth / session state
│   │   ├── hooks/
│   │   │   └── useAssessmentFlow.js   # API submission logic
│   │   ├── lib/
│   │   │   ├── buildQuestionnairePayload.js  # Maps answers → API schema
│   │   │   └── mapAnalysisResult.js          # Maps API response → UI props
│   │   ├── pages/
│   │   │   ├── Home.jsx
│   │   │   ├── Assessment.jsx
│   │   │   ├── Results.jsx
│   │   │   ├── Progress.jsx
│   │   │   └── FAQ.jsx
│   │   └── services/
│   │       └── api.js            # Centralised API client
│   └── .env.example
│
└── backend/                      # FastAPI application
    └── app/
        ├── core/
        │   ├── config.py         # Pydantic settings (env vars)
        │   ├── constants.py      # Domain constants
        │   ├── dependencies.py   # FastAPI DI providers
        │   └── security.py       # JWT + magic-link token logic
        ├── database/
        │   └── mongodb.py        # Motor client lifecycle + indexes
        ├── ml/
        │   ├── inference/
        │   │   └── predictor.py  # CNN forward pass
        │   └── models/
        │       ├── Skinwise_acne_model_final.pth
        │       └── final_model_config.json
        ├── models/               # MongoDB document shapes
        ├── repositories/         # MongoDB CRUD (no business logic)
        ├── routes/
        │   ├── analysis.py       # POST /analysis/start, GET /analysis/results/{id}
        │   ├── auth.py           # POST /auth/request-login, POST /auth/verify
        │   ├── dashboard.py      # GET /dashboard/overview, GET /dashboard/history
        │   └── health.py         # GET /health
        ├── schemas/              # Pydantic v2 API contracts
        ├── services/
        │   ├── analysis_service.py       # Questionnaire + CNN → skin profile
        │   ├── recommendation_engine.py  # Rule-based routine generator
        │   ├── dashboard_service.py      # History aggregation
        │   └── auth_service.py           # Magic-link + JWT issuance
        ├── utils/
        │   └── response_formatter.py    # Domain → API schema mapping
        └── main.py

Analysis Pipeline

The core principle: questionnaire first, CNN second.

User Photo + Questionnaire Answers
            │
            ▼
┌─────────────────────────────────────────┐
│           Validation Service            │
│   Image format, size, MIME type check   │
└─────────────────┬───────────────────────┘
                  │
       ┌──────────┴──────────┐
       ▼                     ▼
┌────────────┐     ┌──────────────────────┐
│ CNN Model  │     │  Questionnaire Data  │
│ (PyTorch)  │     │  skin_type           │
│ 3 classes: │     │  primary_concern     │
│  minimal   │     │  secondary_concerns  │
│  mild      │     │  sensitivity_level   │
│  mod/sev   │     │  lifestyle factors   │
└─────┬──────┘     └──────────┬───────────┘
      │                       │
      │   CNN weight = 30%    │   Questionnaire weight = 70%
      │   (only for acne,     │   (drives skin type, all
      │   only if conf ≥ 65%) │   concerns, routines)
      └──────────┬────────────┘
                 │
                 ▼
┌─────────────────────────────────────────┐
│           Analysis Service              │
│  Builds SkinProfile + ConcernSnapshots  │
└─────────────────┬───────────────────────┘
                  │
                  ▼
┌─────────────────────────────────────────┐
│       Recommendation Engine             │
│  Rule-based, concern-driven routines    │
│  Different paths for: acne / pigment /  │
│  sensitivity / dryness / oiliness       │
└─────────────────┬───────────────────────┘
                  │
                  ▼
         AnalysisResultSchema
      (stored in MongoDB + returned to frontend)

API Reference

Analysis

Method Endpoint Auth Description
POST /analysis/start Optional Submit questionnaire + image. Returns assessment_id.
GET /analysis/results/{id} Optional Fetch full analysis result.

POST /analysis/start — multipart/form-data

questionnaire_json   string (JSON)   QuestionnaireSubmitSchema
image                file            JPEG or PNG, max 10 MB

Response

{
  "assessment_id": "664a...",
  "session_id": "session_1234_abcd",
  "status": "complete"
}

Dashboard

Method Endpoint Auth Description
GET /dashboard/overview Optional Full dashboard payload for current session/user.
GET /dashboard/history Optional Paginated history cards. Requires ?session_id=.

Auth

Method Endpoint Auth Description
POST /auth/request-login None Request magic link for email. Returns token in dev mode.
POST /auth/verify None Verify magic link token. Returns JWT.

Health

Method Endpoint Description
GET /health Liveness check. Returns app version + status.

Local Development

Prerequisites

  • Node.js 18+
  • Python 3.11+
  • MongoDB running locally or a MongoDB Atlas connection string

Backend

cd backend

# Create and activate a virtual environment
python -m venv venv
source venv/bin/activate        # Windows: venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt

# Configure environment
cp .env.example .env
# Edit .env — set MONGODB_URI at minimum

# Start the server
uvicorn app.main:app --reload

The API will be available at http://127.0.0.1:8000. Interactive docs (dev only): http://127.0.0.1:8000/docs


Frontend

cd frontend

# Install dependencies
npm install

# Configure environment
cp .env.example .env
# VITE_API_URL defaults to http://127.0.0.1:8000 — no change needed locally

# Start the dev server
npm run dev

The app will be available at http://localhost:5173.


Environment Variables

Backend .env

APP_ENV=development
DEBUG=true

MONGODB_URI=mongodb://localhost:27017
MONGODB_DB_NAME=Skinwise

SECRET_KEY=your-long-random-secret-here

# Comma-separated — add your frontend URL in production
ALLOWED_ORIGINS=http://localhost:5173

MODEL_PATH=app/ml/models/Skinwise_acne_model_final.pth
MODEL_CONFIG_PATH=app/ml/models/final_model_config.json
MODEL_DEVICE=cpu

Frontend .env

VITE_API_URL=http://127.0.0.1:8000

Deployment

Backend → Render

  1. Push the backend/ folder to a GitHub repository.

  2. Create a new Web Service on Render.

  3. Configure:

    • Build command: pip install -r requirements.txt
    • Start command: uvicorn app.main:app --host 0.0.0.0 --port $PORT
  4. Set environment variables in the Render dashboard:

    Key Value
    APP_ENV production
    DEBUG false
    MONGODB_URI Your Atlas connection string
    SECRET_KEY A long, random secret
    ALLOWED_ORIGINS https://your-app.vercel.app
  5. Add a Persistent Disk (1 GB) mounted at /opt/render/project/src/uploads to store uploaded images across deploys.

Note on the CNN model weights: Skinwise_acne_model_final.pth (~15 MB) is included in the repo. If you need to exclude it from git for size reasons, store it in cloud object storage (S3/R2) and download it at startup.


Frontend → Vercel

  1. Push the frontend/ folder to a GitHub repository.

  2. Import the project to Vercel. Framework preset: Vite.

  3. Set the environment variable:

    Key Value
    VITE_API_URL https://your-render-backend.onrender.com
  4. Deploy. Vercel handles the rest.


Key Design Decisions

Why no LLM? An earlier version used Gemma for generating insights. It was removed because inference was slow (5–15 seconds per request), free-tier API availability was unreliable, and the responses were inconsistent across runs. The current rule-based engine is deterministic, fast (<1 second), and produces results that are just as actionable.

Why questionnaire-first weighting? CNN models see one photo taken in one moment. A person knows whether their skin is dry year-round, how stressed they are, and whether they sleep five hours a night. The questionnaire captures longitudinal self-knowledge that a single image cannot. The CNN is used as a second opinion on acne severity only, and only when its confidence is above 65%.

Why magic-link auth? Password auth for an MVP adds complexity (reset flows, hashing edge cases, brute-force protection) without meaningful benefit. Magic links are simpler to implement, require no password management UX, and work well for a skincare app where sessions are infrequent and low-stakes.

Guest sessions Every assessment works without an account. A session_id is generated client-side on each new assessment and stored in sessionStorage. The backend groups assessments by session, so guests get full dashboard functionality. Authentication just claims those sessions to a persistent account.


Roadmap

  • Email delivery for magic links (SMTP integration)
  • Progress charts rendered from multi-assessment history
  • Photo comparison view (before / after across assessments)
  • Ingredient cross-reference lookup (flag conflicts between current products)
  • Push notifications for routine reminders
  • Accessibility audit (WCAG 2.1 AA)

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you'd like to change.

  1. Fork the repository
  2. Create a feature branch: git checkout -b feat/your-feature
  3. Commit your changes: git commit -m 'feat: add your feature'
  4. Push and open a pull request

License

MIT — do whatever you want with it, just don't sell it as a medical device.


Made with way too much skincare research and a healthy distrust of marketing claims. 🧴

About

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors