Haitham AssoliRead this page in Arabicاقرأ هذه الصفحة بالإنجليزية
All projects

ShippedMobileSince 2025

Malabji

Find a pitch, find players, book it, play.

Malabji lets you search nearby football pitches, see available slots, and reserve one. Team search, challenges, and tournaments help players fill the match.

Malabji: Find a pitch, find players, book it, play.
Role
Founder: product, design and full engineering
Year
Since 2025
Status
Shipped
Built with
  • React Native
  • Expo Router
  • TypeScript
  • Supabase
  • Zustand
  • React Query
  • React Hook Form
  • Zod
  • Reanimated
  • Skia
  • Restyle
  • In-App Purchases
  • Deep Linking
  • Calendars
  • Push Notifications

Football pitch bookings in Jordan run through phone calls and WhatsApp. You ask a ground about Thursday, gather players, then find the slot has gone; payment happens in cash on arrival. You also need nine other players.

Malabji handles both. The booking side is a live availability calendar per pitch with instant reservation. The social side lets you look for a team, challenge another one, and run or join a tournament, plus a directory of sports academies.

I founded it and built all of it: the Expo client for both stores, the Supabase backend, the store releases, and the support that follows a real product.

Challenges

  • Never sell the same hour twice

    The snag

    Two people opening the same 7pm slot at the same time is not a rare edge case on a Thursday evening. It is the normal load. Checking availability and then writing the booking is two steps, and anything can happen between them.

    What I did

    Availability is never trusted from the client. The reservation is a single server-side transaction with a uniqueness constraint on (pitch, time range); the loser of a race gets a clean 'just taken' state and the calendar refreshes under them rather than a failed payment.

  • In-app purchases on two stores with different rules

    The snag

    Apple and Google disagree on receipts, on what a restore means, and on what they will approve. A purchase that succeeds on the device but never reaches the backend is the worst possible bug in a paid product.

    What I did

    Entitlement is decided on the server from a verified receipt, never from the client's word. The client re-validates on launch and after every restore, so a purchase interrupted mid-flight reconciles itself the next time the app opens.

  • Calendar and notifications that respect the user

    The snag

    A booking is useless if the player forgets it. But asking for calendar and notification permission on first launch, before the app has earned anything, gets both denied.

    What I did

    Permissions are asked at the moment they pay off. The calendar prompt appears right after a successful booking, not before. Reminders are scheduled locally so they still fire if the device is offline.

  • Deep links that survive an install

    The snag

    Growth happens when someone shares a match invite in a group chat. If the tap opens a store page and the invite is lost after installing, the whole loop breaks.

    What I did

    Invite links carry their payload through the install, so a new user lands on the actual match after opening the app for the first time, not on a generic home screen.

Results

  • Live on the App Store and Google Play.
  • Bookings, team search, challenges and tournaments in one app.
  • Built and operated solo, from schema to store listing.

Screens

Next design — SignalSee all 14