- Design for the unhappy path first. Bad lighting, no match, or a slow camera are the common cases, not the exception. Clear on-screen feedback ("no face detected", "try again") matters more than a slick success animation.
- Keep the API the single source of truth. All attendance rules - who is checked in, when a day rolls over - live in the Node layer, not the Angular components. That made the UI simple and the logic testable.
- Separate enrollment from check-in. Registering a face is a different, slower flow than the daily check-in, so I kept them apart to keep the everyday path fast.
- Store events, not states. Recording each check-in and check-out as an event (rather than a single "present/absent" flag) made reports and corrections far easier.
What would I do differently next time?
I would add an obvious manual fallback earlier. Cameras fail, faces change, and there is always someone the model struggles with. A quick manual check-in that still writes to the same attendance records keeps the system usable on a bad day, and it removes the pressure for the recognition step to be perfect.
Frequently Asked Questions
What tech stack did you use?
Angular for the front end, Node.js with a REST API for the back end, and a face-recognition step behind the API for matching. The front end only captures frames and shows results; all attendance logic lives in the API.
Why put face matching behind the API instead of in the browser?
It keeps the Angular app simple, keeps matching logic and data in one place, and means the recognition step can change without touching the UI. The browser just sends a frame and displays the returned result.
How do you handle a failed or low-confidence match?
The app shows clear feedback and lets the employee retry, and a manual fallback can still write to the same attendance records. Treating "no match" as a normal case, not an error, keeps the daily flow smooth.
Is a facial-recognition attendance system hard to build?
The recognition step is the smaller part. Most of the work is the everyday flow - camera capture, clear feedback, storing check-in and check-out events, and building readable reports on top of that data.