Bagtyyar

AutoTM

Active build

Turkmenistan's vehicle marketplace rewrite — an active Turborepo rebuild with Expo, NestJS bounded contexts, Prisma, and air-gapped deployment constraints.

  • Expo SDK 55
  • React Native 0.83
  • NativeWind v4
  • NestJS 11
  • Fastify
  • Prisma 7
  • PostgreSQL 16
  • Redis 7
  • BullMQ
  • Next.js 16
  • Tailwind CSS v4
  • shadcn/ui
  • MinIO
  • Sharp
  • Zod
  • Socket.IO
  • Turborepo
  • Docker
  • Caddy

Outcome

Active ground-up rewrite of Turkmenistan's vehicle marketplace. S1-S3 are shipped; S4 Listings CRUD is the current build slice. The architecture is designed for air-gapped deployment with no cloud dependency on the critical production path.

Context

AutoTM is a vehicle listing and transaction platform built specifically for the Turkmenistan market. The original version was a Flutter mobile app with a stock NestJS API. The current rewrite is a ground-up rebuild of the product and delivery system: clearer domain boundaries, shared contracts, mobile-first listing workflows, and deployment constraints suitable for infrastructure inside Turkmenistan.

Engineering Decisions

  • Monorepo: Turborepo + pnpm workspaces with shared Prisma schema, Zod contracts, and UI tokens consumed by every client.
  • Mobile: Expo + React Native with NativeWind and React Native Reusables, replacing Flutter for better ecosystem access and team velocity.
  • API: NestJS on Fastify with bounded contexts, a pure TypeScript domain layer, one use-case per file, and ports/adapters for cross-context communication.
  • ORM: Prisma with explicit migrations and a single schema package, replacing Sequelize for type safety and reliable migration discipline.
  • Web: Next.js + Tailwind CSS + shadcn/ui for the public site and admin dashboard.
  • Media pipeline: MinIO (S3-compatible, self-hosted) + Sharp for variant generation, replacing Firebase Storage. Client-side compression is mandatory before upload.
  • Auth: Phone OTP via a custom SMS gateway fleet, JWT access tokens, bcrypt-hashed refresh tokens, and capped multi-device sessions.
  • Job queue: BullMQ + Redis + dedicated worker process for async processing.
  • Hosting: Designed for air-gapped deployment inside Turkmenistan with Docker Compose, Caddy, self-hosted services, and no cloud dependency on the critical production path.

Current State

Phase 1 — Marketplace MVP

  • S1 (Scaffold): Shipped — Turborepo structure, CI pipeline, Docker Compose dev environment.
  • S2 (Identity): Shipped — Phone OTP login, JWT sessions, multi-device cap, rate limiting, full test coverage.
  • S3 (Catalog): Shipped — Trilingual catalog seed data, read endpoints, FX rates, and shared contracts.
  • S4 (Listings CRUD): Current focus — Prisma schema and API use-cases are being wired to the mobile 7-step listing wizard, upload state machine, and listing lifecycle. Known gaps are tracked explicitly: autosave edge cases, orphan media cleanup, and public listing-detail route.
  • S5–S10: Next — Search/filters, garage/dealership, chat, notifications, admin dashboard, production polish, and soft launch.

Testing: API, mobile, and SMS-gateway suites cover the shipped slices. CI remains the source of truth for regressions.

Documentation: Architecture Decision Records, context docs, sprint files with Definition of Done, and agent skill docs for mobile and TypeScript runtime boundaries.

Milestones

  1. M1 — Hello stack

    OK

    Turborepo monorepo scaffold, CI pipeline, Docker Compose dev environment, and local Postgres/Redis/MinIO services.

    Completed May 2026

  2. M2 — I can log in

    OK

    Phone OTP authentication via custom SMS gateway, JWT access tokens, bcrypt-hashed refresh tokens, multi-device session cap with FIFO eviction, and rate limiting.

    Completed May 2026

  3. M3 — I can browse cars

    Active

    Listings CRUD with mobile 7-step wizard, media upload state machine, catalog integration, and public listing discovery.

    Target May 2026

  4. M4 — I can search + save

    Active

    Full-text search, advanced filters, saved searches, and garage/dealership profiles.

    Target Jun 2026

  5. M5 — I can contact the seller

    Active

    Socket.IO real-time chat between buyers and sellers, message persistence, and read receipts.

    Target Jun 2026

  6. M6 — I get notified

    Draft

    Push notifications via FCM/APNS, in-app notification center, and notification preferences.

    Target Jul 2026

  7. M7 — Admins run the place

    Draft

    Admin dashboard with moderation queues, user management, analytics, and content administration.

    Target Jul 2026

  8. M8 — Soft launch

    Draft

    App store submissions, production hardening, load testing, monitoring, and beta release to Turkmenistan market.

    Target Aug 2026

Architecture Decisions

Level 2 bounded contexts with use-cases

NestJS on Fastify with pure TypeScript domain layer, one use-case per file, and ports/adapters for cross-context communication.

Stock NestJS feature folders led to bloated services and tight coupling. Bounded contexts with explicit domain/application/infrastructure/presentation layers enforce clear boundaries between identity, catalog, listings, subscriptions, conversations, notifications, content, reports, and admin.

Stack selection: NestJS + Prisma + Next.js + Expo

NestJS API, Prisma ORM, Next.js web, and Expo mobile. Replaced Flutter, Sequelize, and Firebase.

Prisma provides type-safe migrations and a single schema source of truth. Expo + React Native gives better ecosystem access than Flutter for the team. Next.js handles both public site and admin dashboard.

Turborepo + pnpm workspaces

Monorepo with 7 apps and 5 shared packages. Rejected Nx, Lerna, and multi-repo.

Shared packages for Prisma schema (db), Zod contracts, UI tokens, tsconfig presets, and ESLint config. All clients consume the same types and validation rules.

Fully air-gapped hosting in Turkmenistan

Self-hosted Ubuntu servers with Docker Compose, Caddy, and no cloud dependencies. Docker tarballs shipped via SCP/USB.

Internet connectivity inside Turkmenistan is unreliable and foreign cloud providers have latency and compliance issues. Topology C: build on CI, bundle images, transfer to local servers.

Phone OTP + JWT auth with custom SMS gateway

OTP via fleet of Android phones running a Kotlin agent. JWT access tokens + bcrypt-hashed refresh tokens. No password database.

Local SMS providers are expensive and unreliable. A fleet of 5–20 Android phones with SIM cards provides a cost-effective, controllable OTP delivery system. Multi-device sessions capped at 10 with FIFO eviction.

MinIO + Sharp media pipeline

Self-hosted MinIO for S3-compatible object storage. Sharp for server-side variant generation. Client-side compression mandatory.

Replaces Firebase Storage. MinIO runs locally alongside the API. Sharp generates thumbnails and compressed variants on upload. Client compresses before upload to save bandwidth.

Pipeline Evidence

Mobile test suite — 7 files passing

Testing

Expo mobile app unit and integration tests covering components, hooks, and API client behavior.

API test suite — 63 specs passing

Testing

Domain, application, and e2e layers tested. NestJS service layer, controller, and utility tests pass consistently in CI.

Docker multi-stage build — 5 services

Docker

API, web, admin, worker, and SMS-gateway containers build successfully with production optimizations and multi-stage Dockerfiles.

CI pipeline — GitHub Actions with self-hosted runner

CI/CD

Lint, typecheck, test, and build steps run on every push and PR via self-hosted runner labeled tm-proxy.

Prisma schema — 8 migrations applied

architecture

Type-safe Prisma client generated from a single schema in packages/db. 8 migrations applied covering identity, catalog, listings, media, and exchange rates.

AutoTM

Listings mobile wizard — 7-step flow with upload state machine

Expo mobile app listing creation wizard with step validation, media upload staging, and catalog integration. Prisma schema extended with ListingDraft, ListingMedia, and ExchangeRate. Known gaps documented: autosave edge cases, orphan cleanup, public listing-detail route pending.

AutoTM

Catalog context with trilingual seed data

Read endpoints for Brand, Model, Color, BodyType, Region, City, EngineType, Transmission, and DriveType. Seed data in Turkmen, Russian, and English. FX rates table for currency conversion.

AutoTM

Identity context shipped — OTP login, JWT sessions, multi-device cap

Phone OTP authentication via custom SMS gateway with 5-device fleet. JWT access tokens and bcrypt-hashed refresh tokens. Multi-device session cap at 10 with FIFO eviction. Rate limiting on OTP endpoints. Full domain + application + e2e test coverage.

AutoTM

Prisma schema and 8 migrations applied

Single schema file in packages/db covering identity, catalog, listings, media, exchange rates, and subscriptions. Type-safe client generated and consumed by API, worker, and SMS-gateway apps.

AutoTM

Turborepo monorepo scaffold with 7 apps and 5 packages

Turbo.json pipeline configured with lint, typecheck, test, and build stages. Shared packages established for Prisma schema, Zod contracts, UI tokens, tsconfig, and ESLint config. Docker Compose dev environment with Postgres 16, Redis 7, and MinIO.

AutoTM | Bagtyyar