Inspiration

As busy engineering students, dedicated focused study time can be hard to come by. There's part-time jobs, design team projects to work on, endless lectures and labs to attend, etc... Consequently, the bulk of our study time is often solo, remote work, at late hours of the night with no one around to tell you you look fried. Most of us only notice we've been stressed for two hours once we're already drained, and we can't tell when we're in our best focus until someone interrupts it. Productivity apps make you track yourself, but your body is already sending those signals. We wanted to build something that reads those signals and interprets them for you.

What it does

Flow State turns your laptop webcam into a focus coach, with no wearables. • You start a session and type what you're working on. • Presage reads your pulse, breathing, blinks, and whether you're talking, straight from the webcam. • The first few minutes set your personal baseline, because everyone's "focused" looks different. • Every 30 seconds, Flow State compares your vitals to that baseline. Gemini then interprets the summary and decides whether you're focused, stressed, or neutral, and explains why. • When stress builds up, you get a break suggestion based on what you've been working on and how long you've been going. • Every reading is stored in Tiger Data, and the insights page shows your peak focus hours over time.

Only numbers leave the camera process. No video is ever stored.

How we built it • Presage SmartSpectra C++ SDK on Windows captures vitals and prints each reading as a JSON line. • Spring Boot launches the Presage client, reads its output stream, builds 30-second summaries against the user's baseline, and streams live state to the frontend with Server-Sent Events. • Tiger Data stores vitals and Gemini decisions in hypertables. Continuous aggregates power the focus-by-hour insights. • Gemini API gets a compact summary (not raw readings) plus task context, and returns a structured JSON decision: state, reason, and suggestion. • [Frontend framework] shows the live state, Gemini's reasoning, and the break card.

We also built a fake vitals generator and a replay mode, so the team could develop without a camera and the demo can't fail because of bad lighting.

Challenges we ran into • No Java SDK for Presage. The SDK is C++, and its Windows support is experimental. We connected it to Spring Boot by having the C++ client print JSON to stdout and reading that stream with ProcessBuilder. • Raw vitals are hard for an LLM. Sending Gemini a firehose of pulse readings gave inconsistent answers. We split the work: our code does the math (deviation from baseline, trends), and Gemini does the interpretation. • Hypertable keys. Hypertables require the time column in every primary key, so we had to design composite keys that JPA could handle. • "Is this actually flow?" There's no validated physiological flow detector. We chose to measure changes relative to each user's own baseline rather than claim medical-grade detection.

Accomplishments that we're proud of • Live vitals from an ordinary webcam, flowing end to end into a time-series database within a weekend. • Gemini decisions that include a reason you can read, not a black-box score. • A demo that survives bad conditions, thanks to replay mode.

What we learned • Where to draw the line between deterministic code and an LLM. Models reason well over clean summaries and badly over raw numbers. • How to bridge native SDKs into a JVM backend without JNI. • Time-series design in Tiger Data: hypertables, composite keys, and continuous aggregates.

What's next for Flow State • Automatically muting Slack/other notifications and setting your status when you're in focus • Short focus check-ins to calibrate the model to each user • App usage tracking, so you can see what leads to your best focus • "Ask your data": natural-language questions over your focus history

Built With

  • gemini-api
  • java
  • persage
  • react
  • springboot
  • tiger-data
Share this project:

Updates

Submission history