Back to home

Project

VIN Decoder

Mahad Farooq

GitHub · Live demo

A VIN is the 17-character ID stamped on every vehicle. Hidden inside it is the make, model, year, weight class, fuel type, and more, but only if you can decode it. The plain version of this project: you type in a VIN, and you get back clean, reliable details about the car.

The interesting part is not the decoding. The government already gives you that for free. The interesting part is making the result trustworthy.

The real problem: the source data is a mess

The app calls the free NHTSA vPIC API. That API works, but it hands you back around 150 fields that are noisy and completely untyped. Empty strings, the literal text "Not Applicable," stray whitespace, numbers stored as strings, weird range descriptions jammed into one field. If you build directly on that, every screen downstream has to re-handle the same garbage.

So I built a normalization layer that turns all of that into one consistent, strongly-typedVehicle contract. Decode a VIN once, and everything after it can trust the shape of the data.

VIN decode pipeline: a raw vPIC response normalized into a clean, typed Vehicle model

What the normalization actually does

  • Empty values, "Not Applicable," and whitespace all collapse to a clean null instead of five different versions of nothing.
  • Numeric fields like model year, door count, and engine cylinders get coerced to real numbers, not strings.
  • The GVWR weight class gets parsed out of the long range description into its own field.
  • Error codes and messages from the API are kept, so you can tell how trustworthy a given decode is instead of silently showing bad data.

The output is one Vehicle model: VIN, make, model, year, vehicle type, body class, weight class, fuel types, drive type, engine specs, manufacturer, plant country, door count, and the data-quality signals.

The VIN Decoder app interface

How it is built

It is a Next.js app with the App Router, written in strict TypeScript with no any. Tailwind for styling. The tests run on Node's built-in test runner with experimental TypeScript type-stripping, which means zero test-framework dependencies, nothing extra to install.

There are two endpoints. GET /api/decode?vin=... decodes a single VIN, and POST /api/decode/batch takes a list of VINs at once. The whole thing deploys to Vercel with zero config and no API keys, because the vPIC API is free and needs no registration.

Why I built it

It is a small project, but it is the kind I like: take a messy real-world data source and wrap it in something clean and reliable that other code can actually depend on. The value was never the API call. It was the contract on top of it.

Back to home