Caleb Lanting
iAttend

Attendance for an after-school program at 12 schools.

iAttend replaced a stack of hand-merged spreadsheets for a K-8 after-school enrichment program. Instructors take attendance on their phones, admins see every site live, and the district that funds the program has its own portal.

Role
Sole developer, from discovery to on-site training
Status
Launched March 2026. Handed off to the client in August
When
December 2025 to August 2026
Built with
Next.js, React, TypeScript, Firebase
Made-up schools and students. No real data.

The problem

The program ran at 12 school sites with about 500 students. Attendance lived in Google Sheets kept by different people and merged by hand, so nobody had a current picture.

Instructors kept attendance in their own sheets, and the district that funds the program needed monthly numbers it could trust.

What I built

One web app with three kinds of users.

  • Attendance in a few taps

    Instructors mark each student Present, Absent or At another program, and log quick social-emotional check-ins, from their phones.

  • Live dashboards for admins

    Attendance rates by site, rosters, waitlists and alerts, updated as instructors save.

  • Monthly reports

    PDF reports the app builds and emails, instead of a spreadsheet someone assembles.

  • A portal for the district

    A separate, read-only portal for the district partner that funds the program.

  • The history came along

    I cleaned the old spreadsheets and imported about 5,500 attendance and check-in records, so the dashboards started with the whole year.

The hard part

The attendance rate was lying.

The district-wide rate was an average of each school's rate. That counts a 10-student site as much as a 60-student one, so one small site's bad week could move the whole district. It also counted days when a school's program doesn't meet, which dragged every rate down.

I raised it with the client myself, then changed the math. District numbers now add up real attendance and divide once. Every metric, report and alert counts only the days each school's program actually runs.

Combine the four sites
Days that count
District rate
(40 + 48 + 72 + 64) ÷ 4 = 56%

Willow Creek’s 10 students counted as much as Lakeside’s 70.

Every school day counted, Fridays too. The program meets Monday to Thursday, so every site lost a fifth of its rate.

Each site’s share of the district number
Willow Creek
10 students · counts for 25%
40%
Oak Hill
25 students · counts for 25%
48%
Pine Ridge
60 students · counts for 25%
72%
Lakeside
70 students · counts for 25%
64%
Lost to Fridays

Launch

The first full version, district portal included, came together in 23 days. The client tested it for several weeks and asked for additions. I trained the instructors on site, and iAttend went live at all 12 schools in March 2026.

In August I handed over the code and the Firebase project. The client's team has kept building on it since.

By the numbers

12school sites
~500students
23days to the first full version
~5,500past records cleaned and imported
21screens across three roles

From the project's git history and import files at my last commit (April 2026). Student counts vary slightly by source, from 485 to 495.

Stack and role

I did all of it: discovery calls, scoping and pricing, the build, on-site training, support, and the handoff. I built it with Claude Code, directing and reviewing every change.

Next.jsReact 19TypeScriptTailwind CSSFirestoreFirebase AuthCloud FunctionsRechartsjsPDFClaude Code

Want to build something together?

I'm looking for a team to build with full time. Email is the fastest way to reach me.