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.
Car marketplace for Turkmenistan by Alpha Motors, live on Google Play. Expo mobile app, NestJS and PostgreSQL API, real-time chat and admin moderation.




Demo data. Car photos: Wikimedia Commons contributors, CC BY-SA.
Live on Google Play. Built over five months, from first commit in May 2026 to the October release.
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.

packages/db, replacing Sequelize.Live on Google Play in English, Russian and Turkmen, as an update to the existing Play listing.
What shipped:
In progress since October 2026. None of this has shipped yet:
Turborepo monorepo scaffold, CI pipeline, Docker Compose dev environment, and local Postgres/Redis/MinIO services.
Completed May 2026
Sign-in with one-time codes sent through a custom SMS gateway, sessions on up to 10 devices, and rate limits.
Completed May 2026
The 7-step sell flow in the mobile app, photo upload, drafts, and listing detail with owner and sold states.
Completed Jun 2026
Search screen for brands, models, and years; full-screen search parameters with live result counts; favorites with active-only filtering.
Completed Oct 2026
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
Direct-message push notifications with eligibility rules and an in-app notification center on Cabinet.
Completed Oct 2026
Admin app with staff moderation, report review, audit UI, verified-phone seller signals, and inspection-interest management.
Completed Jul 2026
Move production from Railway to servers inside Turkmenistan.
Target Nov 2026
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.
API, web, admin, worker and SMS-gateway services each build from a multi-stage Dockerfile.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Open and list conversations use-cases landed in the API, followed by the seller conversation list on the mobile Chat tab.
Listing creation in the mobile app, with step validation, photo upload and catalog pickers.
Brands, models, colors, body types, regions and other lookup lists, plus exchange rates for price conversion.
Sign-in with one-time codes sent through a custom SMS gateway, sessions on up to 10 devices, and rate limits on code requests.