Case study 03 · 2026

Mahalehمحله

A little piece of home, closer to home.

Role
Co-builder (with a collaborator)
Status
Pre-launch · private repository
Stack
React 19 · Vite · Firebase · Cloud Functions · Google Maps · Schema.org SEO
Mahaleh: Persian businesses in Southern California — every listing in English and Farsi.

Overview

Every listing in English and Farsi. Co-built with a collaborator: Google sign-in, an owner portal and an admin dashboard, with review stats that only the server is allowed to write.

Who it’s for. Persian-Americans and visitors looking for restaurants, markets, salons, doctors and other businesses, and the owners who manage their listings.

My role. Co-builder (with a collaborator).

Built with a collaborator in a shared repository with feature branches and pull requests: 54 of the 94 commits are mine.

Mine: the initial app and Firebase setup, business detail pages, sign-in and routing, the review system and badges, the submission moderation queue, Firestore security rules, admin authorization with Firebase custom claims, favorites, and the accessibility and launch-readiness pass.

My collaborator's: the business owner portal, the map page, the admin AI auto-fill Cloud Functions, admin search, and much of the visual redesign.

The interesting parts

  • Review stats and trust badges are written only by a Cloud Function trigger; Firestore rules deny them to every client, including administrators.
  • A business with no reviews has a rating of null, not zero — the structured data omits the rating rather than claim one.
  • Build-time SEO pass: sitemap and prerendered listing pages with per-route metadata and JSON-LD.

The problem

Southern California has a large Persian community, but its businesses are spread across social media pages, word of mouth and general-purpose directories that don't speak Farsi. Mahaleh puts them in one place, with every name in English and Farsi, and reviews people can trust.

The product

Reviews people can trust

  • Review statistics and trust badges (Mahaleh Verified and مامان‌پسند, “mom-approved”) are written only by a Cloud Function trigger. Firestore rules deny them to every client, administrators included.
  • A business with no reviews has a rating of null, not 0. The page and its structured data leave the rating out instead of showing a score nobody gave.
  • User submissions go through a moderation queue before they appear.

Access control

Administrators are identified by Firebase custom claims set on the server, not by a flag in a document the client could edit. App Check limits the backend to the real app.

Getting ready to launch

  • Named every control, trapped focus in dialogs, and gave each route its own title and metadata; the skip link was verified in a real browser.
  • Cleared every dependency advisory and fixed measured contrast failures.
  • Split the bundle and added a build-time SEO pass: sitemap and prerendered listing pages with JSON-LD.

Built & next

Built and working

  • Bilingual listings with English and Farsi names
  • Business pages with reviews, badges and a gallery
  • Google sign-in, favorites, moderation queue and admin tools

Not built yet

  • Public launch (pre-launch today; the repository is private)
  • A Google Maps billing error found on the final browser pass, recorded in the launch audit
  • A full Farsi interface: translation and right-to-left support exist in the code, but the interface is currently fixed to English

What I learned

  • Sharing a codebase means agreeing on who owns what and reviewing each other's branches before they land.
  • Trust rules belong in the database rules and on the server; the interface is only a view of them.