Skip to main content
All Work

StudySphere

Offline-first Android planner for attendance, lectures, and assignments.

Year

2025

Status

Released — APK available

Stack

Kotlin · Jetpack Compose · Room · DataStore · Material 3 · Android

Problem

Attendance defaulter status in Indian engineering colleges has two thresholds. Below 75% triggers mandatory compensatory assignments. Below 50% — critical defaulter — means disqualification from semester examinations. I was sitting just above 50% with no reliable way to track which subjects were safe, which were recoverable, and which were approaching the line. The college portal had a two-day update lag. My mental model was clearly not working.

Why it matters

The information needed to manage attendance is a ratio — but spread across six or seven subjects, each with a different minimum target, different lecture frequency, and different remaining classes. The cognitive load of maintaining this manually while tracking assignment deadlines is high enough that most students don't do it correctly. The consequence ranges from unnecessary extra work to exam disqualification.

Approach

Built the tool I needed. The core logic is the attendance recovery model: for each subject, the app calculates not just the current percentage but how many consecutive classes you can still skip and remain safe, and how many you must attend consecutively to recover from an unsafe position. This converts a ratio into an actionable number. Risk labels — Safe, Warning, Danger, Critical — surface the same information visually at a glance. The two questions I was asking every morning defined the entire feature set: am I safe, and what's due today.

Architecture

Kotlin + Jetpack Compose + Material 3. Room Database for all local persistence — subjects, lecture slots, attendance records, assignments. DataStore Preferences for user settings and theme state. Navigation Compose for screen routing. Kotlin Coroutines + Flow for reactive UI updates — Room queries return Flow, ViewModel collects them, Compose recomposes automatically on any data change. No network calls, no account, no sync. Everything stored locally on-device. The attendance calculation logic lives in the repository layer as pure functions: current attended over total held, projected percentage with remaining lectures, can-skip-N and must-attend-N recovery calculations, risk threshold evaluation.

System flow

Create subject with minimum attendance targetAdd recurring lecture slotsMark attendance daily (Present / Absent / Cancelled)App recalculates recovery figures in real timeDashboard shows risk label per subjectAdd assignment with due date and priorityOverdue assignments highlighted automatically

Execution Context

I'm a full-stack web developer — TypeScript and React are my primary environment. Kotlin and Jetpack Compose were new territory, learned during the build while covering semester coursework simultaneously. The constraint — learning a new stack while actively needing the tool I was building — kept the scope honest.

Tradeoffs

No cloud sync by design — the absence of a network layer removes a failure surface and a privacy surface simultaneously. The recovery calculation assumes lectures are scheduled at fixed intervals, which doesn't account for cancelled or rescheduled classes mid-semester. This is tracked manually, which is a UX limitation worth addressing in a future release.

Learnings

Building something because you genuinely need it produces different quality decisions than building it as an exercise. Every feature exists because I specifically needed it. The features that aren't there — cloud sync, social features, shared timetables — aren't absent because I couldn't build them. The attendance recovery logic was the feature I was most careful about getting exactly right, because I was going to rely on it.