GeoMarkAdmin Manual
← Back to App

GeoMark

Geo-Verified QR Attendance System

All Roles & Technical Reference

Version 2.0  ·  May 2026

§ Table of Contents

  1. 1System Overview
  2. 2Student Guide
  3. 2.1Signing In & Registering
  4. 2.2Mark Attendance — QR Code
  5. 2.3Mark Attendance — Enter Code
  6. 2.4Mark Attendance — Bluetooth
  7. 2.5Viewing Your History & Rate
  8. 2.6Notifications
  9. 2.7Profile, Photo & Settings
  10. 3Lecturer / Instructor Guide
  11. 3.1Starting an Attendance Session
  12. 3.2The QR Code Display
  13. 3.3The Verbal Code
  14. 3.4Monitoring Live Attendance
  15. 3.5Adjusting Attendance Status
  16. 3.6Ending a Session
  17. 3.7Late Threshold Setting
  18. 3.8Multi-Department Sessions
  19. 4Admin Guide
  20. 4.1User Management
  21. 4.2Security Logs
  22. 4.3Analytics & CSV Export
  23. 5Technical Notes
  24. 5.1QR Token Security
  25. 5.2Geofencing
  26. 5.3Rate Limiting
  27. 5.4Audit Trail
  28. 5.5Security Headers
  29. 5.6Environment Variables
  30. 6Troubleshooting

1System Overview

GeoMark is a web-based attendance management platform that combines cryptographically-signed rotating QR codes with GPS geofencing to guarantee that students mark attendance only when they are physically present inside the classroom. No dedicated mobile app is required — everything runs in a modern browser.

Core security model

A student must satisfy three independent checks to mark attendance: (1) a valid, unexpired QR token or matching verbal code, (2) GPS coordinates within the configured classroom radius, and (3) an authenticated account session. Failing any one check blocks the attempt.

Key capabilities

2Student Guide

2.1Signing In & Registering

Navigate to the app URL and click Sign In. You can sign in with Google or use a local account. When registering as a student, your Matric Number is your login identifier — no email address is needed. Enter it in the format BU24CSC1021 (2 letters + 2-digit year + 3-letter department code + 4 digits).

Signing in without email

Students can sign in with their matric number or email address. Instructors and admins always sign in with their email address.

2.2Mark Attendance — QR Code

  1. From the student dashboard, click Check In and select QR Code from the dropdown. You can also open Attendance in the sidebar directly.
  2. Allow the browser to access your camera and location when prompted.
  3. Hold your phone so the QR code displayed by your lecturer fills the square viewport.
  4. The app detects and submits the code automatically — no button press needed.
  5. A green success card confirms your status (Present or Late), your distance from the classroom centre, and the course name.

Tip — scanning speed

The scanner uses your device's hardware-accelerated barcode detector when available. Detection is near-instant. Ensure the QR code is well-lit and fully visible inside the square guide.

2.3Mark Attendance — Enter Code

Click Check In → Enter Code on the dashboard, or tap the Code tab on the Attendance page. Your lecturer will display or read out a 6-character code (e.g. XKPR7W). Type it in and tap Submit Code.

GPS location is still required for the code method. You must be within the classroom geofence even when typing the verbal code.

2.4Mark Attendance — Bluetooth

Click Check In → Bluetooth on the dashboard, or tap the Bluetooth tab on the Attendance page. Tap Scan for Beacon and select the GeoMark device from the browser prompt. The app reads the session token from the beacon and submits your attendance automatically.

How it works

Your lecturer's device broadcasts a BLE (Bluetooth Low Energy) beacon containing the current session token. You must be within approximately 10 m of the lecturer's device. The beacon is only active while a session is running.
GPS location is still required even for Bluetooth check-in. You must be within the classroom geofence for the submission to be accepted.

2.5Viewing Your History & Rate

Go to History in the sidebar. The page shows a card per course you have attended, each with:

How the rate is calculated

The denominator is the number of distinct sessions ever held for that course (not just the ones you attended). A student who attends 2 out of 10 sessions correctly shows 20%, regardless of when they registered.

2.6Notifications

The bell icon in the top bar shows your personal notifications. Each successful check-in, late mark, or status change generates a notification visible only to you. Clicking Mark all read clears the unread badge.

2.7Profile, Photo & Settings

Open Settings from the sidebar. You can:

You can also click your name in the topbar and select Change Icon to pick an emoji avatar, which appears in place of a photo.

3Lecturer / Instructor Guide

3.1Starting an Attendance Session

  1. Go to QR Sessions in the sidebar.
  2. Click Generate New Session.
  3. Fill in the form:
    • Course ID — a stable identifier for the course (e.g. CS101).
    • Course Name — friendly display name (e.g. "Introduction to Computing").
    • Departments — tick one or more departments whose students should be able to mark attendance. Leave blank to allow all departments. See §3.8 for multi-department sessions.
    • Radius (m) — how far from your GPS position students may be and still count as present. Default 100 m. Adjust for large lecture halls or outdoor venues.
    • Session Start time — the scheduled start of the class (datetime picker). Used to compute the Late threshold.
    • Late after time — students who check in at or after this datetime are marked Late. The form shows the computed gap (e.g. "Students arriving after 15 min are marked Late") next to the picker so you can verify at a glance. Set it equal to the start time to mark everyone Late.
  4. Click Start Session. The system captures your browser's GPS coordinates as the classroom centre.
Allow location access when your browser asks. Without your GPS coordinates the system cannot create a geofence and the session will fail.

3.2The QR Code Display

After creation, a large QR code appears on screen. Project it on the classroom screen or share your screen via video conferencing. The code refreshes automatically every 15–30 seconds (depending on server configuration) — students must scan the current code. Old codes are cryptographically invalidated when they expire.

Display tip

For large lecture halls, use a projector or large monitor. The QR code renders at 400 × 400 px with high error correction — it remains readable when projected at 2 m × 2 m.

3.3The Verbal Code

Below the QR code, a 6-character attendance code(e.g. XKPR7W) is displayed in large monospace text. Read this code aloud or write it on the board for students who cannot scan the QR. The verbal code remains valid for the full duration of the session (it does not rotate like the QR token).

Code character set

Codes use only uppercase letters and digits with visually ambiguous characters removed (0 O 1 I Lare excluded) to prevent reading errors.

3.4Monitoring Live Attendance

The session panel shows a live list of students who have checked in, including their name, email, status, timestamp, and distance from the classroom. The list refreshes every 10 seconds automatically.

3.5Adjusting Attendance Status

Each row in the attendee list has a status dropdown. You can change a student's status to Present, Late, Absent, or Flagged. Every change is:

Manual status overrides are logged for academic integrity. The audit record includes the modifier's email, the timestamp, and the IP address of the request.

3.6Ending a Session

Click End Session. The QR code and verbal code become immediately invalid — any subsequent scan or code submission will be rejected with "Session not found or already ended." A notification is sent to you summarising the total number of students who attended.

3.7Late Threshold Setting

The late threshold is configured via two datetime pickers in the session creation form: Session Start and Late after. The difference between them is the grace period. The form displays the computed gap as a live preview (e.g. "Students arriving after 15 min are marked Late") so you can see the exact value before starting the session.

ConfigurationBehaviour
Late time = Start timeAll arrivals are marked Late immediately (0-minute grace period)
Late time 15 min after startStudents who check in within 15 minutes are Present; after that, Late
Late time not setLate threshold disabled — all students marked Present regardless of when they arrive

Tip — large classes

For lectures that take time to settle, set the Late time 10–15 minutes after the scheduled start to give students a reasonable grace period without penalising genuine late arrivals for minor delays.

3.8Multi-Department Sessions

By default, a session is open to students from all departments. To restrict attendance to specific cohorts, tick one or more departments in the Departments checkbox list in the session creation form.

Department codes

Department codes are derived from student matric numbers (e.g. CSC from BU24CSC1021). Ensure students register with the correct matric format so their department is parsed correctly.

4Admin Guide

4.1User Management

Navigate to Users in the sidebar. Admins can:

4.2Security Logs

The Security page shows all high-severity events: invalid QR tokens, location anomalies, and manual attendance overrides. Each entry records the user, event type, IP address, user-agent, and full details.

4.3Analytics & CSV Export

The Analytics page aggregates attendance across all courses and sessions. Use the filters at the top of the page to narrow the data:

Click Export CSV to download the filtered data as a spreadsheet. The export respects the currently selected period and course filters. All fields are sanitised to prevent spreadsheet formula injection (cells beginning with =, +, or @ are prefixed with a tab before export).

CSV columns

The export includes: Student Name, Email, Matric Number, Department, Course ID, Course Name, Session Date, Check-in Time, Status, and Distance from Classroom.

5Technical Notes

5.1QR Token Security

Each QR code embeds a signed token (not a plain session ID). The token is structured as:

<base64url(JSON payload)>.<HMAC-SHA256 signature>

Payload fields:
  sessionId   — UUID for the QR session
  courseId    — course identifier
  courseName  — human-readable course name
  lat / lon   — classroom GPS coordinates
  radius      — allowed geofence radius in metres
  iat         — issued-at timestamp (ms)
  exp         — expiry timestamp (ms)

The HMAC is computed with the server-side QR_SECRETenvironment variable using timing-safe comparison (crypto.timingSafeEqual) to prevent timing-oracle attacks. Tokens are validated for signature and expiry on every scan — an expired token is rejected even if the signature is valid.

Secret rotation

Rotating QR_SECRET immediately invalidates all outstanding QR codes. Plan rotation during off-hours or between sessions.

5.2Geofencing

Distance is computed with the Haversine formula:

const R = 6371000; // Earth radius in metres
const dLat = toRad(lat2 - lat1);
const dLon = toRad(lon2 - lon1);
const a = sin²(dLat/2) + cos(lat1)·cos(lat2)·sin²(dLon/2);
const distance = 2·R·atan2(√a, √(1−a));

Accuracy depends on the device's GPS hardware. Indoor GPS can be off by 10–50 m on some devices. Set radiusMeters generously (100–150 m) for multi-storey buildings or venues with poor GPS reception.

ScenarioRecommended radius
Small seminar room30–50 m
Standard lecture hall80–120 m
Large auditorium or campus venue150–200 m
Multi-building campus area300–500 m

5.3Rate Limiting

All submission endpoints are protected by an in-memory sliding-window rate limiter:

EndpointLimitWindow
POST /api/qr/validate30 attemptsper user per minute
POST /api/code/validate10 attemptsper user per minute
POST /api/qr/generate20 sessionsper instructor per hour
POST /api/auth/register5 registrationsper IP per 15 minutes
The current rate limiter is in-memory and resets on server restart. For multi-instance deployments (horizontal scaling, serverless), replace it with a Redis-backed implementation.

5.4Audit Trail

Every manual attendance status change writes aSecurityLog document:

{
  userId:    "<modifier's user ID>",
  eventType: "attendance_status_modified",
  severity:  "medium",
  details: {
    attendanceId:  "<record ID>",
    studentId:     "<student's user ID>",
    studentEmail:  "<student email>",
    courseId:      "<course ID>",
    previousStatus: "present" | "late" | "absent" | "flagged",
    newStatus:      "present" | "late" | "absent" | "flagged",
    modifiedBy:    "<modifier's email>",
  },
  ipAddress: "<requester IP>",
  userAgent: "<browser string>",
  createdAt: <timestamp>
}

Logs are never deleted automatically — retain them according to your institution's data governance policy.

5.5Security Headers

All responses include these HTTP security headers:

HeaderValue
X-Frame-OptionsDENY
X-Content-Type-Optionsnosniff
Strict-Transport-Securitymax-age=63072000; includeSubDomains; preload
Permissions-Policycamera=self, geolocation=self, microphone=()
Referrer-Policystrict-origin-when-cross-origin
Content-Security-Policydefault-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; connect-src 'self' wss:; img-src 'self' data: blob: https://lh3.googleusercontent.com

5.6Environment Variables

The following environment variables must be set before deploying. Missing required variables cause the server to refuse to start.

VariableRequiredDescription
MONGODB_URIYesMongoDB connection string
NEXTAUTH_SECRETYesLong random string for session encryption
NEXTAUTH_URLYesPublic URL of the deployment (e.g. https://geomark.example.com)
QR_SECRETYesLong random string for HMAC-signing QR tokens. Never expose publicly.
LECTURER_CODEYesRegistration code that grants instructor role
ADMIN_CODEYesRegistration code that grants admin role
FOUNDER_PASSWORDYes (seed only)Password used by the admin seed route
QR_TTL_SECONDSNo (default: 30)QR token lifetime in seconds — clamped to 15–300
GOOGLE_CLIENT_IDNoGoogle OAuth client ID (needed for Google sign-in)
GOOGLE_CLIENT_SECRETNoGoogle OAuth client secret

6Troubleshooting

Problem: Camera does not start / "Could not start scanner"

Ensure the site is served over HTTPS (camera access is blocked on HTTP). Check that you granted camera permission in your browser. On iOS, use Safari — other browsers on iOS share Safari's camera engine and may behave inconsistently.

Problem: QR code scans slowly or not at all

Ensure the QR code is well-lit and fills the square viewport. Chrome and Edge on Android use hardware-accelerated decoding — use these for the best experience. On slower devices, the pure-JS fallback (jsQR) may take 1–2 seconds per frame.

Problem: "You are Xm away from the classroom"

Move closer to the lecturer's position. If you are physically inside the room but still rejected, the instructor may need to increase the radius setting. Indoor GPS drift of 20–50 m is normal on some devices.

Problem: "Code not found or session has ended"

The instructor may have ended the session, or the QR token has expired before you submitted. Ask the instructor to confirm the session is still active. If using the verbal code, check you typed it correctly (no 0, O, 1, I, or L in valid codes).

Problem: "Attendance already recorded"

You have already checked in to this session. If you believe the recorded status is wrong, contact your instructor — they can change it manually from the session panel.

Problem: "Too many attempts" (rate limit)

You have exceeded the scan/code submission limit. Wait 60 seconds and try again. If this recurs, check that the QR scanning loop is not submitting duplicate requests.

Problem: Notification bell is empty for a new account

This is correct. Notifications are generated by system events (check-ins, session starts, status changes). No pre-existing notifications are shown for newly registered users.

Problem: Attendance rate shows 0% despite attending sessions

The rate is relative to all sessions held for a course. If sessions were created under a different course ID, your check-ins will not be counted. Confirm with the instructor that the same Course ID is used consistently.

Problem: Bluetooth — "No beacon found" or scan completes with no result

Ensure you are within approximately 10 m of the lecturer's device. BLE range drops significantly through thick walls or in crowded rooms. Also confirm the lecturer has an active session running — the beacon is only discoverable while a session is live. Try moving closer and tapping Scan for Beacon again.

Problem: Bluetooth — browser shows no device picker / permission denied

Bluetooth access requires the user to interact with a browser permission prompt. If you dismissed it or previously denied access, open your browser's site settings and re-enable Bluetooth. On mobile devices, ensure both the device Bluetooth toggle and the browser permission are enabled in system settings.

Problem: Bluetooth check-in accepted but attendance still rejected

Bluetooth check-in still requires a valid GPS geofence. Even if the beacon is detected, you must be within the classroom radius set by the lecturer. If you are inside the room but still rejected, ask the lecturer to check the radius setting (see §3.1).