You are browsing as a guest. Sign up (or log in) to start making projects!

MonkeySpeak

  • 9 Devlogs
  • 13 Total hours

track how fast you can speak .. as that is going to be the new way of communicating with tech

Open comments for this post

2h 22m 16s logged

da monkey upgradesss -> leaderboard + results

shipped two big surface reworks this week.

leaderboard got its own hub. rankings, filters, and personal stats live on one page now & ofc no more bouncing between /stats and a tiny home board. cleaner rows, mode/duration toggles, and your own numbers sitting under the global board.

post-test results got rebuilt from scratch. one shared results view: wpm, accuracy, consistency, streak, and the session graph, instead of the old packed panel. same screen whether you just finished a run or are peeking at what a good score looks like. ( graph mite be reworked on again but eh )

mic still moves when you’re talking. words still have to earn their place.

👻 something ghosty is next. that’s all you’re getting its really cool trust 👀👀

0
0
18
Ship #2 💀 Cursed

monkeyspeak update is live 🙊

spoken monkeytype —> read prompts out loud, get scored on speed and clarity. v0 had the core loop. this ship adds the stuff that makes it feel like a real app.

what's new:

leaderboard
global board via supabase — nickname + emoji after a run, no signup
home page 3-column layout with leaderboard, hero, and your personal best card
your top score card still tracks local pb for the current duration, not whoever is #1 globally
stats + profile

/stats dashboard — streak, totals, recent runs, wpm charts, achievements
profile hub drawer — activity heatmap, badges, lifetime stats
everything uses the same minimal desk ui as home
speech fixes

try it: monkeyspeak-delta.vercel.app
github.com/nothariharan/monkeyspeak

  • 3 devlogs
  • 7h
  • 17.31x multiplier
  • 63 Stardust
Try project → See source code →
Open comments for this post

3h 15m 53s logged

UPDATEE:: — stats, brave stt actually works, hydration fix

tl;dr

  • deepgram stt works on brave now (and edge) — words dissolve, wpm moves, no more fake “google speech blocked” errors
  • root cause: brave kills the vercel http audio bridge + we fell back to browser speech (which shields also blocks)
  • fix: brave/edge → render websocket proxy (wss://monkeyspeak.onrender.com/...); chrome/firefox still use vercel bridge
  • fixed utterance_end_ms=400 deepgram 400 spam (minimum is 1000 on live listen)
  • fixed bridge sending keepalive json into the pcm stream (corrupted audio, empty transcripts)
  • stats page + profile hub — streaks, achievements, session history, same minimal desk ui as home
  • live: https://monkeyspeak-delta.vercel.app
  • repo: https://github.com/nothariharan/monkeyspeak (commit might differ by the time u read — i keep pushing)

CHANGES::

deepgram / stt (the painful part)

routing by browser

browser path brave / edge websocket → render proxy → deepgram chrome / firefox (prod) same-origin POST /api/deepgram/live bridge on vercel localhost ws://localhost:8080 when backend is up, else bridge

🐜🪲🐞 that made it look dead

  1. utterance_end_ms=400 — deepgram returns http 400 on live ws below 1000ms. was baked into client urls. clamped to 1000 everywhere (client, bridge, render backend, server.js)
  2. keepalive in pcm body — http bridge was writing {"type":"KeepAlive"} into the upload stream every 3s. deepgram got garbage bytes, transcripts stayed empty, no obvious error in ui
  3. brave + duplex fetch — bridge connects, mic on, waveform moving, but ndjson response never streams back. zero words dissolved
  4. bad fallback — deepgram fail → auto webspeech → brave shields block google → ui says google is blocked even though user picked deepgram. now we don’t fallback on brave/edge when deepgram is preferred

other STT polish

  • bridge waits for BridgeReady before marking session ok
  • server-side keepalive via deepgram sdk on the bridge route (not in pcm stream)
  • removed verbose [STT:deepgram] console spam from prod — debug only with NEXT_PUBLIC_DEBUG_STT=true
  • gsap scale not eligible for reset warning fixed on momentum meter

stats + profile

  • new /stats dashboard — totals, streak, recent runs, wpm trend charts
  • profile hub drawer — nickname, activity heatmap, achievement badges
  • shared stats-* / desk css so stats doesn’t look like a different app
  • achievements + streak logic with unit tests (lib/achievements.ts, lib/stats/streak.ts)

UI / polish

  • home + results + settings aligned to same minimal desk style
  • daily challenge card, error/not-found pages match the rest
  • monkey favicon + readme/docs polish

Infra

  • GET /api/deepgram/proxy-health — same-origin render health check (browser never hits render directly, no cors scream)
  • render monkeyspeak-dg-proxy redeployed via render cli

what actually happened on brave

  1. user picks deepgram → app tries vercel http bridge
  2. brave never delivers streaming ndjson reliably
  3. fallback kicks webspeech → shields block google
  4. ui shows “brave shields may be blocking google’s speech service” — confusing af because user didn’t pick browser mode

fix was routing + stop lying via fallback. not more deepgram dashboard staring.


what’s next (maybe)

  • GHOST RACE — new mode where u speak against ur pb (most wanted)
  • signed run tokens so leaderboard posts tie to a finished test
  • shared rate limit (redis/kv) if leaderboard spam shows up
  • vendor ort wasm properly so vad worker stops whining in console

ok that was a lot of browser-specific nonsense for a monkey that just wants you to read words out loud 🐒🐒🍌


0
1
21
Open comments for this post

1h 5m 30s logged

monkeyspeak devlog more fixes (leaderboard + home + cors bug) - ship soon trust ..


tl;dr

  • home page is a 3 column layout now — leaderboard on the left, hero in the middle, top score on the right
  • global leaderboard via supabase — nickname + emoji after a run, no signup, same board for everyone on the site
  • personal bests still local — top score card shows your best for the duration, not whoever is #1 globally
  • supabase wired on vercel with service role key server side only (/api/leaderboard get + post)
  • cors scream from chrome fixed — browser no longer fetches render root directly for proxy health checks

what i changed

home page layout

the thing ig what it does hero leaderboard duration tabs synced with config bar, crown svg for top spots, emoji avatars, your row pinned at the bottom even if you are not top 5 leaderboard save prompt pops after a speed run — pick name + icon (defaulted to hehe 🐵), saves to supabase, remembers name locally for next time top score card personal best for current duration + prompt type only visual cleanup removed hero doodles, tightened title spacing, consolidated duplicate hero css

leaderboard rows used to live in zustand localStorage. ripped that out — supabase is source of truth now. name and emoji prefills still persist locally.

global leaderboard backend

  • new table leaderboard_entries in supabase (migration in supabase/migrations/001_leaderboard_entries.sql)
  • rls enabled, no anon policies — all reads/writes through next.js with SUPABASE_SERVICE_ROLE_KEY
  • upsert rule matches old local behavior: same name + duration + prompt type (case insensitive) only updates if wpm goes up
  • light rate limit on post (~30s per ip) — good enough for hobby scale, not fortress grade
browser → GET/POST /api/leaderboard (vercel)
              ↓ service role
         supabase postgres

render backend unchanged — still deepgram only, no db env vars there.

cors fix (chrome (ofc brave as well) was mad again)

production deepgram mode probes whether the render proxy is alive before connecting. that probe used to be a cross origin fetch at https://monkeyspeak.onrender.com/ from the vercel app.

render cold starts and error pages often ship without cors headers even when express has origin: * — so chrome logged the whole blocked by cors policy thing and deepgram mode thought the proxy was dead.

fix: new same origin route GET /api/deepgram/proxy-health on vercel. server checks render, browser never touches render over http cors. also slapped explicit options handling on the render backend for anything that still hits it directly.


what’s next (maybe)

  • signed run tokens so leaderboard posts are tied to an actual finished test
  • shared rate limit (redis/kv) if spam shows up
  • delete the testmonkey row sitting on prod from smoke testing
  • render keep alive still on the list from v0.1
  • preview env on vercel for prs

ok that was a lot of infra for a monkey with a crown svg but at least the board is real now. lmk in replies if you want the supabase dashboard walkthrough or the security fixes implemented properly.

2
0
62
Open comments for this post

2h 54m 39s logged

monkeyspeak final devlog before ship ( hopefully )


tl;dr

  • so brave and edge broke everything ( ye read what broke for more info )
  • deepgram mode now transcribes live text again (words dissolve, wpm moves, momentum still reacts to your voice)
  • brave and edge no longer hang for 25 seconds then fake a mic error
  • production uses a render websocket proxy + vercel env, same path that worked locally
  • github: nothariharan/monkeyspeak (commit 095b731 and earlier speech routing work on main)
  • live: monkeyspeak-delta.vercel.app

what i changed

speech routing (back to something that made sense)

mode behavior browser web speech api only. no deepgram hijack on brave/edge mount. deepgram try deepgram first (proxy → bridge fallback on chrome only). if that fails, fall back to web speech with a clear error.

the ui now shows errors for the provider that actually failed, not a generic “mic blocked” when stt died for other reasons.

deepgram client hardening

  • prefer var name ur wish websocket proxy over the vercel http bridge
  • brave/edge without a reachable proxy: fail fast with a useful message (no 25s timeout)
  • utterance_end_ms locked to 1000 everywhere (deepgram rejects live ws with 400 below that)
  • bridge watchdog clears on BridgeReady, not on first random chunk
  • server bridge waits for upstream deepgram before closing the socket

the transcript fix (the big one)

  • client parses deepgram json whether it arrives as a string, blob, or arraybuffer
  • render proxy forwards deepgram replies as utf-8 text frames instead of opaque binary

infra

  • backend/ express + ws proxy deployable on render (render.yaml included)

  • set up env with ur var name at vercel

  • redeployed frontend via vercel cli after env update

small polish

  • clearer vad fallback logs (worker load fail vs no voice detected vs timeout)
  • config bar hint on brave/edge when browser mode is selected
  • momentum sprites + gsap monkey states (from earlier in the sprint)

what broke (and why it looked cursed)

  1. brave and edge block or mishandle the vercel http audio bridge (duplex fetch upload), so deepgram connections hung ~25s and never returned transcripts.

  2. those browsers also cannot open an authenticated websocket straight to api.deepgram.com, so they need the render ws proxy (wss://…/api/deepgram/proxy) instead of the chrome-friendly paths.

  3. even after the proxy worked, deepgram sent json in binary ws frames and the client ignored anything that was not a string, so words never updated until we parsed blob/arraybuffer payloads.


what’s next (maybe)

  • vendor ort wasm for vad so the worker stops complaining
  • gsap scale split for clean console
  • render keep-alive or paid instance if cold starts hurt demos
  • preview env on vercel for pr deployments (production is wired today)

sorry if i yapped a lot and the fixes where actually slighly more techy stuff so i didnt wanna yap abt that as wel so yeah if u want to know lmk in replies :)

6
2
386
Ship #1

monkeyspeak v0 is live 🙊

been building this for a while --- it's the spoken equivalent of monkeytype. you get a prompt, hit the mic, read it out loud, and the app tracks how fast and how accurately you speak.

what's in v0:

speed mode
- pick 15s, 30s, 60s, or 120s
- live net wpm (filler words like "um" and "uh" get stripped)
- sentences, numbers, or paste your own custom text
- words dissolve on screen as you nail them
- monkey mascot animates based on your speaking momentum
- personal bests per duration + prompt type

clarity mode
- type or paste what you said
- word-level diff against the original prompt
- grades from s down to "needs work"
- practice mode that rebuilds a prompt from words you missed

ui refresh
- new landing hero: "how fast⚡can you speak 🙊"
- the monkey mascot IS the start button now — click it to begin
- speech-themed doodles, clean flat design, no gradient bloat
- sprite animations via gsap

under the hood
- next.js 14 + typescript + zustand
- web speech api by default (no api key needed)
- optional deepgram integration with server-side proxy (key never hits the browser)
- silero vad for voice activity detection

try it: clone the repo, npm install, npm run dev, allow mic access, go.

github.com/nothariharan/monkeyspeak

  • 5 devlogs
  • 3h
  • 15.16x multiplier
  • 53 Stardust
Try project → See source code →
Open comments for this post

26m 39s logged

reworked the ui and got monkeyspeak ready for v0 ship launch :))

it’s basically monkeytype but for your voice — read a prompt out loud, get scored on speed + clarity.

features:

  • speed mode: timed speaking tests (15s / 30s / 60s / 120s) with live wpm + word accuracy
  • clarity mode: paste your transcript, get a word-by-word diff + letter grade
  • click the monkey mascot to start (no separate mic button anymore lol)
  • animated monkey companion that reacts to your speaking energy mid-test
  • words dissolve on screen as you say them correctly
  • personal bests saved locally
  • browser speech api works out of the box, optional deepgram for better stt
  • themes, accent colors, custom fonts
  • keyboard shortcuts (enter to start, tab to reset, escape to stop)

built with next.js, typescript, gsap, zustand.

repo: github.com/nothariharan/monkeyspeak

0
0
50
Open comments for this post

16m 53s logged

made the ui more clean still settling the latency here and there

current new approach i am building around is using the deepgram api key for initial purpose later trying to replicate what they do

open to questions or recommendations for the whole stt etc.

0
1
278
Open comments for this post

36m 14s logged

cooking up 🚀🔥

soon making it public just lots of latency issue in speaking to text conversion who knew it would be a pain but yeah let me know if u guys think of an alternative for it or anything at all

thanks for reading :)

0
0
40
Open comments for this post

16m 1s logged

built the first iteration of the website !

got lots of customizing options now i am working more towards reducing the latency between what u speak and what is being transcribed

give me your opinions and recommendations :)

0
0
41

Delete project?

Are you sure you want to permanently delete this project? This action cannot be undone.

All devlogs, followers, and associated data will be removed.

Followers

Loading…