Hey! Welcome to Mirror Mirror — a project I built to help people slow down, check in with themselves, and celebrate small wins, one day at a time.
What is Mirror Mirror?
It's a daily self-reflection companion where you chat mindfully, receive personalised affirmations based on your mood, and — if you want — snap a selfie. Each selfie is saved alongside your daily affirmation, so you can literally watch your self-growth over time in your own private gallery.
Key Features:
- Guided, empathetic chat to help you reflect and process your feelings
- Personalised, uplifting affirmations & encouragement
- Daily selfie feature: Look yourself in the eye, capture a photo, and pair it with your affirmation
- Private gallery: Revisit your journey — see your photos and words of kindness to yourself
Tech Stack:
- Vite (development & build)
- React + TypeScript (UI & logic)
- shadcn-ui & Tailwind CSS (design system)
- Supabase for backend & storage
- Deno for running serverless functions
- Google Gemini API for conversational AI and personalised affirmations
npm install
npm run devCreate .env in the project root:
VITE_SUPABASE_URL=your_supabase_project_url
VITE_SUPABASE_PUBLISHABLE_KEY=your_supabase_publishable_key
GOOGLE_GEMINI_API_KEY=your_gemini_keyNotes:
- The frontend uses
VITE_SUPABASE_URLandVITE_SUPABASE_PUBLISHABLE_KEY. GOOGLE_GEMINI_API_KEYin.envhelps local/dev testing, but deployed Supabase Edge Functions read this key from Supabase project secrets.
Link this repo to your own Supabase project:
supabase link --project-ref your_project_refsupabase secrets set GOOGLE_GEMINI_API_KEY="your_real_gemini_key"supabase functions deploy chat-reflection
supabase functions deploy generate-affirmation
supabase functions list- If sign-in shows
Email not confirmed, disable email confirmation in Supabase:- Authentication -> Providers -> Email -> Confirm email OFF
- If your function is protected and the user session is missing, function calls can return
401 Unauthorized.
If selfie capture cannot access camera:
- Open app in Chrome.
- Click lock icon in address bar -> Site settings -> Camera -> Allow.
- On macOS: System Settings -> Privacy & Security -> Camera -> enable Google Chrome.
- Close apps that may be using the camera (Zoom, FaceTime, Teams, etc.).
FunctionsFetchError: function is unreachable or not deployed.FunctionsHttpError (401): user session/JWT issue or function auth mode mismatch.FunctionsHttpError (500): function runtime failed (often missingGOOGLE_GEMINI_API_KEYsecret or Gemini API error).
If you try this out, I'd love to hear how the experience feels or if you have feature ideas!
Thanks for checking out my project.
— Grace


