Qlay AI Proctor
A Mac and Windows app that supervises a remote job assessment and watches the candidate through their own webcam, on their own computer.
- Electron
- React
- Python
- Agora
Why it has to be a desktop app
A company sends a candidate a link to an assessment. Nobody is in the room with them. This app is the invigilator.
A website cannot see a second monitor being plugged in, cannot stop the candidate switching apps, and cannot run face detection without uploading every frame. So the product is a desktop app for Mac and Windows. The checks run on the candidate's own machine.
What the candidate does
They paste their session link and agree to being monitored. They verify their identity, set a phone up as a second camera angle, and calibrate where they are looking and how they sound. The test then opens in a window they cannot switch away from, with their webcam in a small panel beside it.
What I built
Several people built this. By commit count I wrote most of it. My share was the operating-system side and the live exam session.
That covers starting and supervising the detection program, the locked exam window, the floating webcam panel, the second-monitor detector, and the rules for what counts as a violation. On the interface, I built the live session: reading gaze, recording and uploading the webcam, holding the live connection, and turning those signals into the activity log a reviewer reads afterwards.
Staying inside the test
Each candidate has their own test link. If they are not signed in yet, the assessment site sends them to a login page and then drops them on its homepage, not on their test. The exam window remembers the address it was asked to open and returns there once login finishes. It tries a handful of times, and it waits until the page no longer looks like a login screen.
Not every alarm means the same thing. Blocking an app-switch means the candidate tried to leave. A window losing focus can be an operating-system notification stealing it. Those are reported as different events.
How the product is put together
Three programs run at once, and the split is the point. The interface is React, and it has no access to the computer. A Node process holds the operating-system work: locking the window, watching displays, and restarting anything that dies. A Python program owns the webcam and runs the face and gaze models. Python is packaged inside the app, so the candidate does not install it.
The interface can ask Node only for a short list of allowed actions. That is what keeps a compromised page away from the machine. Video runs through Agora. Session events and crash reports go to their own services.
Keeping the laptop usable
Running face detection on every camera frame would heat up the laptop the candidate is being tested on. Gaze is checked three times a second, on a compressed snapshot, and a change is reported at most once every three seconds. The webcam recording uploads during the test, in short pieces, at the smallest size the storage service accepts.
Two release checks stop a bad build from looking fine. The build stops if the server address is missing, because the app would otherwise open normally and quietly fail to talk to anything. A release is also rejected unless its signature is time-stamped. The certificate expires in about three days, so an unstamped build works today and breaks for candidates later in the week.
A tradeoff I kept
Node sends Python one request at a time. The order stays simple, and a slow detection makes the next step wait, including calibration. Checking gaze only three times a second is what keeps that line short. The cost is noticing a glance away up to a third of a second later.
If the connection drops, violations are saved on the machine, and only the latest 200 are kept. A long outage loses the middle of the log. I chose a bounded gap over a log that grows without limit in a window that reloads often.