Skip to content

Real estate · React Native

Moonrock

Rent, leases and maintenance for tenants and landlords, on one mobile app.

Product
Moonrock PM — landlord and tenant property management
Role
Developer and team lead, Dixeam
Scope
React Native app for iOS and Android, Stripe rent collection, maintenance workflow
Moonrock case study cover

The tension

Rent, leases and repairs are three conversations between the same two people.

What was happening

Landlords and tenants were running a tenancy across email, phone calls and paper, so the record of what was agreed depended on who was asked.

What changed the brief

The two sides need different views of the same tenancy, not different products. Once that was the frame, one app with two roles replaced the idea of two apps.

Success looked like

Rent collected on schedule without a reminder, and a maintenance request that both sides can see the state of.

The constraint

Recurring money and a subscription both run through the same app, on two platforms, for users who will not tolerate a second tool.

The product story

One tenancy, two roles.

The relationship

Simplifying the landlord-tenant relationship.

The landing view frames the product as the relationship rather than as property software, because that is the problem both sides recognise.

Moonrock PM — landing view
Both sides, one product.Sign up leads into a role rather than into a separate app.

Narrow first

This is a phone product.

The marketing site reflows to the width the app itself is used at, keeping signup and pricing reachable throughout.

Moonrock PM — mobile view
Mobile-first by construction.The site matches the product rather than a desktop-first template.

The offer

One subscription, both platforms.

Pricing is a single monthly plan, presented alongside the app availability so the commitment is legible before signup.

Moonrock PM — full page
Available on iOS and Android.One React Native codebase serving both stores.

Walkthrough

The product in motion

Recorded from the live site.

The trust test

The happy path is only half the product.

A rent payment fails

Payment state is separate from tenancy state, so a failed charge is a recoverable payment rather than a tenancy that looks broken to either side.

The tenant has no signal

The app is written against an offline-tolerant read path, so viewing a lease or a request does not require connectivity that a basement flat may not have.

Both sides act on one request

State transitions are server-owned, so a stale client cannot close a maintenance request the other side has already reopened.

The decisions

Three moves carried the story.

One codebase, two roles

React Native across iOS and Android, with role deciding the view rather than the binary, so a tenancy has one implementation and cannot drift between platforms or sides.

Make maintenance a tracked state

Requests move through explicit states rather than living as messages, so both sides can see where a repair is without reconstructing it from a thread.

Let Stripe own the recurring money

Rent collection runs on Stripe subscriptions rather than a scheduler of our own, so retries, failures and receipts are handled by the system built for them.

What I would test next

Maintenance states were modelled from the landlord's process. Whether tenants read them the same way is the thing worth watching.