Founder, Designer & Mobile Developer

Client

Personal Product — live on App Store & Google Play

Role

Founder, Designer & Mobile Developer

Stack

React Native, Expo, TypeScript, Supabase, React Query, PostHog

Date

2026

Website

Visit site

01

The Challenge

Coffee discovery apps are either soulless directories or closed review silos. I wanted to build a real social product — follows, feeds, shared lists, top-3 rankings — around café culture in Paris, and ship it solo: design, mobile development, backend, push notifications, store submissions and analytics. The hard part was the full product surface: auth (Apple/Google), interactive map with clustering, real-time feed, moderation tools, deep links, and a guest mode that converts.

02

The Solution

Built with React Native + Expo (file-based routing via Expo Router) on a Supabase backend: Postgres with row-level security, storage, RPCs and auth triggers. React Query handles caching and optimistic updates across the feed, reviews, lists and follows. The map clusters hundreds of cafés with supercluster, profiles feature top-3 podiums and shareable lists, and a perks system rewards early members with swipe-to-claim offers. Shipped to both stores with EAS, instrumented with PostHog and Sentry, localized FR/EN, with universal links and a public web page per café.

typescript
// Map clustering — rebuild index only when cafés change,
// re-query clusters when the visible region moves
export function useClusters({ cafes, region, radius = 60 }: Options) {
  const index = useMemo(() => {
    if (!cafes?.length) return null;
    const sc = new Supercluster<PointProps, ClusterProps>({
      radius,
      maxZoom: 16,
      minPoints: 3,
    });
    sc.load(
      cafes.map((cafe) => ({
        type: "Feature",
        geometry: {
          type: "Point",
          coordinates: [cafe.longitude, cafe.latitude],
        },
        properties: { cafe },
      }))
    );
    return sc;
  }, [cafes, radius]);

  const clusters = useMemo(() => {
    if (!index || !region) return [];
    const zoom = Math.round(Math.log2(360 / region.latitudeDelta));
    return index.getClusters(regionToBbox(region), zoom);
  }, [index, region]);

  return { clusters, index };
}

Supercluster-based map clustering hook — the index is only rebuilt when the café list changes, while region moves trigger a cheap bbox re-query

Measured results

iOS · Android

Live on both stores

100

SEO — Lighthouse

Mobile audit, July 2026 (sipclub.app)

100

Best practices — Lighthouse

95

Accessibility — Lighthouse

Gallery image 1
Gallery image 2
Gallery image 3
Gallery image 4
Gallery image 5
Gallery image 6
Estevan took Sip Club from sketch to the app stores: design, development, backend — he handled it all. Seeing the app in our members' hands, exactly as we imagined it, says everything about how he works.
Adèle // Co-founder of Sip Club

Next Project

Quitio

SaaS / Development