创始人、设计师与移动开发者

客户

个人产品 — 已上线 App Store 与 Google Play

角色

创始人、设计师与移动开发者

技术栈

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

日期

2026

01

挑战

咖啡发现应用要么是毫无灵魂的目录,要么是封闭的点评孤岛。我想围绕巴黎的咖啡文化打造一个真正的社交产品——关注、动态、共享清单、Top 3 排名——并独自完成所有环节:设计、移动开发、后端、推送通知、商店上架和数据分析。难点在于产品覆盖面:登录(Apple/Google)、带聚合的交互地图、实时动态、审核工具、深度链接以及能促进转化的访客模式。

02

解决方案

采用 React Native + Expo(通过 Expo Router 实现文件路由)开发,后端基于 Supabase:Postgres 行级安全、存储、RPC 和认证触发器。React Query 负责动态、点评、清单和关注的缓存与乐观更新。地图通过 supercluster 聚合数百家咖啡馆,个人主页展示 Top 3 领奖台和可分享清单,权益系统以滑动领取的方式回馈早期会员。通过 EAS 发布至双商店,接入 PostHog 和 Sentry,支持法语/英语,并配有通用链接和每家咖啡馆的公开网页。

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 的地图聚合 hook — 仅在咖啡馆列表变化时重建索引,地图移动只触发低成本的 bbox 重新查询

Gallery image 1
Gallery image 2
Gallery image 3
Gallery image 4
Gallery image 5
Gallery image 6

下一个项目

Quitio

SaaS / 开发