03 / 2026
Hazzoura
An Arabic-first smart board for teachers, built solo end to end — a custom DOM/SVG board renderer, PDFs and videos on the page, six class tools, and autosave that never loses a stroke.
RoleFounder & Full-Stack Engineer
Timeline2026 – present

Overview
Hazzoura (حزورة) is my own product, live and used by teachers: one Arabic-first place for the whole lesson. Teachers in Arabic classrooms run a single lesson across a PDF reader, a video site, a timer site, a name picker and a quiz site, mostly in English. Hazzoura puts all of it on one board in the browser — writing and drawing, PDFs and worksheets, images, videos, embedded websites, and six class tools — free to start, with paid plans on the way, nothing to install, light on school Wi-Fi. I designed and built both halves solo: a Next.js 16 frontend deployed on Cloudflare Workers, and an Express 5 + MongoDB API with media on Cloudflare R2.
The challenge
A teaching board has to feel as immediate as a pen on paper, on a school laptop over weak Wi-Fi, in front of thirty kids. Strokes can't lag, a save can't be lost when the connection drops mid-lesson, and a PDF has to become something you can write on without a server-side renderer. Everything had to be right-to-left from the first pixel — Arabic digits, mirrored chrome, RTL keyboard navigation — while the board itself stays neutral so ink reads the same on a projector in either language.
What I did
- Wrote the board renderer from scratch in DOM/SVG with perfect-freehand — no Konva, Fabric or tldraw — with pen, highlighter, shapes, eraser, laser, select/move/resize/rotate, zoom, pan and pinch, and undo/redo built on a command stack
- Built pen smoothing and an even-thickness mode that are baked into the stored points, so writing with a mouse or a finger looks clean without adding fields to the saved model
- Engineered autosave for flaky school networks — debounced saves, one request in flight, an IndexedDB backup before every PUT, exponential backoff on failure, and version-checked saves that return 409 instead of ever overwriting newer work
- Imported PDFs entirely in the browser with pdf.js — each page rendered and uploaded as an image, either as separate board pages to write on or as one document you scroll inside its box
- Shipped six live class widgets on the board — timer, stopwatch, name-picker wheel, traffic light, dice and a group maker — plus YouTube, Vimeo and Google Drive videos and embedded websites
- Built a full-screen presentation mode for screen-sharing to the class — auto-hiding toolbar, page keys, and a screen wake lock so the projector never sleeps mid-lesson
- Designed the API as a product — Express 5 + MongoDB, a strict Zod schema validating every board save down to each object type, refresh-token rotation with replay detection, Google sign-in, rate limits, CSRF origin checks, and Swagger docs
- Handled media like it matters — uploads typed by sniffing the real bytes (never the extension), stored on R2, shared by reference across copies and templates, ref-counted, and purged once nothing uses them
- Made embeds safe — an SSRF-guarded server fetch inspects X-Frame-Options and frame-ancestors before a site is embedded, and falls back to a link card when it can't be framed
- Built a design system with its own living style guide — semantic tokens, a paper-cut sticker look, light and dark themes, reduced-motion paths, and lint rules that ban physical CSS so every screen works in RTL and LTR
Deep dive
A board renderer, not a library
The board is plain DOM and SVG with perfect-freehand for ink — a deliberate choice over canvas libraries so text, images, videos and widgets live on the same page as strokes and stay accessible. Hit-testing, resize and rotate are pure geometry functions, every edit is an undoable command, and the same renderer draws the editor, the dashboard thumbnails, and the live sample board on the landing page — the one with a felt eraser you can drag across it.
Autosave you can trust in a classroom
Every change restarts a 1.5s timer. When it fires, the snapshot is written to IndexedDB first, then PUT with the board's version. A 200 bumps the version and drops the backup; a network error retries with backoff up to a minute; a 409 stops saving for good and offers a reload, because silently overwriting newer work is worse than asking. Edits made mid-save queue exactly one follow-up save, so there is never more than one request in flight.
PDFs without a PDF server
Object storage has no page transforms, so the browser does the work: pdf.js (the legacy build, because school machines run old browsers) renders each page, the image is uploaded, and the teacher picks how it lands — one board page per PDF page to write on, or a single document object that scrolls inside its box. The backend validates both shapes and counts every page image so shared media is never purged while a board still uses it.
Arabic first, not translated
Arabic is the default locale and the source of every string; English is an equal second. Layout uses logical CSS only, enforced by a custom ESLint rule. Directional icons mirror, clocks and media controls don't. Numbers render in Arabic-Indic digits through a formatting hook, Radix components give RTL arrow-key navigation, and Arabic text gets its own type sizes and line heights. Search on the backend normalizes Arabic — diacritics, tatweel, letter variants — so a teacher finds a board however they typed its title.
The product around the board
Everything a live product needs beyond the editor: email and Google auth, a board dashboard with trash, templates and share links, a contact flow, honest privacy and terms pages that describe what the code actually does, per-page SEO with hreflang and JSON-LD, an llms.txt, and first-party analytics with an admin dashboard. Accounts already carry a plan, so paid plans can land without a migration. The API runs a unit suite and an end-to-end suite against real MongoDB and S3-compatible storage.
The result
A live product at hazzoura.com that teachers use today in the browser, free to start, with pricing plans coming next — designed, built and shipped solo across frontend, backend, infrastructure and copy. Where EgyStay and Lesoll show production work inside a company, Hazzoura shows what I build when I own the whole thing: the product idea, the renderer, the API and the brand.
Written up from this project
- Next.js Localization: i18n Routing, Translations, a Language Switcher, and the RTL U-TurnNext.js localization in the App Router: [lang] i18n routing, typed translations, a language switcher, Arabic RTL, and hreflang — with or without next-intl.
- Technical SEO in Next.js: Crawlability, Sitemaps, Canonicals, and JSON-LDMake a Next.js App Router site crawlable: server-rendered HTML, sitemap.ts, robots.ts, canonical URLs, the Metadata API, and XSS-safe JSON-LD.