Skip to content
Go back

Constraint as a Feature: Designing an “Anti-Canvas” for Sacred Text

Most design tools optimize for flexibility: drag anything anywhere, resize freely, experiment endlessly.

When dealing with sacred text, that kind of flexibility is often a bug. If you let a user drag a verse manually, they might accidentally misalign the basmalah, obscure a diacritic, or break a semantic line pause.

I took the opposite approach and built a deliberately constrained tool — an “Anti-Canvas” — which later became AyatFlow.

Here is why I built it, the technical hurdles of Arabic typography, and the constraints I enforced to make it work.

The Problem: Text Shaping vs. Text Rendering

Most web developers assume rendering text is the browser’s job. You throw a string into a <div>, set direction: rtl, and walk away.

But when you need to generate a high-fidelity image for export, you can’t rely on the client’s browser rendering engine. You need to render it on the server to ensure consistency across devices and to generate dynamic Open Graph (OG) meta-images.

This introduces the nightmare of Arabic Text Shaping.

Unlike Latin script, Arabic characters change shape based on their position (initial, medial, final, or isolated). A standard graphics library often treats characters as individual blocks. If you just draw the string s-a-l-a-m, you get disjointed letters.

To render this correctly on the backend, you need an engine that handles:

The Solution: The Rails + Go Stack

I skipped the popular “Next.js + Canvas” route. I didn’t want client-side canvas implementations behaving differently on iOS vs. Android.

I chose a hybrid stack: Rails for the logic, Go for the rendering.

I have previously written about the architectural decision to use Go as a sidecar. But the reason for this split wasn’t just performance—it was typography.

Why Go? I used Go to orchestrate a headless browser environment (via chromedp). Browsers have the most battle-tested text shaping engines in the world. By driving a controlled instance on the server, I get the best of both worlds: the strict shaping correctness of a browser engine, with the reliable performance control of a Go backend.

The Anti-Canvas: Encoding Respect Through Constraints

As an engineer, the temptation is to build “The Platform.” I fought that urge. To ship this in two weeks and guarantee correctness, I applied aggressive constraints.

1. Rigid Layout Engine (The “Stack” Model)

Instead of absolute positioning (the “Canvas” model), the rendering engine uses a strict vertical stack:

The user cannot “move” these elements. They can only style them. This guarantees that no matter what screen size or font size is selected, the visual hierarchy and the dignity of the text remain unbreakable.

2. Statelessness by Default (No Auth)

I treated the entire application as a pure function: Image = f(Surah, Ayah, Theme).

Because the output is deterministic, I didn’t need user accounts or a database of “saved designs.”

3. Curated Typography

I blocked user-uploaded fonts. Arabic typography on the web is fragile; a font that looks good in Word might have broken ligatures in a browser. I manually vetted only open-source fonts known to have complete Quranic glyph sets.

The Result

AyatFlow isn’t trying to replace Photoshop. It is a specialized utility for a specific niche that demands high accuracy.

It accepts the constraints of Arabic morphology and Quranic structure, and builds a rendering pipeline around them. It’s a simple tool, built on a boring stack, designed to do one specific thing without error.

AyatFlow is one concrete expression of this idea.

If this saved you time or helped you reason about a trade-off, feel free to reply on Twitter or email me .


Share this post on:

Previous Post
Escaping the AMS Trap: How We Benchmarked Our Way to Alba
Next Post
Rails Removed Email Obfuscation. Here's How I Brought It Back with Stimulus