Currently building: himasjid · Week 16
Perth, AU · GMT+8 00:00:00
Back to work
Client: Self-initiated· Role: Solo builder· Timeframe: Jan 2026 — Present

himasjid.

Most mosques use the TV on the wall to show prayer times, and nothing else. himasjid turns the same TV into a communications channel: announcements, images, videos, scheduled playlists, and a flyer for the WhatsApp group. Free forever for the core. Built solo, on nights and weekends.

Status

Live in 2 Perth mosques as a closed pilot · himasjid.com ↗ · free forever for the core, pro tier wired but unmarketed

Stack

Next.js 16 · Supabase · Tailwind 4 · Workbox · Stripe

Speak More Through Your Masjid TV

Show announcements, images, videos, and many more using your phone from anywhere — all updating instantly.

Get Started — It's Free
See Demo
Next Adhan
Maghrib
00
Hrs
:
42
Min
:
18
Sec
17:15
Tue, Feb 3, 2026
www.himasjid.com
Fajr
05:30
05:45
Sunrise
06:45
Dhuhr
12:30
12:45
Asr
15:45
16:00
Maghrib
18:15
18:20
Isha
19:30
19:45
§ 01 — Context

Most mosques already have a TV. It sits above the main entrance or near the imam's podium, it has been there for years, and almost all of the time it is showing the same thing: a prayer-time schedule. That is the only job anyone has ever asked it to do, because no one has built the tools that would let it do anything else.

hiMasjid is the layer that lets the same TV do more. The display loads in a browser, logs into the mosque account once, and from then on the screen is driven by a playlist the admins edit from their phones. Prayer times still update on their own, but now the same screen also runs announcements, images, videos, flyers, and time-of-day-aware content, Ramadhan reminders, Friday Jumu'ah cards, the iftar notice this evening. Nothing about the hardware changes. The TV that was only doing one thing starts doing five.

I started it as a side project in January 2026. The honest reason is that I wanted to build an end-to-end SaaS from schema to Stripe on my own time, and I wanted the problem domain to be one I actually cared about rather than a SaaS-boilerplate clone. It is not my day job and it is not funded.

The 5 prayer times are the scheduling system. Volunteer admins don’t think in 14:00, they think in Dhuhr.
§ 02 — Constraints

A solo project with real users has a particular constraint shape. There is no team to delegate to, but the thing has to actually work for people who are not you, which means the shortcuts that are fine in a personal tool are not fine here. Multi-tenancy had to be real from the first migration because there was never going to be a rewrite. And because the business model is "free forever for the core," the infrastructure had to fit inside the free tier of every service it touches, otherwise the project funds itself out of existence.

Team size
One. Nights and weekends.
Budget
$0/month. Free-tier Supabase, free-tier hosting, free-tier everything. The pricing model is a constraint on the architecture, not a thing bolted on after.
Pricing
Free forever for the core (prayer times, basic playlists, single display). Pro tier, unlimited slides & playlists, realtime emergency override, team invitations, wired through Stripe but unmarketed while the free product is still being made undeniable.
Tenancy
Multi-tenant from day one. Isolation per mosque enforced at the database, not in the route layer.
Display hardware
Whatever TV is already in the wall. Smart-TV browsers from 2018, cheap Android sticks, the occasional iPad on a swing arm. Unreliable mosque wifi.
Users
Mosque admins on phones. Volunteers, not sysadmins. They get to himasjid in the gap between work and the next prayer.
§ 03 — Architecture

The interesting decision was not the framework. Next.js on the App Router was a foregone conclusion, I wanted server actions for mutations and a single codebase for the marketing pages, the admin app, and the display endpoint. The interesting decisions were three: where to put the tenancy boundary, what the scheduling primitive should be, and how to keep the display alive when the wifi is not.

Tenancy lives in Postgres. Every table that holds mosque-scoped data has a masjid_id column and a row-level security policy that filters on the caller's membership. Route handlers and server actions cannot leak data across tenants even if I write the query wrong, because the database refuses to return rows the caller does not own. Supabase gives me that policy engine, auth, Postgres, and Realtime in a single managed service, and stays inside the free tier at the size we are at.

The scheduling primitive is not the clock, it is the prayer. Volunteer admins do not want to think in "14:00 to 16:00." They want to say "show this from Dhuhr to Asr," and have the system handle the timezone-aware translation behind the scenes. So the scheduler stores ranges as prayer-name pairs and resolves them to wall-clock windows at display time, against that mosque's timezone and that day's prayer times. The 5 prayer times are already the most universally-understood schedule in the building; building on top of them instead of around them is the design choice that makes the rest of the product feel obvious.

The display side is a Workbox-backed PWA. It caches its own assets and the current playlist to IndexedDB, so the screen keeps playing the last-known loop when the mosque wifi drops, which happens often enough that it had to be designed for, not patched around. When an admin edits the playlist, a Supabase Realtime broadcast tells the subscribing displays to pull the new version. The pro-tier emergency override uses the same channel with a higher-priority message type, a funeral notice, a changed iftar time, and lands on every display in the mosque within a second of an admin tapping "broadcast."

CLIENTS Admin app MOBILE · DESKTOP Display PWA OFFLINE-FIRST · WORKBOX Marketing EN · ID · MS APP Next.js 16 · App Router SERVER ACTIONS · RSC DATA · AUTH · RT Stripe BILLING · FREEMIUM Supabase POSTGRES · RLS · AUTH · RT Resend TRANSACTIONAL MAIL Upstash RATE LIMIT LIME = REALTIME / TENANCY BOUNDARY
Fig. 01 — System diagram. RLS at the database is the tenancy spine; every read and write goes through it. Displays subscribe to Realtime for playlist updates and emergency overrides.
§ 04 — Stack & reasoning
Next.js 16
App Router colocates marketing, admin, and display endpoints. Server actions avoid a separate API layer I’d have to maintain alone.
Supabase
Row-level security is the tenancy boundary. Auth, Postgres, and Realtime in one service so I’m never on call for infrastructure I didn’t choose to operate. Stays inside the free tier at the size we’re at, which is why the “free forever” promise is sustainable rather than aspirational.
Tailwind 4 · shadcn/ui
Component primitives I can actually read. No design system maintenance burden on a solo project.
TanStack Query
Optimistic updates for playlist reordering and slide drag-and-drop where it matters; server actions everywhere else.
Workbox · PWA
The thing that makes the display product viable. Caches assets and the current playlist to IndexedDB so the screen keeps playing through wifi drops, which is a feature on mosque networks, not an edge case.
Supabase Realtime
Powers live playlist propagation and the pro-tier emergency override. Edits land on every display in the mosque within a second of the admin tapping “broadcast.”
Prayer-time scheduling
The domain primitive. Schedules are stored as prayer-name pairs (Dhuhr to Asr) and resolved to wall-clock windows at display time against each mosque's timezone. The 5 prayer times already are the schedule volunteer admins know, building on top of them instead of around them is the design choice that makes the rest of the product feel obvious.
Flyer generator
One input, two outputs. Admin sets prayer times once in the dashboard; the same data drives both the TV display and a downloadable flyer image for the mosque WhatsApp group. Most communities already share prayer-time graphics in chat, himasjid generates the graphic for free, with the same numbers that just went up on the TV.
Stripe
Pro-tier billing for the small number of mosques who need unlimited playlists, realtime emergency override, or team invitations. Wired in but unmarketed, the priority is the free product first.
Vitest · Testing Library
Colocated tests, mostly for the security-critical paths, redirect sanitization, realtime auth, RLS policies, prayer-time scheduling math across timezones. Catches the class of bug I can’t rely on a second reviewer to catch.
§ 05 — Status

hiMasjid is live in 2 Perth mosques as a closed pilot, admins I know personally, on screens I have walked into the building to look at. Displays drive themselves, prayer times update on their own, admins edit playlists and push flyers from their phones in the gap between work and Maghrib. The pro tier is wired but unmarketed; the priority is making the free product undeniable before opening a sales surface that would only distract from it.

The visible weekly rhythm is hardware. Mosque TVs are not a single platform, they are a long tail of screen sizes (32" in the office, 65" in the prayer hall), browser engines (Chromium 2018 on a smart TV that will not update, Chrome 130 on a $40 Android stick, Safari on the imam's old iPad), and connectivity (carpark wifi that drops every 20 minutes). Every week of real use surfaces some new combination, a font that does not hint at 65", a CSS feature the 2018 build does not know about, a Realtime channel that needs to back off and retry instead of giving up. Fixed in turn. There will be another one next week.

§ 06 — Reflection

The thing I got right was refusing to treat it as a toy. RLS from the first migration, Vitest from the first component, a changelog from the first release. Side projects die when you tell yourself you will add the boring parts later, so the boring parts went in first, and the fun parts got to ride on top of them. That is why I could ship a multi-tenant architecture on nights and weekends without the kind of incident that would have ended the project. The other thing I got right by accident was free-forever: when the infrastructure cost is $0/month, the "sustainability" conversation never happens, and the product gets to be judged on whether it is good rather than on whether the pricing makes sense.

The thing I would do differently is commit to a non-browser TV runtime sooner, an Android TV build, a Tizen app, a small Electron-style shell, anything I control. The browser-on-TV assumption has been the single biggest source of friction. Some screens run a Chromium fork from 2018 that cannot be updated; others cannot install a modern browser at all. Every screen-size and browser-quirk fix I have shipped has been a workaround for a decision I made on day one, "just use the TV's browser", that looked like the simple choice and turned out to be the long one.

Next case study

Caretbox

An open-source developer knowledge hub. Also a showcase of how I write code when I’m the only reviewer.