Machine-translated draft — terminology + flow still being reviewed.

Keel — 5 first-class native modules for China

The most common pain point for domestic RN developers: WeChat / Alipay / Amap / Jiguang / Umeng either don’t exist on Expo or have community implementations with uneven quality. Keel maintains these 5 as official first-class modules — install with one @keel-ai/<name> npm line + standard autolink, no community piecing-together required.

This doc locks the spec: npm package names, JS surface, native implementation strategy, dependencies, limits.


General conventions

  • Package name: @keel-ai/<module> (official) or keel-module-<name> (community); standard npm + autolink
  • JS surface: default export + flat methods; stay Promise-based + 1:1 mapped to the native SDK
  • Native integration: iOS pulls in the official SDK via CocoaPods; Android via Maven
  • Errors: all Promise rejects throw KeelError (with code: string + message), aligned with RN standard
  • Types: each @keel-ai/<module> package ships .d.ts; editors get full autocomplete
  • Sample code: every module README contains a minimal demo

1. @keel-ai/wechat — WeChat Pay + Login + Share

Capabilities

FeatureMethodNotes
Paypay(orderInfo)Pulls up WeChat app for payment; returns { status, transactionId }
Sign-insignIn()OAuth code → exchange for access_token on your backend
ShareshareText / shareImage / shareLink / shareMiniProgramShare to chat / moments / favorites
Open Mini ProgramlaunchMiniProgram(appId, path)Launch a WeChat mini program from your RN app

Native dependencies

  • iOS: pod 'WechatOpenSDK_XCFramework' + URL scheme config
  • Android: implementation 'com.tencent.mm.opensdk:wechat-sdk-android'

Merchant requirements

  • Must have a WeChat Open Platform account + mobile app appId
  • Payment also requires a merchant ID (WeChat Pay mch_id) + API key
  • Keel does NOT manage merchant credentials; users pass appId + universalLink (iOS) on init

JS API (draft)

import { wechat } from '@keel-ai/wechat';

await wechat.init({ appId: 'wx...', universalLink: 'https://...' });

// Pay
const result = await wechat.pay({
  partnerId: 'merchant ID',
  prepayId: 'prepay_id returned by backend pre-order',
  nonceStr: '...',
  timestamp: ...,
  package: 'Sign=WXPay',
  sign: '...',
});

// Sign-in
const { code } = await wechat.signIn({ scope: 'snsapi_userinfo' });
// Use code to exchange for a token via your own backend

Limitations

  • The WeChat SDK must be called on the main thread — @keel-ai/wechat wraps this internally; callers don’t worry
  • On Android, the app signing fingerprint must match what’s registered on the Open Platform — Keel CLI keel doctor verifies

2. @keel-ai/alipay — Alipay Pay + Real-name auth + Mini Program

Capabilities

FeatureMethodNotes
Paypay(orderString)Pulls up Alipay app for payment
Real-name authrealName(certifyId)Ant Financial Cloud face verification
Launch Mini ProgramlaunchMiniProgram(appId)Open an Alipay mini program
Auth loginsignIn(authInfo)Get auth_code → exchange for user_id on backend

Native dependencies

  • iOS: pod 'AlipaySDK-iOS'
  • Android: implementation 'com.alipay.sdk:alipaysdk-android'

Merchant requirements

  • Alipay Open Platform + app appId
  • Payment requires an RSA2 key pair (public key uploaded to Alipay, private key held by backend)
  • Same as WeChat — Keel does NOT manage credentials

JS API (draft)

import { alipay } from '@keel-ai/alipay';

const orderString = '<orderString assembled by backend>';
const result = await alipay.pay(orderString);
// result: { resultStatus: '9000' | '6001' | ..., result: '...' }

3. @keel-ai/amap — Amap (Gaode) maps + location + routing + geo

Capabilities

FeatureMethod / ComponentNotes
Map component<AMapView />RN component, renders the native map
LocationgetCurrentLocation() / watchLocation(cb)GPS + network hybrid positioning
Geocodinggeocode(address) / reverseGeocode(lat, lng)Address ↔ coordinates
RoutingroutePlan({ origin, dest, mode })Walking / cycling / driving / transit
POI searchsearchPOI(keyword, region)Search restaurants / gas stations etc.
Distancedistance(p1, p2)Straight-line distance

Native dependencies

  • iOS: pod 'AMap3DMap' + pod 'AMapLocation' + pod 'AMapSearch'
  • Android: implementation 'com.amap.api:3dmap' + 'location' + 'search'

App keys

  • Apply on the Amap open platform for a web-service key + iOS / Android client keys (each platform has its own key)
  • init({ iosKey, androidKey, webServiceKey }) — Keel CLI reads from keel.json

JS API (draft)

import { amap, AMapView } from '@keel-ai/amap';

await amap.init({ iosKey, androidKey, webServiceKey });

// Component usage
<AMapView
  style={{ flex: 1 }}
  center={{ lat: 39.91, lng: 116.39 }}
  zoom={14}
  markers={[{ position: ..., title: ... }]}
/>;

// Imperative API
const loc = await amap.getCurrentLocation({ accuracy: 'high' });
const route = await amap.routePlan({ origin: loc, dest: ..., mode: 'driving' });

Alternatives

China also has Baidu Maps / Tencent Maps; by market share (maps: Baidu + Amap take ~90%), making one first-class is enough. Baidu users go through community modules (not Keel first-class).


4. @keel-ai/push — Push notifications (Jiguang + Getui dual backend)

Abstract layer + two backends

@keel-ai/push is an abstract interface with two native backends below:

@keel-ai/push                       ← abstract interface (small, ~300 LoC)

   ├─→ @keel-ai/push-jpush          ← Jiguang backend (planned)
   └─→ @keel-ai/push-getui          ← Getui backend (planned)

Users pick one at init time and don’t run both simultaneously — to avoid double notifications across vendor channels.

import { push } from '@keel-ai/push';

await push.init({ provider: 'jpush', appKey: '...' });   // or 'getui'
const id = await push.register();
await push.setAlias('user_123');

Why not just Jiguang

  • Jiguang: works out of the box; the free tier suits small/medium developers; auto-adapts to Huawei / Xiaomi / OPPO / vivo / FCM vendor channels; default backend
  • Getui: more stable performance, enterprise SLA, long-link heartbeat more battery-friendly; choice for enterprise users
  • Vendor direct integration (Huawei / Xiaomi / OPPO / vivo each): 5× the work; only top apps willing to do it; out of scope for now

Capabilities

FeatureMethodNotes
Registerregister()Get registrationId (push target)
Set alias / tagsetAlias(alias) / addTags([...])Server pushes by alias / tag
Listen for notificationsonNotificationOpened(cb) / onMessageReceived(cb)Different callbacks for in-app / app-closed cases
BadgesetBadge(num)iOS badge
Clear notificationsclearAllNotifications()Clears the notification center

Native dependencies

  • iOS: pod 'JPush'
  • Android: implementation 'cn.jiguang.sdk:jpush'
  • Vendor channels (auto-managed by Jiguang): Huawei / Xiaomi / OPPO / vivo / FCM each

App keys

Apply on the Jiguang Portal for AppKey + Master Secret (backend uses the latter). Keel CLI configures appKey in keel.json.

JS API (draft)

import { jpush } from '@keel-ai/jpush';

await jpush.init({ appKey: '...', isProduction: true });
const id = await jpush.register();          // Backend records the registrationId
await jpush.setAlias('user_123');

jpush.onNotificationOpened((noti) => {
  // User tapped a notification; handle the deep link
});

Limitations

  • iOS APNs cert / p8 key must be uploaded to the Jiguang Portal (one-time; Keel provides doctor verification)
  • Android push permission requires explicit grant on OS 13+; the Keel SDK auto-prompts

5. @keel-ai/umeng — Umeng analytics + backup push

Capabilities

FeatureMethodNotes
Track eventtrack(event, props)Custom events + dimensions
Page trackingpageEnter(name) / pageLeave(name)RN screen transitions
User identitysignIn(userId) / signOut()Associate users
CrashreportCrash(error)JS Error → Umeng crash report
Backup pushpushReceiver(handler)Backup channel when Jiguang / Getui aren’t installed

Native dependencies

  • iOS: pod 'UMCommon' + 'UMAnalytics' + 'UMCrash' (push: 'UMPush')
  • Android: implementation 'com.umeng.umsdk:common' + per-module

App keys

Apply on Umeng console for AppKey + Channel ID (distinguishes app store of origin). Configured via Keel CLI.

JS API (draft)

import { umeng } from '@keel-ai/umeng';

await umeng.init({ appKey: '...', channel: 'Huawei' });
umeng.track('button_clicked', { button_id: 'pay' });

Why not Sentry / Firebase Analytics

  • Sentry has unstable access from mainland China; self-reporting to Mortar works, but per-device analytics requires writing your own
  • Firebase Analytics isn’t distributed in mainland China Google Play; reach on domestic Android devices is extremely low
  • Umeng has native China presence; most domestic ops / ad-platforms natively support Umeng data callbacks

Domestic libraries NOT in the first-class set

LibraryStatusRecommended alternative
Tencent MapsCommunityUse @keel-ai/amap (Amap)
Baidu MapsCommunitySame as above
GetuiCommunityUse @keel-ai/push (Jiguang backend)
Bugly CrashCommunityUse @keel-ai/umeng
Aliyun Sophix hotfixProject-integratedUse KAS Update
Meituan ACE containerForbiddenOverlaps with Keel scope; not recommended

Users needing these community modules pull them in via standard npm; Keel doesn’t block but doesn’t officially support either.


Planned implementation order (by market demand + tech dependency)

  1. @keel-ai/push abstract layer + jpush backend — most-used + easiest (Jiguang SDK is mature); the abstract interface needs to be carefully designed up front (not locked to a single backend)
  2. WeChat Pay — required for the business model
  3. Alipay — same
  4. Amap — required for LBS apps
  5. Umeng — required for data callbacks
  6. @keel-ai/push-getui second backend — extra choice for enterprise users; deferred until after jpush ships and we see real feedback

Abstract layer + single backend ~3 weeks; second backend ~3 weeks (including native integration + server-side dispatcher). Each other module expected ~2-3 weeks dev + 1 week internal beta; total ~3-4 months coverage.


Coordination with Mortar

Keel’s 5 modules only handle client-side native integration. Server-side signature verification / callback handling / data persistence is Mortar’s job:

  • @keel-ai/wechat’s pay returns prepayId; Mortar feature/payment handles signing + state machine (planned)
  • @keel-ai/jpush’s push trigger: Mortar backend calls the Jiguang server API (users don’t write their own backend code)
  • @keel-ai/umeng’s crash reports can optionally forward to Mortar feature/usage for backup

This coordination makes Keel users also Mortar users — a bundled value proposition.