← Back to all projects

Client project

VavaStone - Inventory, Sales & Delivery for Natural Stones Industry

VavaStone - Inventory, Sales & Delivery for Natural Stones Industry

Tech stack

GolangReactTypeScriptPostgreSQLDockerKubernetesMicroservicesProjectFullstackAWS

Services

  • Fullstack development (Go + React + TypeScript)
  • OpenAPI contract definitions and typed client generation
  • Local Kubernetes dev environment standardisation
  • Inventory and order management module development
  • Engineering hiring, structured onboarding, and mentorship

Deliverables

  • Type-safe API contracts between microservices, integration bugs caught at compile time
  • Makefile-based local dev setup, new engineers productive on day one
  • Inventory and order management feature improvements
  • Hiring pipeline and onboarding process for distributed engineering team

Challenge

VavaStone is an international platform for natural stone inventory, sales, and delivery, a domain with complex logistics: multi-warehouse stock, weight-based shipping, multi-currency pricing, and multinational customer workflows. The engineering team was distributed across several countries. By the time I joined, the Go + React microservice architecture was functional but had accumulated friction: service boundaries were implicit, local development required significant setup, and onboarding new engineers took too long.

Discovery

A few weeks of codebase exploration and team conversations identified three root causes. First: services communicated via untyped JSON with no shared schema, making integration bugs subtle and hard to catch before production. Second: the local Kubernetes environment required manual steps that weren't documented, so each engineer had a slightly different setup. Third: the hiring and onboarding process was informal, knowledge lived in people's heads, not in docs.

Options Considered

  1. Introduce a service mesh and auto-generated clients, too heavy for the team size; would have taken months to migrate existing services.
  2. Add OpenAPI specs and generate typed clients per service: chosen as the pragmatic middle ground. Explicit contracts, generated types, no new infrastructure.
  3. Migrate to a monorepo with shared type packages, deferred; viable long-term but too disruptive short-term.

Decision

Introduce typed API contracts incrementally as services are touched, rather than a big-bang migration. Simultaneously: document the local dev environment into a repeatable setup script, and formalise the onboarding process with a written checklist and a designated buddy for new hires.

Implementation

Added OpenAPI definitions to the services I worked on and generated TypeScript client types used by the React frontend. This caught a class of bugs at compile time that previously only surfaced in staging. Refactored the local Kubernetes setup into a documented Makefile-based workflow, `make dev-up` instead of six manual commands. New engineers could run the full stack locally on day one.

On the product side, delivered inventory and order management module improvements: stock level display across warehouses, order status tracking, and delivery cost calculation flows. Participated actively in hiring: wrote job descriptions, conducted technical interviews, and ran the first structured onboarding for two new engineers.

Outcome

Integration bugs between services dropped measurably as typed contracts caught mismatches at build time. New engineer ramp-up time shortened from weeks to days with the documented dev environment. The team shipped features at a noticeably higher velocity in the quarters following the tooling improvements.

Demo

Tightening the types between backend and frontend came down to one practical option: generating an annotation for every single API call. Doing that by hand across the whole surface is a long grind, so I tested the AI tooling available at the time, still raw then, and picked it to carry that work. This is the R&D recording of that approach.

Second half of the same story: an OpenAPI utility reads those call annotations and generates the frontend types from them. From there a type mismatch surfaces as a compile-time error on its own, which removes an entire category of runtime integration bugs.

The approach did not stay mine: I recorded a walkthrough and presented it to the rest of the team. It got the teamlead's sign-off and was adopted as the standard for further development, so new and reworked endpoints went through the same annotate-and-generate flow.

VavaStone, team feedback on the type-generation approach
Team feedback in the project channel

Early alpha of the reporting system prototype, order and inventory analytics built on top of the type-safe data layer.

🔒 How it ended

This part is closed. Enter the code to read it.

Open for contract collaboration

I am available for contract-based collaboration. If you have an interesting project idea, schedule a call via Calendly.

Schedule a 30-min call