Proiecte/CoffeeBrew
CoffeeBrew
Un espressor într-o aplicație: împerechere prin Bluetooth, predarea rețelei Wi-Fi, preparare programată și un widget pe ecranul principal. Nu există espressorul, așa că e scrisă pe un protocol de dispozitiv și rulează pe unul simulat. Tot ce e deasupra liniei ăleia e real.
- ROL
- Design și dezvoltare
- AN
- 2026
- PLATFORMĂ
- iOS + Android
- STARE
- Nepublicată

Espressorul, favoritele și ce e la rând
02 / 07
Screen 2 of 7: Espressorul, favoritele și ce e la rând
Orice aplicație pentru un aparat conectat e simplă exact până în momentul în care aparatul nu e în cameră.
CoffeeBrew se împerechează cu un espressor prin Bluetooth, citește cât mai are apă, boabe și ciclu de curățare, îi dă rețeaua ta Wi-Fi ca să meargă și când telefonul nu e prin preajmă, iar apoi prepară după un program, cu un widget pe ecranul principal care spune ce urmează și cu o notificare dacă are nevoie de tine.
Nu aveam un espressor. Așa că dispozitivul stă în spatele unei interfețe de protocol: scanează, citește senzorii, listează rețelele, configurează și prepară, iar aplicația livrează o singură implementare a ei, una simulată. Înlocuirea cu un espressor real e un fișier, nu o rescriere. Constrângerea asta e rostul proiectului, nu o scuză pentru el.
Tot ce e deasupra interfeței ăleia e construit de-adevăratelea: fluxul de împerechere cu stările lui de eșec, backendul pe Supabase, checkoutul Stripe pentru boabe, memento-urile pentru preparările programate care rulează pe un cron din baza de date indiferent dacă aplicația e deschisă, precum și modulul Swift care ține widgetul în pas cu aplicația.
Nepublicată, și e pe pagina asta pentru ce demonstrează, nu pentru ce a vândut. Design și dezvoltare în întregime ale mele.
- STARE
- Nepublicată
- PLATFORMĂ
- iOS + Android
- CONSTRUITĂ
- 2026
Trei ecrane îl duc.Un singur dispozitiv, trei stări.

STAREA 01 / 03
Ce spune espressorul
Apa, boabele și ciclul de curățare se citesc din aparat înainte să ți se ofere ceva, așa că unul care nu poate răspunde apare ca indisponibil, nu ca pregătit. Favoritele și programul stau dedesubt, pentru că întrebarea la deschiderea aplicației nu e niciodată ce poate face. E dacă aparatul e gata și ce e deja la rând.

STAREA 02 / 03
O preparare, specificată complet
Mărimea și tăria se rezolvă într-o singură comandă trimisă prin interfața dispozitivului, nu într-un ecran de setări lăsat la interpretarea aparatului. Interfața aia are azi o singură implementare și e una simulată; înlocuirea cu un espressor real e un fișier, nu o rescriere.

STAREA 03 / 03
O preparare de la care telefonul poate pleca
Ecranul îți spune să-l închizi și chiar asta vrea să spună, pentru că prepară aparatul, nu aplicația. Preparările programate merg mai departe: programul stă în Postgres, iar un cron din interiorul bazei de date trimite memento-ul, așa că pornește indiferent dacă aplicația e deschisă, închisă forțat sau dezinstalată.
Două decizii care merită explicate.Părțile care au durat cel mai mult.
D—01
Cum scrii pentru un aparat care nu există
Scurtătura tentantă e să presari `if (demoMode)` prin tot fluxul de conectare. Merge pentru o demonstrație și pe urmă nu mai poate fi descurcat, pentru că purtarea reală și cea falsă ajung amestecate în aceleași funcții.
Așa că dispozitivul e o interfață cu șase metode, iar aparatul simulat e o implementare a ei: întârzieri, o putere de semnal, patru rețele false, valori de senzori care alunecă. Fluxul de conectare nu știe niciodată cu care dintre ele vorbește.
export interface CoffeeMakerProtocol { getScanFilter(): ScanFilter readSensors(id): Promise<SensorData> readAvailableWifiNetworks(id) provisionWifi(id, credentials) sendBrewCommand(id, command)} // one implementation today, two tomorrowD—02
Un memento care nu are nevoie de aplicație
O preparare programată nu valorează nimic dacă memento-ul depinde de aplicația deschisă, iar un cronometru în client e exact asta, pentru că moare odată cu procesul, iar iOS o să omoare procesul.
Programul stă în Postgres, un cron din interiorul bazei de date trezește o edge function în fiecare minut, iar funcția aia e cea care trimite notificarea. Telefonul e client al programului, niciodată proprietarul lui.
-- pg_cron, inside the databaseselect cron.schedule( 'brew-reminders', '* * * * *', $$ select net.http_post(…) $$) // the app can be closed, force-quit,// or uninstalled. The brew still fires.PE CE E CONSTRUIT
- CLIENT
- React Native · Expo SDK 54 · expo-router · TypeScript strict · Zustand
- DISPOZITIV
- react-native-ble-plx · configurare Wi-Fi prin BLE · protocol simulat
- BACKEND
- Supabase: Postgres, Auth, Edge Functions, Realtime, pg_cron
- NATIV
- modul Expo în Swift · WidgetKit · App Groups · BGTaskScheduler
- COMERȚ
- Stripe: payment intents, webhooks, confirmare de comandă
CREDITE
Design și dezvoltare în întregime ale mele.
STARE
Nepublicată. Construită pe un protocol de dispozitiv și rulează pe un aparat simulat.
PROIECTUL URMĂTOR
Rhovie
Un antrenor de îngrijire a pielii cu AI. O scanare a feței îți citește pielea, iar fiecare scanare se salvează, așa că progresul se vede, nu se presupune.
Spune-mi ce construiești.Un plan scris și un preț fix înainte să se miște vreun ban.
Răspund la tot într-o zi lucrătoare. Dacă nu sunt omul potrivit pentru proiect, ți-o spun din start, nu după trei săptămâni.




