The problem
What locals know about a place — who lived in that house, what stood on that corner — lives in people's heads and scattered blogs, not on a map you can stand inside. The people who do dig it up, local historians and walking-tour guides, have no clean way to be paid for it without a platform sitting on their money.
Approach
- The map is the canvas: stories are short, photo-led and pinned to a coordinate, and reading one should take seconds.
- Premium access is decided in the database, not the client. A free account never receives premium rows, whatever the app asks for.
- Creators are paid through Stripe Connect direct charges: a purchase or tip settles on the creator's own connected account, and the platform takes an application fee without ever holding the funds.
- The webhook is the source of truth for a subscription, not the checkout redirect, and processing is idempotent so a replayed event changes nothing.
Architecture
- React 18 single-page app on Vite, with React Query for server state and Zustand for client state. It also runs as a PWA with offline support and inside a Capacitor shell.
- Supabase Postgres with row-level security on every table. Edge functions run behind shared withAuth, withAdminAuth and withContributorAuth wrappers that fail closed and report to Sentry centrally.
- MapLibre GL on self-hosted Protomaps tiles, read from object storage by HTTP range request with no tile token. The map engine sits in its own chunk that only map routes load.
- Typesense for full-text search, kept in sync from edge functions. Account deletion runs as a pg_cron and pg_net pipeline inside Postgres.
- A pre-deploy drift check blocks a release when the repository's migrations or edge-function code are newer than what production runs.
What shipped
- Map discovery with clustered markers, and story contribution with photos, pinned to a place and moderated before it goes live.
- A Contributor subscription with in-app cancellation, premium content purchases and tips paid directly to creators, and PayPal as a second payment rail.
- Location-triggered and push notifications, a progression layer of achievements, challenges and leaderboards, and multi-language support.
- The Lore Planet homepage: a turning globe where every lit point is a place with published stories.
- GDPR data export and account deletion with a grace period.
By the numbers
- Edge functions
- 96
- Row-level security policies
- 153
- Test files
- 220
Stack
React 18MapLibre GLSupabaseStripe ConnectTypesenseSentry
Building something like this?
Tell us what you're working on and we'll tell you honestly whether we're the right team for it.
Start a conversation