JAYESH.OS
Eduteck preview
back
SHIPPED2024

Eduteck

A course platform where students lose their place every time the train goes into a tunnel is a course platform students stop using.

Client
Eduteck (edu-teck.com)
Role
Frontend Developer
Duration
2024
Team
Frontend build against an existing backend team's API

The problem

An ed-tech company selling online course subscriptions to students, primarily on mobile.

Students watch lessons on mobile data, in transit, on cheap devices. The failure mode isn't a crash, it's friction: a page that reloads to show a progress bar, a video that forgets where you were, a dashboard that takes three seconds to paint. Each one is a small reason to close the tab, and course completion is the metric the whole business runs on.

the brief

Build the student-facing web application against an existing REST API: authentication, course catalogue, the lesson player, and progress tracking — responsive first, because most of the traffic is phones.

  • The API contract was fixed — the backend already existed and wasn't changing for me.
  • Mobile-first, on real network conditions rather than a fast dev machine.
  • No design system to inherit; the UI had to be built and kept consistent from scratch.

What I built

Student web application

React single-page app covering sign-in, catalogue, course detail, and the lesson player.

Progress tracking

Per-lesson completion state that updates as a student watches, without a page reload, and survives a dropped connection.

Responsive design system

Tailwind-based component set giving the app one consistent look from small phones through desktop.

How it's built

hover to trace · click to pin

A React SPA talking to an existing REST backend over token auth. The interesting part is client-side: progress is written to local state first and synced to the API in the background, so the UI never blocks on the network and a dropped connection doesn't lose a student's place.

Decisions & trade-offs

Write progress locally first, sync in the background

The straightforward build POSTs progress to the API and waits. On a good connection that's invisible; on mobile data it means the progress bar lags the video by seconds, or a dropped request silently loses the update.

  • ·Write through to the API and reflect the response
  • Update local state immediately, sync to the API in the background

chose Local first, background syncThe student's own device is a perfectly good source of truth for 'where am I in this video'. Treating the API as a sync target rather than a gatekeeper made the UI instant and made a dropped connection a non-event.

what it cost

Two sources of truth, which means reconciliation. A student who watches on their phone and then opens a laptop can see the two disagree until the next sync. For a single-device-at-a-time product that was an acceptable trade; for a product where people genuinely switch devices mid-lesson it would not be.

Tailwind instead of a component library

No existing design system, and a UI that had to look deliberate across phone, tablet, and desktop without a designer on call.

  • ·A component library (MUI / Ant) for speed
  • Tailwind and build the handful of components the app actually needs

chose Tailwind with a small hand-built component setThe app needed about eight repeated components. A library would have shipped a lot of CSS and JS for the other ninety, and fighting its defaults to match the brand usually costs more than writing the eight.

what it cost

No accessibility behaviour for free. Focus management and keyboard handling on the interactive pieces were mine to get right, and that's slower than inheriting it from a mature library.

Hard problems

Progress that updates during playback without re-rendering the player

symptom
Progress needs to update continuously as a lesson plays. Naively wiring playback time into React state re-renders the tree several times a second, and on low-end phones that shows up as dropped frames in the video itself.
diagnosis
The stutter only appeared on throttled CPU, which is exactly the device profile most of the traffic was on — so it wasn't visible during normal development.
fix
Decoupled the high-frequency playback signal from React's render cycle: playback position is tracked outside component state and only promoted to state at the thresholds that actually change what's on screen (completion crossings, not every tick). Renders dropped to a handful per lesson.

Outcomes

Live at edu-teck.com
measured
Status
Yes
observed
Progress survives a dropped connection

Playback position is held client-side and synced when the network returns.

Auth, catalogue, player, progress
measured
Scope delivered

Every figure is tagged with how it was arrived at. Nothing here is an estimate dressed up as a measurement.

Stack

Frontend
ReactJavaScriptTailwind CSS
Integration
REST APIsToken auth
Building something like this?

Open to freelance & contract work.