All projects
Case study

Tapt

An offline-first NFC attendance system that turns card taps into DepEd's monthly SF2 report.

Role
Full-stack developer
Type
Thesis, team project
Timeline
Aug 2026 to present
Status
Ready for pilot
React NativeExpoTypeScriptReactSupabasePostgreSQLexpo-sqliteVitest

The problem

At the partner school, a public senior high school in Pangasinan, attendance was kept on paper. A student class secretary wrote attendance on a logsheet every subject period, the subject teacher signed it, and at the end of the month the class adviser tallied everything by hand into School Form 2 (SF2), DepEd's Daily Attendance Report of Learners.

The SF2 is strict: each day splits into AM and PM half-days, partial absence counts as tardy, learners are grouped by sex with subtotals, and the form needs monthly statistics like Average Daily Attendance and learners with five consecutive absences. Doing that by hand every month is slow and error-prone, and a lost or unsigned logsheet leaves a gap the adviser has to reconstruct.

Who uses it

  1. 01Class secretary: scans classmates' NFC cards on an Android phone
  2. 02Class adviser: reviews, corrects and confirms each session, then exports the SF2
  3. 03Admin: sets up the school, rosters, schedules and suspensions on the web
  4. 04Students: just tap their cards, with no account to manage

Constraints

  • The classroom has no reliable Wi-Fi or mobile data, so the app had to work fully offline. This was a hard requirement, not a nice-to-have.
  • The secretary takes attendance in the short change between periods, so scanning had to be fast and hard to get wrong.
  • Class suspensions for typhoons and flooding come from several sources (PAGASA, DepEd, the provincial DRRMO, the LGU, the school) and arrive unpredictably.
  • The output had to be the official SF2, matching DepEd's rules exactly, not a look-alike report.
  • The data is about minors, so access had to follow the Data Privacy Act of 2012 (RA 10173): scoped by role, with as little data collected as possible.

Key decisions

  1. 01

    Offline-first with a local write queue

    Every write is saved to SQLite on the phone before any network call. A sync queue sends writes to Supabase one at a time, in the exact order they were made, retrying with backoff. Order matters because the server only accepts taps while a session is open: if "session ended" arrived before an offline tap, the tap would be rejected. A bug that broke this ordering was found, fixed and covered by tests.

  2. 02

    IDs made on the phone, so retries are harmless

    Sessions and attendance records get their UUID on the phone, not from the server. The server upserts on that ID, so if the app is killed after a write lands but before it's marked synced, sending it again updates the same row instead of creating a duplicate. A double tap reuses the existing record too.

  3. 03

    Access rules live in the database

    Supabase row-level security is on for every table: each school sees only its data, secretaries and advisers only their section, and each role can write only what it should. A bug in the app can't leak another section's attendance. Work that needs secret keys, like filling the SF2 or creating accounts, runs in Edge Functions so the keys never reach a phone.

  4. 04

    Only the adviser corrects marks

    Subject teachers aren't in the system, so the adviser's confirmation replaced the paper signature. A card tap is the only way a secretary can mark someone present, and the database blocks anything else. Every correction is the adviser's, and the original mark is kept for audit.

  5. 05

    Follow the real SF2 exactly

    The export fills DepEd's official Excel template, with cell addresses read from the actual file. An early draft used a majority rule for half-days; after checking with the adviser and the real form, it was corrected to the count-and-compare rule the SF2 actually uses.

From tap to SF2

On the phone, offline

  • Card tap

    UID looked up in the cached card list

  • Saved to SQLite

    record written locally, with a UUID made on the phone

  • Queued

    the full row goes into a write-ahead sync queue

Sync queue

Sends one write at a time, in the order made. Retries network errors with backoff from 2 to 60 seconds; real rejections go to a Sync Problems screen.

On Supabase

  • Upsert on the UUID

    a retry updates the same row, never a duplicate

  • Row-level security

    checks school, section and role on every write

  • Adviser confirms

    corrections keep the original mark

  • SF2 export

    confirmed sessions roll up into the official template

Taps are saved on the phone first and synced in order whenever a connection appears. Only adviser-confirmed sessions count toward the SF2.

Getting the SF2 right

Requirements came from a site visit and questionnaire at the school, its real class program, a real DepEd school calendar, the official blank SF2 template read cell by cell, and direct confirmation of the half-day rule with the adviser.

  • Half-day rule: absent in none of a block's sessions is Present, in some is Tardy, in all is Absent.
  • Suspensions and holidays mark a block as no class, so fully suspended days never count as absences. A suspension declared mid-session ends it; the data is kept but excluded.
  • Learners are grouped by sex with subtotals, and the monthly summary fills Average Daily Attendance, percentage of attendance and five-consecutive-absence counts.
  • Unconfirmed sessions don't block the export. They're flagged for the adviser, the same way a missing paper sheet is handled today.
  • Advisers can also download a blank SF2 with the class list and school days filled in, for filling by hand.

Screens

The secretary's home screen listing today's classes, with the current class in progress and earlier ones marked confirmed or pending adviser review.
The secretary's day at a glance: what's running now, and what still needs the adviser.
The scanning screen showing "NFC Ready to Scan" for Earth and Life Science, 14 of 22 learners scanned, and a list of learners not yet scanned.
Taking attendance by NFC tap. Anyone who hasn't tapped is marked absent when the session ends. (Demo records: the emulator has no NFC reader.)
The scanning screen in airplane mode, with an amber banner saying the device is offline and changes will sync when it reconnects.
Works offline: taps are saved on the phone and upload once a connection is back.
A Sync problems list showing attendance changes the server rejected, each with the error details and a Skip this change button.
When the server rejects an offline change, here a secretary marking attendance by hand, it's shown plainly instead of retrying forever.
The adviser's session review with one learner's mark corrected to Late and labeled as edited, above a Confirm button.
The adviser reviews the secretary's record, corrects a mark, and confirms the session.
The SF2 Export screen for October 2026 with an alert explaining that some days aren't confirmed yet and will be flagged in the file.
SF2 export flags unconfirmed days instead of passing them off as final.
The admin Schedule page listing eight subjects for a section with their AM or PM block, weekdays and class times.
The admin web: each section's weekly class program, which drives the secretary's daily list.
The admin Calendar page with a Declare Event dialog filled in for a whole-day, school-wide class suspension due to a typhoon.
Declaring a class suspension, so suspended days drop out of attendance and the SF2.
A filled DepEd School Form 2 for October 2026 with daily attendance columns, male and female learners grouped with daily totals, absences as X, tardies as shaded cells, and the monthly summary box.
The generated SF2 in DepEd's official template: day columns, sex grouping and the monthly summary, all computed from the taps.

What it does

  • NFC scanning with the card's read-only UID; nothing is written to the card
  • Session flow: start, tap, end (non-tappers become absent), adviser confirms
  • Push notifications to the adviser for each finalized session
  • Sync Problems screen for writes the server rejects, so nothing is skipped silently
  • Roster import from the school's SF1 Excel export
  • Weekly class schedule, holidays and suspensions managed by the admin
  • Monthly SF2 export through a short-lived private link
  • 15-table PostgreSQL schema with row-level security on every table

How it was built

About 60 commits between late August and October 2026. Testing covered 22 Vitest unit tests for sync ordering, backoff, error handling and suspension rules, emulator runs including offline and device-clock scenarios, a database test of the secretary's write rules, and checks that forged login tokens are rejected.

A dry run at the partner school on real phones confirmed login, NFC scanning and push notifications work, and surfaced one limit: the sync queue is per phone, so each account needs its own device.

At the thesis panel evaluation, the panel made ten suggestions. Nine were built, tested and deployed the same day, including database rules that stop secretaries from marking attendance by hand; two-factor authentication was deferred to future work.

A 2 to 4 week pilot with two sections and 100 NFC cards is planned, with the paper SF2 kept in parallel to compare accuracy.