Skip to content

Repository files navigation

Tomo Together

A cozy pixel-art friends app: real accounts, real hangouts, and real proof you showed up. It ships as an Expo/React Native Android app and web build backed by a small Express API.

UI styling uses the Sprout Lands UI Pack (Basic) by Cup Nooble: sprite panels, buttons, icons, and pixel font in assets/ui and assets/fonts. Its license is free for non-commercial use only, with no redistribution. Replace or license those assets before commercial use.

How it works

  • Accounts: self-hosted username/password sign-in. The server hashes passwords with scrypt and issues an opaque bearer token per account, sent as Authorization: Bearer. Accounts left over from the earlier Auth0 phase are claimed by setting a password on the first sign-in.
  • Profiles and friends: pick a username and avatar, search by username, send a request, and see equipped friends wandering through the yard.
  • Hangouts: invite friends and use pairwise choices to narrow down an activity. Every pick tunes preference weights on the server.
  • Proof: upload a photo and confirm every attendee pair by NFC. Completed hangouts become Memory Book polaroids and increase friendship vibe.
  • Acorns and wardrobe: earn acorns through friendship levels and spend them on avatar items.
  • Wallet and staking: the separately gated crypto service uses Unifold treasury custody for Base USDC and MongoDB Atlas for durable ledger, withdrawal, event, and idempotency state. Hangout no-shows can forfeit a stake to attendees. This moves real value when enabled.
  • Music: Tomo Yard.mp3 loops quietly while the app is active. The global Music on/off control persists the preference. Web playback starts after the first user gesture because browsers block unsolicited autoplay.

Production

  • Main API and marketing site: https://tomo-together.com
  • Expo web app: https://app.tomo-together.com
  • APK download: https://tomo-together.com/apk
  • Legacy hostnames ht6.icinoxis.net / ht6-app.icinoxis.net 301-redirect to the domains above; API routes still answer on the old host for installed APKs.
  • Main Azure App Service: ht6-tomoyard
  • Crypto Azure App Service: ht6-tomoyard-crypto
  • Atlas databases on the dedicated tomo-yard cluster: tomoyard (main social data) and ht6_crypto (crypto ledger), each with its own least-privilege user

Terraform in infra/ manages Azure and Cloudflare. External crypto credentials live in Azure Key Vault ht6tomoyardkv4831; no secret value belongs in Terraform, Git, an EXPO_PUBLIC_* variable, or chat. The crypto feature is enabled only when Terraform's crypto_enabled input adds CRYPTO_API_URL to the main service. Keep that input false until the crypto deployment passes /ready and the non-monetary acceptance checks.

Read the production runbook before applying infrastructure, rotating credentials, or enabling crypto. It contains the Atlas inventory, Key Vault secret names, two-phase deployment, checks, rollback, and rotation procedures.

CI/CD on push to main uses:

  • .github/workflows/deploy-server.yml for the main API and marketing site;
  • .github/workflows/deploy-web.yml for the Expo web build;
  • .github/workflows/build-apk.yml for the signed Android APK; and
  • .github/workflows/deploy-crypto.yml for the separately tested crypto service.

The crypto workflow needs AZURE_CRYPTO_WEBAPP_PUBLISH_PROFILE. APK signing needs ANDROID_KEYSTORE_BASE64 and ANDROID_KEYSTORE_PASSWORD; preserve the original keystore because APK updates must keep the same signature. No public auth-provider build variables are required — authentication is served by the app's own API.

Run locally

Main API (needs a MongoDB; tests bring their own in-memory instance):

docker run -d -p 27017:27017 mongo:7   # or any MongoDB at MONGODB_URI
cd server
npm install
npm test
node index.js

Crypto service:

cd custody
npm install
cp .env.example .env
# Fill the local ignored file; use CRYPTO_STORE_BACKEND=json only for local development.
npm test
npm start

Start the main API with CRYPTO_API_URL=http://localhost:8787 and the same 32-or-more-character CRYPTO_SERVICE_TOKEN on both processes. Production refuses the JSON store and requires Atlas.

The product cash-out minimum is 20 USDC (20000000 base units). A withdrawal's Idempotency-Key and exact payload must be reused after an uncertain response; generating a fresh key can represent a new money operation. Automatic real-USDC grants, raw balance adjustments, and treasury-funded event bonuses are disabled in production unless their exact dangerous opt-in is set to true.

Build the app

npm install
npx expo run:android

The NFC pieces (HCE service, TomoHce bridge module, manifest entries, and release signing) are generated by plugins/withTomoHce.js, so npx expo prebuild can regenerate the ignored android/ directory. The NFC HCE native module requires a development or standalone build; do not use Expo Go for the NFC exchange test.

NFC notes

  • Scan uses react-native-nfc-manager with IsoDep and AID F0544F4D4F31.
  • Show uses a custom generated Android HostApduService.
  • Phones without NFC get a clear message, and the emulator has no NFC radio.
  • The radio exchange still needs two physical phones even when API paths pass.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages