Inspiration

Hi, my name is Evan, and I am one of the founders of FloWriter and a computational Neuroscience major at JHU. As a child, I was put into remedial classes because I failed cursive, a class mandated by my state's standards. What I remember most is the endless, mindless flow of tracing worksheets my teachers handed out throughout those early years.

Why write when you can just type? Why learn an archaic practice? Those questions consumed me whenever I thought about cursive. Beyond setting me behind early in school, mandatory cursive made me hate writing in general until high school, when I learned about the many benefits of handwriting, and of cursive specifically. That marked my return to the art. Learning cursive again recently, as it grows more popular through movements like the analog movement that push back against ever-present technology, brought back everything I felt as a child: mindlessness, no room for memory, monotony, and no structured curriculum. I persevered anyway, and now I use cursive for all of my writing because of its benefits and its speed, from journals and pen pals to class notes.

If I'd had something like FloWriter, I don't know how much better my life would have been. It could have helped me early on, when cursive was mandatory in school, or later in life, when I returned to writing. I've been on both sides of cursive, and I know millions of kids probably feel the same way I did, now that cursive is mandatory in 27 states in what's been called "the cursive comeback." There are also many adults who want to learn cursive on their own.

Those two sides represent a wide range of the population and our two main users: schools (teachers and kids) that are required to teach cursive, and general learners who want an engaging way to learn it. These problems, which we faced growing up, led us to create FloWriter, the first application that turns handwriting practice into a musical rhythm game. By syncing cursive strokes to the beats of songs, FloWriter replaces tedious school drills with an experience that is competitive, fun, and effective. It answers an urgent educational need created by a legislative resurgence in handwriting instruction, rooted in recent cognitive research and in a cultural, educational, and political backlash against the digitization of classrooms that affects millions of children.

This is not an isolated event but a national trend. As of 2025, 27 states require cursive instruction, up from just 14 less than a decade ago. Recent mandates in New Jersey (2026-2027 school year), Pennsylvania (2026), California (Assembly Bill 446), New Hampshire, Kentucky, and Iowa show the momentum, and more states are likely to follow. That creates a large, fast-growing market of students who will need a modern, effective tool for handwriting mastery. FloWriter bridges that gap by taking the engagement loop of rhythm games and applying it to a core educational skill, turning a chore into a creative performance.

What it does

FloWriter is an osu!-style rhythm game for cursive. Every word is broken into its individual strokes, and every stroke is locked to a beat of the song. A glowing pen guide travels each stroke at exactly the song's tempo, and the player traces along with it. Cursive provides the movement. The BPM provides the rhythm.

Lessons follow a standard curriculum: letters (lowercase and capitals), 3-letter phrases, 5-letter phrases, full sentences, and excerpts from public-domain classics. Each module unlocks only after every test in the previous one is passed at 90% or higher. Every lesson has three modes: Demo (watch the pace), Practice (the music follows your pen and pauses when you lift), and Test (you follow the music, which never stops, and you get one try). Free Play lets you write any text to any song: a starter library we provide, or your own MP3 with the tempo detected automatically.

Teachers create class periods with join codes, assign modules with due dates, difficulty, and music, track every student's accuracy, and replay exactly what each child's trace looked like. Leaderboards and stats track words learned over time, active writing time, and the fastest song each student can write at 90%+ accuracy.

How we built it:

FloWriter is built on the web platform: HTML5 Canvas for the writing surface, the Web Audio API for sample-accurate music and metronome scheduling, and Pointer Events so it works with a finger, a stylus, or a mouse. We built it in three layers: The tracing engine. This is the core of FloWriter and where most of our time went. It contains our hand-built cursive letter library, the stroke-to-beat timeline, the scoring system, and the audio analysis. There are two builds of it, one for teacher assignments (with a locked student view and a one-attempt test) and one for free play. The platform shell. This covers the cover page, accounts and class codes, student and teacher dashboards, the curriculum, the song library, and the leaderboards. Everything is styled like a real sheet of notebook paper, with punched holes, a red margin line, and blue rules, because the product should feel like the page a child actually writes on. The shell loads the engine inside itself and passes it the words, tempo, song, and difficulty, and the engine reports scores and traces back to the dashboards. A mock backend. Every read and write goes through one API layer backed by generated test accounts (a full class of 25 students with months of practice history), so we can switch to a database without touching the interface.

To give everyone music on day one, our starter songs are synthesized in the browser. Drums, bass, chords, and melody are rendered offline through an OfflineAudioContext and encoded to WAV, so every starter song lands exactly on its BPM and the beat grid is perfect.

Challenges we ran into:

Even though music and cursive are both inherently flowing and melodic, mapping cursive strokes onto music was our biggest challenge. We spent a large part of our early time brainstorming ways to associate the two. We considered mapping letter shapes to melody and pitch, and mapping pen speed to volume, before landing on the idea that held up: the strokes themselves are the notes. When you write in sync with the music, everything flows, and the movement of writing feels satisfying. Getting there meant defining mathematically what makes cursive "flow," which in turn meant mapping every stroke of every letter by hand. We were lucky to have a team with deep backgrounds in both music, writing, and most importantly math, which let us explore the possibilities thoroughly.

Here is the algorithm we arrived at.

  1. Turning a letter into strokes We hand-mapped 57 glyphs (all 26 lowercase letters, all 26 capitals, and 5 punctuation marks) into 150 individual strokes, each placed at a real teaching point: lead-in, oval, downstroke, loop, exit. Each stroke is an ordered list of control points in x-height units, where the baseline is $y = 0$, the midline is $y = 1$, and ascenders reach $y = 2.2$: $$ s_j = \left(P_{j,0},, P_{j,1},, \dots,, P_{j,n_j}\right), \qquad P_{j,i} \in \mathbb{R}^2 $$ A word is then one continuous path cut at those teaching points. When letter $\ell$ joins letter $\ell+1$, the lead-in of the next letter is snapped to the exit height $e_\ell$ of the previous one, $P^{(\ell+1)}{0,0} = (0,, e\ell)$, so the pen never teleports. Letters that exit high (b, o, v, w) are the classic cursive trap. For those we cut the lead-in points below $y = 0.55$ so the join stays at the top, the way it's actually taught. Dots and crosses (i, j, t, x) are deferred until the whole word is written, and the pen lifts after capitals that don't connect (B D F H I O P S T V W).
  2. Making strokes smooth Straight lines between control points look robotic, and ordinary splines overshoot and form little loops on tight cursive turns. We use a centripetal Catmull-Rom spline ($\alpha = \tfrac{1}{2}$), whose knot spacing grows with the square root of the distance between points: $$ t_{i+1} = t_i + \lVert P_{i+1} - P_i \rVert^{1/2} $$ The curve between $P_1$ and $P_2$ is built with the Barry-Goldman pyramid of linear interpolations: $$ A_k = \frac{t_{k+1} - t}{t_{k+1} - t_k},P_k + \frac{t - t_k}{t_{k+1} - t_k},P_{k+1}, \qquad B_k = \frac{t_{k+2} - t}{t_{k+2} - t_k},A_k + \frac{t - t_k}{t_{k+2} - t_k},A_{k+1} $$ $$ C(t) = \frac{t_2 - t}{t_2 - t_1},B_0 + \frac{t - t_1}{t_2 - t_1},B_1, \qquad t \in [t_1, t_2] $$ For strokes to feel like one motion, the tangent has to carry across the cut between them. So a joined stroke borrows its neighbor's control point as its phantom endpoint. A stroke that starts or ends with a pen lift reflects its own point instead, $P_{-1} = 2P_0 - P_1$. Cursive also leans. We apply a shear measured from each line's own baseline $y_b$: $$ x' = x + \sigma,(y - y_b), \qquad \sigma = 0.3 ;\Rightarrow; \theta = \arctan(0.3) \approx 16.7^\circ $$ Finally, every stroke is resampled to uniform arc length ($\Delta s = 0.015$ x-heights), so each point on a stroke represents the same amount of pen travel. This matters in the next step, because it means the guide moves at constant speed.
  3. Locking strokes to beats This is the heart of FloWriter. Every stroke $k$ owns a window of $\beta$ beats (1 or 2), every space between words is a rest of $\rho$ beats, and every attempt begins with a 4-beat count-in. The first beat of stroke $k$ is $$ b_k = 4 + \beta k + \rho, w(k) $$ where $w(k)$ is the number of word boundaries before stroke $k$. The total length of a piece is $B = 4 + \beta N + \rho,(W - 1)$ beats for $N$ strokes and $W$ words. Wall-clock time follows from the tempo and the song's first-beat offset $t_0$: $$ t(b) = t_0 + \frac{60}{\text{BPM}}, b $$ During stroke $k$, the glowing guide sits at arc-length fraction $$ p(b) = \frac{b - b_k}{\beta} \in [0, 1) $$ The result is that a long loop and a tiny hook each take exactly one beat. The shape decides how far the hand travels, and the tempo decides how fast. That's what turns any word into a rhythm you can play.
  4. Scoring a trace Every ink sample $q$ gets a position and a beat timestamp $\tau(q)$, and is assigned to the stroke whose window contains it. With $d(q)$ the distance from the sample to the model stroke and $\varepsilon$ the teacher's margin of error (18% of the x-height by default), we compute three ratios for stroke $k$: $$ I_k = \frac{#{q : d(q) \le \varepsilon}}{#{q}} \qquad \text{(ink inside the margin)} $$ $$ C_k = \frac{#{m \in s_k : \exists, q,\ \lVert q - m \rVert \le \varepsilon}}{#{m \in s_k}} \qquad \text{(stroke covered)} $$ $$ T_k = \frac{#{q : b_k - 0.1\beta \le \tau(q) < b_k + 1.1\beta}}{#{q}} \qquad \text{(ink on the beat)} $$ A stroke is valid only if all three pass: $$ \text{valid}k \iff I_k \ge 0.8 ;\wedge; C_k \ge 0.7 ;\wedge; T_k \ge 0.6, \qquad \text{accuracy} = \frac{1}{N}\sum{k=1}^{N} \mathbf{1}[\text{valid}_k] $$ All three matter. Ink that stays in the margin but skips half the loop fails $C$, and a perfect shape drawn a beat late fails $T$. Because the thresholds are separate, the results screen can tell a child which way they missed: they strayed, skipped, or rushed.
  5. Practice mode: music that follows the pen In Practice, we flip the relationship so the song follows the child. The music pauses on the current beat when either condition holds: $$ \big(\text{pen up} ;\wedge; p < 0.75 ;\wedge; r_k < 0.85\big) ;;\vee;; \big(\text{pen off path for} > 250\text{ ms}\big) $$ Here $r_k$ is how much of stroke $k$ has already been reached. Lifting in the last quarter of a stroke is forgiven, because children naturally lift early. When the pen returns to the path, the song resumes from exactly where it stopped. If the child jumps ahead to the next piece (a dot, a cross, or the next word), the music jumps there too.
  6. Hearing the beat in any song Letting users upload their own MP3s meant we had to find the tempo and the first beat of any song automatically. Our detector works in four steps: Onset strength. We take a 512-sample Hann-windowed FFT (hop size 128 at 22.05 kHz) and split the spectrum into 20 log-spaced bands from 40 Hz to 10 kHz, so the kick drum and bass count as much as the cymbals. The novelty curve is the half-wave-rectified spectral flux of log-compressed band energy: $$ \mathrm{SF}(n) = \sum_{b=1}^{20} \max!\Big(0,; \log!\big(1 + 1000,\sqrt{E_b(n)}\big) - \log!\big(1 + 1000,\sqrt{E_b(n-1)}\big)\Big) $$ We then subtract a 0.5-second moving average and keep only the rises. Periodicity. We autocorrelate the onset curve, $R(\ell) = \frac{1}{N - \ell}\sum_n \mathrm{SF}(n),\mathrm{SF}(n+\ell)$, and weight each candidate tempo by a log-normal prior centered on 115 BPM, where most songs live: $$ \text{score}(\ell) = \Big(R(\ell) + \tfrac{1}{2}R(2\ell)\Big)\cdot \exp!\left(-\frac{1}{2}\left(\frac{\log_2(\text{BPM}_\ell / 115)}{0.9}\right)^{2}\right) $$ Octave-error guard. The classic failure of beat trackers is landing on half or double the true tempo. So we re-test the winner at the related tempos ${1, 2, \tfrac{1}{2}, \tfrac{3}{2}, \tfrac{2}{3}, \tfrac{4}{3}, \tfrac{3}{4}}\times$ and keep whichever one the audio supports best.

Comb refinement and phase. We slide a comb of pulses across the whole song to refine the tempo to $0.02$ BPM and find the beat phase. The tempo snaps to a whole number when it lands within $0.12$ of one, since produced music almost always uses integer tempos. Beat 1 is then aligned to the first real sound in the track, and a confidence ratio (beat energy versus off-beat energy) tells the user when to double-check the result by ear.

If the file name already contains a tempo (like song_120bpm.mp3), we use it directly and only solve for the phase.

What we learned:

Rapid prototyping. Our first versions were ugly on purpose. We built the smallest thing that could test one idea (does a stroke feel good on a beat?), played it, threw away what didn't work, and repeated. The tolerance slider that re-scores strokes live came directly from that loop, because we needed to feel the difference between 12% and 25% instead of arguing about it.

The math has to serve the feel. Every constant above ($\sigma = 0.3$, $\varepsilon = 0.18$, the 0.8 / 0.7 / 0.6 thresholds, the 250 ms grace period) was tuned by writing with it, not just derived on paper. A formula that scores "correctly" but frustrates a seven-year-old is wrong.

UI/UX design for two very different users. A 7-year-old needs big targets, instant feedback, and zero reading. A teacher with 25 students needs a table, a class code, and a due date. Designing one product that serves both, with one shared notebook visual language, taught us to design for the user in front of the screen, not for ourselves.

Pitching. Explaining "cursive as a rhythm game" in one sentence was harder than building it. We learned to lead with the problem (27 states, no curriculum, bored kids) and let the demo do the rest. Dividing roles and responsibilities. Splitting the work into clear lanes (the engine, the platform, the curriculum and music, and the pitch) let us work in parallel without stepping on each other. Agreeing on the handoff early, meaning what the engine receives and what it reports back, is what let the pieces snap together at the end.

Built With

Share this project:

Updates

Submission history