projects / easemysemester / features
Cram swipe: got it or flag to revisit
Cram's advance gesture was given a direction, right for got it and left to flag for revisit, and the completion screen now offers to re-run just the flagged cards.
feature · current · updated 2026-09-16 · EaseMySemester case study
Cram originally tracked nothing per card, deliberately: no know-it/don't-know-it rating, no spaced repetition, read-through only, so a student with limited time was never doing data entry. This amends that rule, on the reasoning that the swipe is the advance gesture regardless, so a direction on it costs nothing extra. A one-to-five rating would still be refused as data entry; a direction on a gesture already being made is not.
What changed
Swiping (or tapping a button) right marks a card read and advances, as before. Swiping or tapping left also marks it read, since the student did read it, and additionally flags it for revisit. Two large on-card buttons, sized to the 44px touch-target floor, implement both directions alongside the swipe, since a swipe-only interface is unusable with a screen reader or a large phone.
The completion screen replaced its coverage delta with the flagged count and a
"Run them again" action. A revisit run drains its own flags: swiping right on
a flagged card during a revisit run clears it, so the set shrinks by use with
no management screen or manual clear. Flags live in a cram_revisit table
keyed on user and question, upserted (not duplicated) on repeat flags so the
original flag time survives, and cascade-deleted with the user or the
question. This is a flag, not a scheduler: no due dates, no intervals, no
ease factors. Spaced repetition is a separate, deliberately parked feature.
Three defects fixed the day after launch, one cause
The swipe indicators, labels, verdict buttons, and the first-card hint, were all children of
the card's own transformed DOM node, so they travelled with the card and left the screen with
it instead of staying put to register the verdict. The fix made the stage itself never
transform: the rails became siblings of the card, and the verdict buttons and hint moved
outside the stage entirely. Feedback also became proportional rather than binary, driven by
drag distance from the first pixel instead of snapping on only once the decision was already
made, and a one-time nudge rocks the first card through the real drag pipeline to demonstrate
the mechanic (suppressed under prefers-reduced-motion).
A pure-function test over the geometry could not catch the nesting and did not; the old suite asserted the broken structure and passed. The replacement test extracts the card's rendered subtree and asserts the rails, both verdict buttons, and the hint are not inside it, verified by sabotage (renesting each element in turn turns the suite red). Two more defects surfaced only by checking in a browser rather than trusting the code: several Tailwind utilities the layout needed generated no CSS in this project's build, so the rail geometry is inline, and React StrictMode's double-invoked effect let the first pass silently cancel the nudge's animation frames before the second pass could run it.
Verified
A full 63-card run flagged 3, completion read "You read through 63 questions in 1:49" with "Run them again (3)" and "Back to Read next," no streak or score. Running the flagged set to completion by swiping right on all three drained it back to zero, leaving only "Back to Read next." Both on-card actions measured as real focusable buttons at 134×44 and 133×44.
Status
Shipped, 2026-09-09. See overview.