Transport & Manpower Services Case study

VanGo

A UK transport and manpower services platform taken from beta to launch.

Transport & Manpower Services

VanGo VanGo

Software Engineer

System map · Transformation

Verified proof

  • ~30% faster initial load Through code splitting and lazy loading
  • JWT and OAuth Authorization across both sides of the product

Frontend path

  1. Two-sided product

    Drivers on one side, companies on the other

  2. Component architecture

    Reusable React components

  3. TypeScript migration

    Key features moved from JavaScript

  4. Optimised delivery

    Code splitting and lazy loading

Engineering

React · TypeScript · Redux · Stripe · JWT · OAuth

Public historical project · CV-supported summary

Role
Software Engineer
Disclosure
Public historical project · CV-supported summary

The problem

What the system had to solve.

A UK transport and manpower services startup needed its beta product and core operational workflows built for launch.

What I owned

The responsibility behind the work.

Built order booking, payment processing and user management for drivers and companies, including Stripe integration and authentication.

Engineering approach

How it was built.

Developed reusable React components, implemented JWT/OAuth authorization, migrated key features from JavaScript to TypeScript and optimized frontend delivery.

Frontend path

  1. Two-sided product
  2. Components
  3. TypeScript
  4. Delivery

Drivers on one side, companies on the other

A booking product with two user models.

Transport and manpower services match companies that need work done with drivers and workers who do it. Those are two different accounts, two different onboarding paths and two different views of the same order — and the platform is only useful when both sides are present.

Taking that from beta to launch meant the ordinary but unforgiving work of a marketplace: an order someone can place, a payment that reliably completes, and an identity model that keeps the two sides apart.

What each side needs

Companies

  • Place and track orders
  • Manage users
  • Pay for completed work

Drivers

  • Receive and accept work
  • Manage their own profile
  • Be paid

Taking money reliably

The path that cannot be approximately correct.

Payment is the point in a marketplace where a bug stops being an inconvenience. The integration handles the states a payment can actually be in — authorised, captured, failed, retried — rather than treating a successful response as the end of the story.

Order to payment

  1. Order placed
  2. Payment initiated
  3. Payment confirmed
  4. Order becomes actionable
  5. Work assigned
Order state and payment state are related but not the same. A paid order and a placed order are different things.

Authentication and authorization

Two account types, one identity system.

Token-based authentication with third-party sign-in covers both account types, with authorization deciding what each may see. A driver and a company employee can both be looking at the same order and should see different things and be able to do different things with it.

Identity surface

  • Token-based sessions
  • Third-party sign-in
  • Role-appropriate access
  • Company and driver account models

Making it load

A measurable improvement, and how it was found.

The application shipped everything to every user on first load, including code for screens most people never opened. Splitting the bundle along route boundaries and deferring what is not needed immediately reduced initial load time by approximately thirty per cent.

What changed

Before

  • One bundle for the whole application
  • Unused screens downloaded on first visit
  • Load time paid up front by everyone

After

  • Code split along routes
  • Deferred loading for what is not immediately needed
  • Approximately 30% faster initial load
The win is structural rather than micro-optimisation: the fastest code is the code that was never sent.

Migrating to TypeScript

Incremental, on a product that was launching.

Key features were migrated from JavaScript to TypeScript while the product was being taken to launch, which rules out a stop-and-convert approach. Migration proceeded feature by feature, so type safety arrived where it was worth most — the order and payment paths — without holding up delivery.

On a two-sided marketplace, the paths worth typing first are the ones where a wrong shape means a wrong charge or an order assigned to nobody.

Engineering scope

What I worked on.

  1. Order booking workflows
  2. Payment processing with Stripe
  3. Driver and company user management
  4. JWT and OAuth authorization
  5. JavaScript to TypeScript migration

Why these decisions mattered

The trade-offs behind the build.

  • Split the bundle by route

    Decision
    Code loaded per screen rather than all at once.
    Why
    Most users never open most screens; sending that code to everyone is the largest avoidable cost.
  • Incremental TypeScript migration

    Decision
    Convert feature by feature during active delivery.
    Why
    A launching product cannot pause for a rewrite, and the highest-risk paths benefit first.
  • Separate account models

    Decision
    Companies and drivers are distinct account types.
    Why
    They see different things and can do different things with the same order.
  • Model payment state explicitly

    Decision
    Order state and payment state are tracked separately.
    Why
    A placed order and a paid order are different, and conflating them loses money in both directions.

Impact

The verified result.

Reduced initial load time by approximately 30% through code splitting and lazy loading.

Technology

The technical surface.

  • React
  • TypeScript
  • Redux
  • Stripe
  • JWT
  • OAuth

Next: AI-Assisted Sage Intacct Automation

Back to all work Start a conversation