Personal & Business Life Management

Earmark / Gosha (گوشہ) — listen to what you read

An audio-first personal knowledge management PWA. Save an article, listen to it hands-free while commuting, capture timestamped voice notes, then search everything and resume exactly where you left off.

React 18 + Vite Dexie / IndexedDB Workbox PWA PHP 8 + MariaDB Live

Reading time and commute time don't overlap

Long articles worth reading pile up faster than there's ever a quiet hour to sit and read them — but there's a commute, a walk, or a drive most days where the eyes are busy but the ears aren't. Text-to-speech apps exist, but none of them treat the notes you'd take while listening — a thought, a reference to follow up on, a disagreement with the author — as first-class, timestamped, and searchable alongside the article itself.

The name is a small joke worth keeping: Gosha (گوشہ) is Urdu for a quiet corner, with gosh ("ear") hidden inside — the same pun as the project's original codename, Earmark.

Save it, listen to it, note it, find it again

Drop in a URL, PDF, or DOCX; Earmark parses it into a clean, sentence-segmented reading view and reads it aloud via on-device text-to-speech. Tap or speak a note at any point and it's saved with an exact timestamp into the article. Later, search runs across articles and notes together — and every article remembers exactly which sentence you were on, even across a refresh, a browser restart, or a dead phone.

Gosha library view — saved articles with resume progress rings, ready to continue listening

Local-first, with a resume model that actually survives real life

Local-first writes, always
Every write — a new article, a note, reading progress — lands in IndexedDB first via a repo layer, then a durable sync queue drains it to the server. Reading, listening, and search all run with zero network required.
Sentence-level resume, deliberately
Articles are pre-segmented into sentences at import time. The player persists the current sentence index on every advance and pause — not the unreliable word-boundary event or elapsed milliseconds — so resume survives refresh, reboot, and lost signal.
A swappable player engine
Playback sits behind one PlayerEngine interface. V1 ships on-device speech synthesis; a future pre-generated-audio engine can slot in behind the same interface with no schema or UI change.
SSRF-guarded importer
The URL importer fetches through a server-side proxy that blocks private IP ranges, restricts to http/https, and caps response size — parsing itself still happens client-side.
Built around iOS's real limits
iOS Safari pauses speech synthesis when the screen locks and doesn't support Background Sync — handled explicitly (not bugs) via a foreground/visibility/online-event sync strategy and a clean pause-and-persist when the page is hidden.
JWT in HttpOnly cookies
The auth token is never readable by JS; a separate CSRF cookie powers a double-submit token requirement on every unsafe request, alongside per-IP rate limiting on auth and fetch endpoints.

Under the hood

FrontendReact 18 + Vite + Tailwind + Dexie (IndexedDB), Workbox PWA
BackendPHP 8 REST API + MariaDB, no Composer dependency
AuthJWT in HttpOnly cookies + double-submit CSRF token
HostingHostinger shared hosting

Where it stands

Live and in daily personal use, currently mid-rebrand from "Earmark" to "Gosha" (the internal identifiers — repo folder, database name, cookie prefix — deliberately keep the old codename so nothing breaks).

← PreviousNexus Finance Next case studyBayaz →

Need a tool built around how people actually use it?

If a workflow needs to survive real-world constraints — spotty networks, distracted attention, mobile-only use — that's the kind of design problem I like solving.