Projects
glanceOS
July 2026
Turns any browser-capable screen into a live dashboard that nobody has to log into, click, or remember to change.
Why it exists
Screens are everywhere, and almost all of them are either dark or showing something that wants attention. A spare monitor, the TV in a waiting room, an old tablet, a battery e-paper panel on a wall.
glanceOS makes them useful and quiet. A screen shows what was chosen for it and nothing else, and there is nothing to configure on the device itself: plug it in, join Wi-Fi, claim it with the code it puts on the glass, and everything after that happens in a web app.
How it works
One server process is the source of truth for devices, boards, and integration data. Screens are dumb glass. They subscribe over Server-Sent Events and render what they are sent, and they cache the last state they were given, so a Wi-Fi blip or a server restart never blanks a wall display. Battery e-paper devices cannot hold a connection open, so they poll instead and get back a pre-rendered 1-bit image of the same board, rendered from the same runtime rather than from a second implementation.
Boards are composed in a Notion-style studio: click anywhere and type, or drop in blocks from a palette of 221 types covering charts, clocks, lists, calendars, tickers, and big numbers. A block binds to one of 190 built-in integrations, to anything that can send a webhook, or to values typed in directly, and falls back to those typed values when a source is unreachable. There are 166 starter boards to begin from, and one board rotates through its own pages on a schedule, so a screen can run standup in the morning and sales in the afternoon unattended. The whole thing self-hosts as one container with a single SQLite file, the screen runtime is held under 32 KB so an old TV browser can run it, and no data leaves the machine.
How a board reaches a screen
- Integrations to Server
- Server to Rules engine
- Rules engine to Server: switch board, alert
- Server to SSE hub
- SSE hub to Screen runtime: push
- Server to E-paper: poll
The hard part
An alert is only worth having if it is right, and both ways of being wrong are expensive. A rule that fires on every blip teaches people to ignore the wall, and a rule tuned quiet enough to stop that will sit silent through a real incident. The first attempt at the quiet side was a per-rule cooldown, which is a rate limiter rather than an understanding: it stops the same alert repeating, but it cannot tell a five-second spike from a deploy queue that has genuinely been backed up for twenty minutes, and it holds back the second alert of a real incident exactly as readily as the second alert of a false one. What works is making the engine time-aware instead. A sustained node keeps a first-true timestamp per rule node, so a condition counts only once it has held continuously for N minutes. Edge comparators read the current sample against the previous one and fire on the transition tick alone, so crossing a threshold alerts once instead of every minute until someone fixes it. A stale sense stamps when a watched field last changed, which catches the failure nobody writes a rule for: a sensor that quietly stopped reporting and is therefore never out of range. Trends are judged over a chosen window from an hour to ninety days rather than against the last reading.
The constraint that made this awkward to build is that the evaluator has to stay pure and total. The same condition tree against the same context must always produce the same verdict, offline, reading no clock of its own. Duration is inherently stateful, so none of the history lives inside it. The tick layer resolves every sustained node once per pass, innermost first, and threads the verdicts back in as an argument, keyed by a node’s own content rather than its position in the tree, so two identical rules share one timer and rearranging a rule does not silently reset a condition that has been counting for nineteen minutes. That history re-baselines on restart, which is the honest cost: after a restart, a twenty-minute condition starts counting from zero. Past a few alerts in a ten-minute window the individual banners collapse into one summary instead of taking over the wall, and anything nobody acknowledges re-raises itself later, louder and on every channel the account can reach.
Stack
Links
CarbonSight
September 2025, MLH Best Use of the Gemini API, PennApps XXVI
A four-person build at PennApps XXVI. Devank owned the React dashboard layer.
Sends each prompt to the smallest Gemini model that can still answer it, and shows a team the energy behind every answer.
Why it exists
A team running prompts through a model API sees a token bill and nothing about energy. Nobody can say which of yesterday’s calls needed the largest model and which would have been answered as well one tier down.
CarbonSight makes that choice before the call and reports it after. The router picks the tier, and the dashboard puts the estimate in front of the person who typed the prompt as well as the manager who pays for it.
How it works
A prompt reaches a semantic cache first. Gemini embeddings and cosine similarity look for a question close enough to one already answered, and a match returns the stored answer with no model call at all. On a miss the router reads an energy threshold and the quality tolerance the user set, picks Flash-Lite, Flash, or Pro, and allocates a thinking budget by how hard the task looks. The agent workflow runs on Google ADK behind a FastAPI backend.
Devank built the React layer above that. Every answer carries an efficiency badge, so the cost lands on the person who typed the prompt instead of in a monthly report; team leaderboards and org-wide analytics give managers the same numbers aggregated, and carbon-credit reports export out of them. Verified gains issue ERC-20 tokens and ERC-721 badges through OpenZeppelin contracts on Polygon, which puts the record of a saving somewhere other than the dashboard that claims it.
Request path
- Prompt to Semantic cache
- Semantic cache to Router: miss
- Router to Flash-Lite
- Router to Flash
- Router to Pro
- Flash-Lite to Dashboard
- Flash to Dashboard
- Pro to Dashboard
- Dashboard to Polygon: verified gains
The hard part
Nothing in a model API reports energy. There is no joules field and no per-call kWh, so the number the whole product rests on had to be derived from what the API does return: latency and token counts, mapped to an estimated kWh per model tier and from there to CO₂. That is an approximation, and it is worth saying so plainly rather than dressing it up. What makes it usable is that the same mapping runs over every call, so two prompts that differ in the dashboard differ in fact, and a leaderboard built on it puts people in the right order even if the absolute grams are wrong. Ordering is what a leaderboard actually needs, and consistency is what buys it. Carbon accounting is the claim the data would not support.
Stack
Links
Built with Advita Shrivastava, Ira Pathak, and Aarav Raina.
iPad-to-Mac Drawing Tablet
June 2026
Turns an iPad and an Apple Pencil into a pressure-sensitive drawing tablet that any Mac application can use, over a USB cable.
Why it exists
A pressure-sensitive drawing tablet costs a few hundred dollars, and the iPad and the Pencil are already on the desk. Sidecar connects the two devices, but it mirrors a display: the iPad becomes a second screen, not an input device that the Mac’s own applications can read pressure from.
The missing piece is a driver. Something the operating system treats as a real tablet, so pressure arrives in whatever application is already open instead of inside a screen-sharing session.
How it works
An iPad app captures Apple Pencil input, including position, pressure, and tilt, and streams it to the Mac over the USB cable with Peertalk, which multiplexes a socket connection between an iOS device and a connected Mac. On the Mac, a DriverKit extension reads that stream and translates it into tablet events, so an application that already knows how to handle a graphics tablet sees one attached and does not need to know what is on the other end of the cable.
DriverKit is the constraint that shapes the rest. Drivers run in user space rather than in the kernel, are written in C++ against a deliberately narrow set of APIs, and require system extension entitlements before macOS will load them at all. Pressure passes through a curve-mapping stage on the way through, so the number the Pencil reports is not the number the driver hands to the system.
Event path
- Apple Pencil to iPad app
- iPad app to USB
- USB to DriverKit extension
- DriverKit extension to Any Mac app
The hard part
The difficulty was never moving bytes across the cable. It was correctness at the level of individual fields: a tablet event carries position and pressure in a particular range and a particular coordinate space, and every one of those has to agree with what the receiving application expects. Get a range or a space wrong and nothing fails loudly. Strokes still appear, roughly where the Pencil is, with roughly the weight it was pressed at, so the result looks plausible and feels wrong, which is a far harder thing to chase than an error. The narrow DriverKit surface makes it harder again, because there is not much room to inspect what the system does with an event once it has left the driver. And the pressure curve on top of that is a judgement rather than a lookup: a Pencil pressed lightly and a stylus pressed lightly on a dedicated tablet do not report the same number, so mapping between them means deciding what a light stroke should mean and then checking it by drawing, not by reading a log.
Stack
Zoodu
October 2024, Best RAG Chatbot, HackPSU Fall 2024
Answers a question about Penn State’s research computing clusters out of the ICDS User Guide rather than out of a model’s memory.
Why it exists
The ICDS User Guide covers Penn State’s research computing clusters from one end to the other: connecting, submitting jobs, handling data, using software. A researcher who opens it usually wants one line out of it. Which queue to submit to, which module to load, how much of a storage quota is left.
Reading a manual to find that line is the wrong shape of work for someone who is halfway through a job submission. A chatbot that locates the relevant part of the guide and answers from it hands back the line instead of the document.
How it works
The guide is stored as sections, each one with its title, its text, and the URL it came from. An incoming question is matched against those sections, the matching section is handed to the model as the material to answer from, and the reply is written out of that text rather than out of what the model already knows. A Flask backend does the matching and the model call, and the interface is a single page.
The hard part
Retrieval always returns something. The guide is a handful of long sections, and a match on any shared word means "how are you doing" lands on whichever section happens to contain the word "how", after which the model answers at length, and confidently, about submitting jobs. Off-topic questions fail in the same direction, and so does anything conversational. Tightening the match is the obvious fix and it trades one failure for the other, because a stricter bar starts refusing real questions phrased in words the guide does not use. What the work came down to was the decision in front of the retriever rather than the retrieval itself: sorting an incoming message into a question the guide can answer, small talk, or something the guide has nothing to say about, and making that last case say so plainly instead of guessing.
Stack
Links
Skoda India Documentation System
Summer 2025
Built during a Software Development Internship at Taikisha Group, May to August 2025.
Scan the code on a machine part to pull up its manual, report the fault, and order the replacement without leaving the floor.
Why it exists
Maintenance documentation at the plant lived on paper. Finding the manual for an industrial part meant finding the binder that held it, and doing that on the floor, next to the machine, was the part that did not work.
Reporting a malfunction and ordering the replacement were their own processes on top of that, each with a person in the middle. The technician who found the problem was not the one who could move it forward.
How it works
Every part carries a QR code. Scanning it opens that part’s record on the floor: its manuals and product documents, and the actions available on it. From the same record a technician files a malfunction report and orders a replacement part, so the fault and the order stay attached to the part they came from instead of being re-entered somewhere else.
An order picks up a vendor quotation on its way through rather than being reconciled with one afterwards. Engineering and procurement use the same application under different roles, and user management for those roles is part of the application.
The hard part
The scanning was the easy half. The difficulty was that engineering, procurement, and vendors each see a different slice of the same order, and the flow has to stay one flow while the permissions diverge. A technician needs to file a fault and request a part; procurement needs the quotation and the vendor side of the same request; the vendor needs only what is being ordered. Building those as three separate screens would have been straightforward and would have quietly rebuilt the handoffs the paper process already had. Keeping it one flow meant the order stayed a single record from report to quotation, and the role decided what of it rendered and what could be changed, which is a harder thing to reason about than three screens because every state of the record has to be correct under every role at once.
Stack
Other builds
-
ESP32 water-tank automation
Embedded automation for a water tank, running on an ESP32.
-
Lirra
A storytelling companion for children, built at Cal Hacks 12.0. It detects emotion in a child’s speech and text, then generates a story around it, narrated in a cloned parent voice with comic-style art.
Devpost
-
Tuk Tuk
Campus carpooling, built at HackPSU Spring 2025. Students, faculty, and staff post and search rides inside a community where everyone is a verified member.
Devpost
Skills
Languages: Python, TypeScript, JavaScript, C++, Java, SQL
Frameworks and tools: React, Node.js, Express, FastAPI, Docker, Git, MySQL, MongoDB, Supabase, SQLite
AI and data: Retrieval-Augmented Generation, Embeddings and semantic search, Google ADK, Gemini API, REST API design
Systems: DriverKit, Server-Sent Events, ESP32, Raspberry Pi, Time-series alerting