Skip to content

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ă
CoffeeBrew — Espressorul, favoritele și ce e la rând

Espressorul, favoritele și ce e la rând

02 / 07

Screen 2 of 7: Espressorul, favoritele și ce e la rând

Problema

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.

Rezultatul

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
Produsul

Trei ecrane îl duc.Un singur dispozitiv, trei stări.

CoffeeBrew — state 2

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.

CoffeeBrew — state 4

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.

CoffeeBrew — state 5

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ă.

Pe dedesubt

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.

protocol.tsTS
export interface CoffeeMakerProtocol {  getScanFilter(): ScanFilter  readSensors(id): Promise<SensorData>  readAvailableWifiNetworks(id)  provisionWifi(id, credentials)  sendBrewCommand(id, command)} // one implementation today, two tomorrow

D—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.

process-brew-reminders/index.tsTS
-- 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.

Preiau proiecte noi

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.