Attendance App

  • JavaScript
  • React
  • Geolocation API
  • react-webcam

An attendance system built for teams that work in the field or outside an office — construction crews, delivery staff, field engineers. Instead of swiping a physical card or clicking a button from home, users mark attendance with a webcam selfie plus their GPS coordinates, both captured at the moment of check-in. That combination is hard to fake and trivial to audit.

Attendance check-in screen

Problem Statement

Traditional attendance systems break down the moment your workforce leaves a single office. RFID cards don’t work on construction sites, time-clock software gets gamed (coworkers clocking each other in), and honor-system check-ins through chat have no accountability at all. Managers end up reconciling timesheets from three different sources and never really know who was where.

Solution

A lightweight web app that captures two things at check-in: a webcam photo (to prove the right person is physically present) and the device’s geolocation (to prove they’re at the right site). Both are timestamped and stored server-side. A manager-facing dashboard can then verify entries and export attendance for payroll without chasing anyone.

Architecture

  1. Frontend: React, bootstrapped with Create React App. Single-page app with a login screen, a capture screen, and a history view. Styling is plain CSS since the surface area is small.
  2. Webcam capture: react-webcam drives the camera. On the capture screen, the user frames themselves, the app snaps a still at the moment of check-in, and the image is uploaded with the entry.
  3. Geolocation: Browser Geolocation API via a small wrapper (locationFetch.js) that requests high-accuracy coordinates with a reasonable timeout. Users have to grant permission once; after that check-in is one click.
  4. Backend / persistence: Entries are posted to a simple JSON API. Images are stored as binary blobs, coordinates + timestamp alongside them.
  5. Admin view: Managers can browse entries by day / user, see the photo + map pin, and flag anomalies (e.g., a check-in far from the expected site).

Features

  1. Webcam selfie on check-in: react-webcam captures a still at the moment of the action. No stored video — just one image per entry.
  2. GPS coordinates with accuracy: The app records latitude, longitude, and reported accuracy. Entries flagged as low-accuracy can be re-prompted.
  3. History / audit trail: Each user sees their own history. Managers see all users, filterable by day.
  4. Web-first, no install: Works in any modern browser. No app-store gatekeeping, no Android/iOS split.

Notable Learnings

Browser permissions are the UX

The first prototype asked for camera and location permissions the moment the page loaded. Half of users dismissed them and never figured out how to re-enable. The fix: defer the permission requests until the exact moment they’re needed (click “check in” → then request camera → then capture). Prompts feel purposeful when they’re tied to an action the user just took.

Geolocation accuracy is noisier than expected

On paper, navigator.geolocation.getCurrentPosition returns nice coordinates. In reality, inside buildings or in urban canyons it can be hundreds of meters off. I added an accuracy threshold — if the reported accuracy is worse than ~100m, the app shows “looking for a better signal” and retries instead of silently recording a bad coordinate.

Images dominated storage

Even downsampled to 640×480 JPEG, one entry per user per day across a small team fills up quickly. I added compression on the client side before upload (downscale + re-encode at 70% quality) which cut storage by ~5×. For a production version I’d push images to object storage rather than a filesystem.

”Web-first” was the right call

I seriously considered React Native. For a tool this simple — camera + GPS + a few forms — the browser does everything, and shipping a browser-based version meant no app-store review, no separate builds, and easy deployment via a URL. React Native would have been months of overhead for zero functional gain.

Thank you for reading!