Skip to content
Bagtyyarfull-stack engineer

Carberk

Car marketplace for Turkmenistan by Alpha Motors, live on Google Play. Expo mobile app, NestJS and PostgreSQL API, real-time chat and admin moderation.

  • React Native
  • Expo SDK 55
  • NestJS 11
  • PostgreSQL 16
  • Next.js 16
  • Socket.IO
  • Docker
Carberk home feed with new listings and TMT pricesCarberk listing detail for a Lexus RX with photo gallery and specsCarberk search filters for condition, brand, year and priceCarberk buyer and seller chat about a Toyota Camry Hybrid

Demo data. Car photos: Wikimedia Commons contributors, CC BY-SA.

Outcome

Live on Google Play. Built over five months, from first commit in May 2026 to the October release.

Context

Carberk, by Alpha Motors, is a car marketplace for Turkmenistan. The old version was a Flutter app on a stock NestJS API. The rewrite rebuilt the mobile app, API, admin and hosting from scratch.

Carberk by Alpha Motors, a car marketplace for Turkmenistan

Decisions

  • Monorepo: Turborepo + pnpm workspaces with 7 apps and 5 shared packages. Shared Prisma schema, Zod contracts, and UI tokens consumed by every client.
  • Mobile: Expo SDK 55 + React Native 0.83.6 with NativeWind v4 and React Native Reusables, replacing Flutter.
  • API: NestJS 11 on Fastify. Each area (sign-in, listings, chat, admin) is its own module with a plain TypeScript core.
  • ORM: Prisma 7 with explicit migrations and a single schema file in packages/db, replacing Sequelize.
  • Web: Next.js 16 + Tailwind CSS v4 + shadcn/ui for both public site (auto.tm) and admin dashboard (admin.auto.tm).
  • Media pipeline: MinIO (S3-compatible) + Sharp for variant generation, replacing Firebase Storage. The app compresses photos before upload, and the API checks who owns a file before it can be attached or deleted.
  • Real-time: Socket.IO 4 with a Redis adapter for buyer-seller chat: saved messages, read states, unread counts, and mute, report and block.
  • Auth: Sign-in codes go out through a fleet of 5–20 Android phones running a Kotlin agent, because local SMS providers are expensive and unreliable. JWT access tokens, hashed refresh tokens, and up to 10 devices per account.
  • Job queue: BullMQ + Redis + dedicated NestJS worker app for async processing.
  • Hosting: Railway, with every service in a plain Docker container, so moving to servers inside Turkmenistan is a redeploy, not a rewrite.
  • Deployment: Multi-service Docker images built via GitHub Actions, with disposable PR backends on Railway for review.

Release

Live on Google Play in English, Russian and Turkmen, as an update to the existing Play listing.

What shipped:

  • Phone sign-in with one-time codes and sessions on up to 10 devices.
  • A 7-step sell flow with brand, model, year and generation pickers, photo upload and drafts.
  • Search by brand, model and year, with live result counts and favorites.
  • Buyer-seller chat with read labels, quick replies, mute, report and block, plus push notifications.
  • Staff moderation, report review, verified-phone seller badges and condition disclosure.
  • Legal pages, account deletion and the Google Play release.

Now building

In progress since October 2026. None of this has shipped yet:

  • Car diagnostics center: a staff workspace for one diagnostics center in Aşgabat, with versioned checklists, photo evidence, finalized reports that cannot be edited later, and stored PDFs. Buyer-private reports and seller-authorized public reports keep separate audiences.
  • Vehicle history by VIN: a paid history lookup from established providers such as Carfax and AutoCheck, run through an operator queue with its own Support channel. No paid provider calls are made until rights and capacity are confirmed.
  • Dealer showrooms: free business workspaces for approved dealerships. The business owns its inventory and enquiries, so a salesperson leaving does not take listings or customer chats with them.
  • Listing video: an optional walkaround video of up to 90 seconds per listing, rolled out to testers first. Photos alone still allow publishing while a video is processing.
  • Aşgabat pilot: a 20-user app pilot, measured in-house, run separately from the manual inspection trial.

Milestones

  1. Project setup

    Done

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

    Completed May 2026

  2. Phone sign-in

    Done

    Sign-in with one-time codes sent through a custom SMS gateway, sessions on up to 10 devices, and rate limits.

    Completed May 2026

  3. Selling a car

    Done

    The 7-step sell flow in the mobile app, photo upload, drafts, and listing detail with owner and sold states.

    Completed Jun 2026

  4. Search and favorites

    Done

    Search screen for brands, models, and years; full-screen search parameters with live result counts; favorites with active-only filtering.

    Completed Oct 2026

  5. Buyer-seller chat

    Done

    Buyer-seller chat over Socket.IO with message persistence, read labels, quick replies, mute/report/block, unread counts, and push deep-links into conversations.

    Completed Jul 2026

  6. Notifications

    Done

    Direct-message push notifications with eligibility rules and an in-app notification center on Cabinet.

    Completed Oct 2026

  7. Admin and moderation

    Done

    Admin app with staff moderation, report review, audit UI, verified-phone seller signals, and inspection-interest management.

    Completed Jul 2026

  8. Move hosting to Turkmenistan

    Planned

    Move production from Railway to servers inside Turkmenistan.

    Target Nov 2026

Tests and deployment

CI gates and release bundles on GitHub-hosted runners

CI/CD

PR checks, CI on main, and release bundle builds moved to GitHub-hosted runners; disposable Railway PR backends stand up per pull request for review.

Docker images for 5 services

Docker

API, web, admin, worker and SMS-gateway services each build from a multi-stage Dockerfile.

Carberk

Sign-in code logs redacted; Play submission decisions recorded

Sign-in log lines now show only the last four digits of the phone number, and Google Play publishing from the command line was set up.

Carberk

Store release wired to the existing Play app as version 2.0.0

The new app ships as version 2.0.0, an update to the existing Play listing, with a build check that refuses a mismatched package name.

Carberk

EXIF and GPS stripped from stored images

Listing photo originals carrying metadata or an orientation tag are re-encoded upright without it (within the 5 MB cap) before variants are built, and chat images are re-encoded the same way before another user can load them. Chat only accepts images uploaded for that conversation.

Carberk

Privacy: credentials and search terms kept out of logs

pino-http no longer logs Authorization, Cookie, or API-key headers, and query strings (including search terms) stay out of the request log. Purge deletes the user's sign-in code records and clears contact phones on kept listings, a job sweeps code records older than 30 days, and Android backup is disabled.

Carberk

Play Console submission pack prepared

Store listing copy in RU, TK, and EN, Data safety answers and permissions cited to the code, app content answers, a reviewer access template, and the founder's Console checklist. That is the full submission pack for the Play release.

Carberk

Account deletion made atomic; Turkmen copy and profile fixes

Deleting an account now archives the user's listings in the same transaction, so a failure can't leave half-deleted data. Control characters are stripped from display names (NUL caused 500 errors), and Turkmen copy uses akkaunt everywhere.

Carberk

Display names, generated avatars, and listing editing

Every user gets a generated name and avatar, shown on Cabinet and Profile. Users can edit their display name, and sellers can edit a published listing section by section.

Carberk

Sell flow: preview, clear blockers and a contact phone step

The check-and-publish step gained a preview with per-section Change links and named blockers instead of generic errors, and a new contact step lets the seller pick or confirm the contact phone bound to the listing.

Carberk

Sell wizard exit saves the draft; photos move to step 3

The Sell wizard's close control now persists the in-progress draft instead of discarding it, and photo selection moved up to step 3 with continue-on-pick and upload failures listed under the grid.

Carberk

Messages, notifications, and release handoff mapped

Messages list rows and conversation screens with mute, report, and block; unread count on the Messages tab; the notification center on Cabinet; contact phone confirmation API; and the Android reviewer release handoff documented for the planned store submission.

Carberk

Cabinet becomes the app menu; legal and account flows wired

Cabinet replaced Settings as the app menu. Legal pages and posting rules are linked from Cabinet rows, the account-deletion flow explains consequences and schedules the purge, and language and theme pickers moved to bottom sheets.

Carberk

Search screen and full-screen search parameters

Search screen for brands, models, and years, then the full-screen search parameters form replacing the filter sheet. Listing detail gained owner and sold states. Results, filters and sorting now look the same on every screen.

Carberk

Sprint 11: test access for store reviewers

Store reviewers get a sign-in bypass that is logged for audit, plus seeded demo data, so they can test the app without real listings.

Carberk

Hosting plan: Railway first, Turkmenistan later

Staging and production move to Railway until the app store approves the app, then to servers inside Turkmenistan. Everything stays in plain Docker containers, so the move is a redeploy. This replaces the original offline-only plan.

Carberk

Sprint 10: chat, message notifications and mobile polish

Buyers and sellers can chat, and new messages trigger push notifications. Verified-phone seller badges and condition disclosure (damage and known issues) shipped in the same weeks.

Carberk

Conversations API and seller chat list

Open and list conversations use-cases landed in the API, followed by the seller conversation list on the mobile Chat tab.

Carberk

7-step sell flow in the mobile app

Listing creation in the mobile app, with step validation, photo upload and catalog pickers.

Carberk

Car catalog in Turkmen, Russian and English

Brands, models, colors, body types, regions and other lookup lists, plus exchange rates for price conversion.

Carberk

Phone sign-in shipped

Sign-in with one-time codes sent through a custom SMS gateway, sessions on up to 10 devices, and rate limits on code requests.