Usman Ghani  /  Case Study

Building AutoPort solo: a multilingual vehicle-export SaaS on Next.js 16, Hono & Supabase

AutoPort is a B2B operations platform for Japanese used-car exporters — vehicle and shipment pipelines, container tracking, multi-currency buyer ledgers, and staff role-based access, in four languages including two right-to-left ones. I designed, built, and shipped it as the sole developer.

Next.js 16 React 19 Hono 4 Supabase TypeScript Turborepo OpenTelemetry Vercel + Heroku

The problem

Japanese used-car export is a business of state transitions. A vehicle is bought at auction, inspected, assigned to a buyer, loaded into a container, shipped, cleared, and settled — and money moves in a different currency at nearly every step. Most exporters run this on spreadsheets and chat messages, where the truth about "where is this car and who has paid for it" lives in several places at once and disagrees with itself.

AutoPort's job is to make that single-sourced: one pipeline, one ledger per buyer, one place where staff see exactly what their role permits.

Why Next.js and Hono, rather than Next.js alone

Next.js Route Handlers would have been the path of least resistance. I split the backend into a standalone Hono service instead, for three reasons that mattered more than the convenience:

The cost is real and worth naming: two deploy targets, cross-origin auth, and shared types that must be kept in sync through the Turborepo workspace. For a solo developer that is a deliberate trade, not a free win.

Multi-tenancy and access control

Every request resolves to an exporter (the tenant) and a role before it touches data. Authorization is enforced server-side in the API's shared middleware rather than in the UI, so hiding a button is a usability decision, never a security one.

ConcernWhere it lives
Tenant resolution & buyer scopingHono middleware, applied before route handlers
Row-level isolationSupabase RLS policies keyed on the tenant
Privileged operationsSeparate super-admin surface with its own auth path
Abuse controlRate limiting in shared middleware

Files are an access-control problem too

Export paperwork — invoices, bills of lading, inspection sheets — is sensitive. Uploads are validated by inspecting magic bytes rather than trusting the declared MIME type or file extension, so a renamed executable cannot masquerade as a JPEG. Downloads are served through short-lived signed URLs, with a cache in front so that listing a container's twenty documents does not mint twenty fresh signatures on every render.

Multi-currency ledgers

A buyer pays deposits in one currency against vehicles priced in another, with FX moving between the two. The ledger is append-only: balances are derived from entries rather than stored and mutated. Recomputing a balance is cheap; explaining a balance that drifted is not. FX rates are captured with the entry, so a historical statement reproduces exactly what the buyer saw at the time — not what the rate happens to be today.

Four languages, two of them right-to-left

AutoPort ships in English, Japanese (日本語), Arabic (العربية) and Urdu (اردو) via next-intl. Arabic and Urdu are right-to-left, which is where most internationalization work quietly falls apart.

The translation catalogues total well over half a megabyte across the four locales — a reminder that i18n is an ongoing content obligation, not a one-time integration.

Observability

Both the web app and the API are instrumented with OpenTelemetry — distributed traces across the two services, plus metrics on the API. When an exporter reports that a shipment update "took forever," the question is answerable with a trace rather than a guess. Product analytics run through PostHog, kept deliberately separate from operational telemetry.

The stack, in full

LayerChoice
WebNext.js 16, React 19, TypeScript, Tailwind, TanStack Query, React Hook Form + Zod
APIHono 4, TypeScript, Zod validation, Sharp, Svix webhooks
Data & authSupabase (Postgres, RLS, Auth, Storage)
i18nnext-intl — en / ja / ar / ur, with RTL support
TelemetryOpenTelemetry traces + metrics, PostHog
InfrastructureTurborepo monorepo, Vercel (web), Heroku (API)

What I would revisit

The two-service split is the right call for this product, but it front-loads work that a single Next.js app defers — auth across origins, shared contracts, two pipelines to keep green. If I were starting a product whose API surface would never leave the browser, I would not repeat it. The RTL work, by contrast, is worth doing on day one every time: retrofitting direction-awareness into a codebase already full of margin-left is dramatically more expensive than starting with logical properties.

See it live: useautoport.com

I'm Usman Ghani, a full-stack developer in Islamabad, Pakistan, working across Next.js, Flutter, and machine learning. If you're building something in this territory, get in touch.