In May 2024, I co-founded S&S Creation with one ambitious goal: build a smart mirror that doesn't just reflect your face, but provides AI-powered wellness insights, real-time data, and an intuitive user experience.
This is the story of how we built it, the problems we solved, and what I learned about IoT, hardware-software integration, and running a tech startup.
The Vision
The problem: Existing smart mirrors were either:
Expensive ($500+) with limited features
DIY projects that looked amateur
Just displays showing time and weather (boring!)
Our vision: An affordable, AI-powered smart mirror that:
Provides personalized wellness insights
Integrates with smart home devices
Has a beautiful, intuitive UI
Costs under $200 to build
The Tech Stack
Hardware
Raspberry Pi 4 (4GB RAM) - brain of the operation
Two-way mirror glass - the display surface
24" LCD monitor - behind the mirror
PIR motion sensor - wake on presence
Camera module - for future AI features
Wooden frame - custom-built enclosure
Software
Python - backend logic and hardware control
JavaScript & Node.js - API server
React - frontend UI
TensorFlow Lite - on-device ML inference
AWS IoT Core - cloud connectivity
Services & APIs
Weather API (OpenWeatherMap)
Calendar sync (Google Calendar)
News aggregation
Smart home integration (Home Assistant)
The Build Process
Phase 1: Hardware Assembly (Week 1-2)
Step 1: The Mirror
We started with a 24" two-way mirror glass from a local supplier:
Two-way mirror principle:-Front:reflective(80%)-Back:transparent(20%)-Monitor behind mirror shines through dark areas
-Bright display + dark background = visible content
Lesson learned: The mirror quality matters. Cheap mirrors look foggy. Invest in good glass.
Step 2: The Display
Disassembled a 24" LCD monitor:
Removed the plastic casing
Kept just the panel and control board
Mounted behind the mirror
Challenge: Display brightness. Needed max brightness for mirror visibility.
Solution:
# Raspberry Pi script to control backlightimport os
defset_brightness(level:int):"""Set display brightness (0-255)""" os.system(f'echo {level} > /sys/class/backlight/rpi_backlight/brightness')# Set to maximum on startupset_brightness(255)
import RPi.GPIO as GPIO
import time
from typing import Callable
classSmartMirror:def__init__(self): self.pir_pin =17 self.is_active =False GPIO.setmode(GPIO.BCM) GPIO.setup(self.pir_pin, GPIO.IN)defon_motion_detected(self, callback: Callable):"""Trigger callback when motion is detected"""defmotion_callback(channel):ifnot self.is_active: self.is_active =True callback() GPIO.add_event_detect( self.pir_pin, GPIO.RISING, callback=motion_callback, bouncetime=2000)defwake_display(self):"""Turn on display and load UI""" os.system('xset dpms force on') self.is_active =Truedefsleep_display(self):"""Turn off display after inactivity""" os.system('xset dpms force off') self.is_active =Falsedefstart(self):"""Main loop"""print("Smart Mirror started") self.on_motion_detected(self.wake_display)# Inactivity timer last_activity = time.time() timeout =300# 5 minuteswhileTrue:if self.is_active:if time.time()- last_activity > timeout: self.sleep_display() time.sleep(1)if __name__ =='__main__': mirror = SmartMirror() mirror.start()
The Frontend UI
// React component for mirror interfaceimportReact,{ useState, useEffect }from'react';import'./MirrorUI.css';constMirrorUI=()=>{const[time, setTime]=useState(newDate());const[weather, setWeather]=useState(null);const[calendar, setCalendar]=useState([]);useEffect(()=>{// Update time every secondconst timer =setInterval(()=>setTime(newDate()),1000);// Fetch weather every 10 minutesfetchWeather();const weatherInterval =setInterval(fetchWeather,600000);return()=>{clearInterval(timer);clearInterval(weatherInterval);};},[]);constfetchWeather=async()=>{const response =awaitfetch('/api/weather');const data =await response.json();setWeather(data);};return(<divclassName="mirror-container"><divclassName="top-left"><divclassName="time">{time.toLocaleTimeString()}</div><divclassName="date">{time.toLocaleDateString()}</div></div><divclassName="top-right">{weather &&(<divclassName="weather"><divclassName="temp">{weather.temp}°C</div><divclassName="condition">{weather.condition}</div></div>)}</div><divclassName="bottom-left"><divclassName="calendar"><h3>Today's Schedule</h3>{calendar.map((event)=>(<divkey={event.id}className="event"><span>{event.time}</span><span>{event.title}</span></div>))}</div></div><divclassName="center">{/* Wellness insights go here */}</div></div>);};exportdefaultMirrorUI;
The CSS (Dark UI for Mirror)
/* Mirror UI must have black background for visibility */.mirror-container{background:#000;color:#fff;font-family:'Roboto', sans-serif;height:100vh;width:100vw;display: grid;grid-template-areas:'top-left top-right''center center''bottom-left bottom-right';grid-template-rows:1fr2fr1fr;grid-template-columns:1fr1fr;padding:40px;}.top-left{grid-area: top-left;}.top-right{grid-area: top-right;text-align: right;}.center{grid-area: center;}.bottom-left{grid-area: bottom-left;}.time{font-size:4rem;font-weight:300;}.date{font-size:1.5rem;opacity:0.8;}.weather.temp{font-size:3rem;}
Phase 3: AI Wellness Insights (Week 5-6)
The differentiator: AI-powered wellness recommendations.
What We Built
import tensorflow as tf
from datetime import datetime, time as dt_time
classWellnessEngine:def__init__(self): self.user_profile = self.load_user_profile()defget_recommendations(self)->dict:"""Generate personalized wellness recommendations""" current_time = datetime.now() recommendations ={'hydration': self.check_hydration(current_time),'posture': self.check_posture_reminder(current_time),'break': self.check_break_needed(current_time),'sleep': self.check_sleep_quality(),}return recommendations
defcheck_hydration(self, current_time: datetime)->dict:"""Remind user to drink water""" last_drink = self.user_profile.get('last_hydration')ifnot last_drink or(current_time - last_drink).seconds >3600:return{'show':True,'message':'💧 Time to hydrate! Drink a glass of water.','priority':'medium'}return{'show':False}defcheck_posture_reminder(self, current_time: datetime)->dict:"""Remind about posture every 30 minutes"""if current_time.minute in[0,30]:return{'show':True,'message':'🧘 Check your posture! Sit up straight.','priority':'low'}return{'show':False}defcheck_break_needed(self, current_time: datetime)->dict:"""Suggest breaks based on work duration""" work_duration = self.calculate_work_duration()if work_duration >90:# 90 minutesreturn{'show':True,'message':'☕ Take a 5-minute break. Your brain will thank you!','priority':'high'}return{'show':False}defcheck_sleep_quality(self)->dict:"""Analyze sleep patterns""" avg_sleep = self.user_profile.get('avg_sleep_hours',7)if avg_sleep <6:return{'show':True,'message':'😴 You averaged less than 6 hours of sleep. Consider sleeping earlier tonight.','priority':'high'}return{'show':False}
Phase 4: Smart Home Integration (Week 7-8)
Integrated with Home Assistant for smart home control:
// Node.js API endpoint for smart homeconst express =require('express');const axios =require('axios');const app =express();app.get('/api/smarthome/lights',async(req, res)=>{try{const response =await axios.get('http://homeassistant.local:8123/api/states/light.living_room',{headers:{Authorization:`Bearer ${process.env.HA_TOKEN}`,},}); res.json({state: response.data.state,brightness: response.data.attributes.brightness,});}catch(error){ res.status(500).json({error:'Failed to fetch lights'});}});app.post('/api/smarthome/lights/toggle',async(req, res)=>{try{await axios.post('http://homeassistant.local:8123/api/services/light/toggle',{entity_id:'light.living_room'},{headers:{Authorization:`Bearer ${process.env.HA_TOKEN}`,},}); res.json({success:true});}catch(error){ res.status(500).json({error:'Failed to toggle lights'});}});
The Challenges
1. Display Brightness vs. Mirror Reflectivity
Problem: Too bright = bad mirror. Too dim = can't see UI.