Platform manajemen motor berbasis AstraPay β a motorcycle-ownership platform where riders manage their bikes, book workshop service, track rides, and unlock financing from their maintenance behaviour. Workshops manage their queue and earnings; ops monitor everything from a web console.
Prototype. Demo build β no real authentication, permissive row-level security, and mocked payments. Not production-ready by design.
| App | Path | Stack | Audience |
|---|---|---|---|
| Consumer | apps/consumer |
Expo Β· React Native | Rider β garage, bookings, MotoScore, marketplace, rides |
| Partner | apps/partner |
Expo Β· React Native (phone + tablet) | Workshop β inbox, queue, QR check-in, earnings |
| Console | apps/console |
Next.js App Router | Ops β web dashboard |
| Shared | packages/shared |
TypeScript library (@umotor/shared) |
Types, constants, theme, mocks |
| Backend | supabase/ |
Postgres + Edge Functions | Migrations, seed, RPCs, RLS, Realtime |
All three front-ends talk to a single hosted Supabase project.
- MotoScore β credit-style score derived from maintenance behaviour that unlocks financing.
- Booking flow β workshop discovery, live slot locking, AstraPay deposit, QR check-in.
- Ride tracking β foreground GPS + activity classification; server recomputes distance and rejects spoofed tracks.
- Finance Hub β STNK / installment bills, fuel top-up that organically advances the odometer.
- Partner ops β realtime inbox, queue, earnings, slot/capacity config, and a sparepart marketplace.
Prerequisites: Node.js (LTS), pnpm, Supabase CLI, and Expo Go for mobile.
pnpm install
# Backend
supabase login
supabase link --project-ref <YOUR_PROJECT_REF>
pnpm db:reset # applies migrations + seed
# Env β copy each template and fill in your Supabase URL + anon key
cp apps/console/.env.example apps/console/.env.local
cp apps/consumer/.env.example apps/consumer/.env
cp apps/partner/.env.example apps/partner/.env| Variable | Used by |
|---|---|
NEXT_PUBLIC_SUPABASE_URL / NEXT_PUBLIC_SUPABASE_ANON_KEY |
Console |
EXPO_PUBLIC_SUPABASE_URL / EXPO_PUBLIC_SUPABASE_ANON_KEY |
Consumer & Partner |
Only the publishable / anon key belongs in
NEXT_PUBLIC_*/EXPO_PUBLIC_*β never the secret key (sb_secret_β¦), which bypasses row-level security..envfiles are gitignored.
pnpm console:dev # Next.js dev β http://localhost:3000
pnpm consumer:start # Expo QR β scan with Expo Go
pnpm partner:start # Expo QR β scan with Expo GoFor installable device builds, use EAS Build via each app's eas.json and pnpm <app>:build:android / :ios scripts.
Schema, views, RLS, and Realtime publication live in supabase/migrations; demo data in supabase/seed.sql. All state changes go through Postgres RPCs β never direct table writes from the client:
| RPC | Purpose |
|---|---|
book_slot |
Atomic slot lock; inserts booking + parts + deposit payment, deducts the AstraPay wallet |
update_booking_status |
Validates the booking state machine; refunds deposit + frees slot on cancel |
complete_booking |
Final payment, +5 MotoScore, +500 MotoPoints, resets serviced components |
advance_odometer |
Adds km; fires maintenance notifications at 80 / 95 / 100 % thresholds |
finish_ride |
Server-side distance recompute, rejects spoofed tracks, awards MotoPoints |
Realtime is published on bookings, motoscore, points, slots, notifications, and rides.
- TanStack Query everywhere, with a polling fallback beside every realtime subscription.
- Plain
StyleSheetin React Native Β· Tailwind CSS in the console Β· shared tokens from@umotor/shared. - Integer Rupiah always β render via
formatRp, never floated. - Bahasa Indonesia for all user-facing copy.
pnpm db:resetRe-applies migrations and re-seeds. Seed data is relative to the current date, so it never goes stale β a reset restores the wallet, score, and bookings to their exact demo numbers before every rehearsal.