All work
My side project

SolveMY

A trilingual local-services marketplace for Malaysia on Android, iOS and web. Customers post requests; verified providers and merchants quote and chat.

Role
Engineering lead, built end to end
Type
My own side project
Period
Jan 2026 to Present
Status
Live on web and Google Play · submitted to the App Store
Visit the live site

SolveMY connects customers with verified service providers and merchants (repairs, cleaning, transport, beauty, tuition and more) in English, Malay and Chinese. I built and run the whole stack: a layered Go REST API on PostgreSQL with PostGIS for location search, a Next.js 16 website with server-rendered SEO pages, and a Flutter app for Android and iOS. Production runs on a self-managed Hetzner server with Docker, nginx and Let's Encrypt, Cloudflare R2 for storage and CDN, and Vercel for the web, with isolated staging and production, encrypted nightly backups, CI quality gates and monitoring.

What I built

  1. 01Designed a layered Go API (domain, services, repositories, HTTP) with chi and pgx: 235 endpoints across 31 domain services, 1,006 test functions, golangci-lint and gofmt gates in CI.
  2. 02PostGIS radius and nearest-first search for providers, merchants and requests, plus a merchant map with clustered pins on the app and the website.
  3. 03Session security: short access tokens with rotating opaque refresh tokens, reuse detection that revokes the whole token family, per-device sessions and a 90-day sliding lifetime.
  4. 04AI search on the Claude API: free text in English, Malay or Chinese, or a photo, mapped to a category and sub-area.
  5. 05Shipped the 48-screen Flutter app to Google Play and submitted it to the App Store, with one codebase made compliant with both stores' pricing rules.
  6. 06Run production on Hetzner with Docker, nginx and Let's Encrypt; staging as a true canary; nightly AES-256 encrypted backups to Cloudflare R2; Sentry, uptime and TLS-expiry alerts.

Stories worth telling

Push notifications silently failed on every device for ten days. I traced the FCM error codes to an APNs block attached to every message, made it iOS-only, removed duplicate pushes and added an admin endpoint that proves delivery per user.

The API went "down" when a TLS certificate expired on a domain that had moved hosts. I re-issued it, restored auto-renew with an nginx reload hook, and added a daily expiry alert so it can't happen silently again.

Race-safe "once per person per day" analytics: a day-table insert with ON CONFLICT DO NOTHING inside a CTE, so repeat taps never double count.

Delete-for-everyone in chat that still works on old app versions: soft delete, with deleted messages served as plain text plus a flag.

Numbers

  • 235 REST endpoints
  • 1,006 Go test functions
  • 116 SQL migrations
  • 48 app screens · 75 web routes
  • 3 languages
  • 834 commits in 8 months

Stack

  • Go
  • chi
  • pgx
  • PostgreSQL 16
  • PostGIS
  • Next.js 16
  • TanStack Query
  • NextAuth
  • Flutter
  • Riverpod
  • Docker
  • nginx
  • Cloudflare R2
  • Vercel
  • Firebase (FCM / APNs)
  • Twilio
  • Google Maps Platform
  • Claude API
  • GitHub Actions
  • Sentry
Need something like this?Mobile apps for iOS & AndroidSee the service
Next projectMT5 risk engine