NHTSA vPIC often returns a TransmissionStyle field on DecodeVinValues-style payloads: strings like "Automatic", "Manual", "Continuously Variable Transmission (CVT)", or longer catalog phrases. That label is useful on a free VIN decode card. The trap is dressing it up as a gearbox pitch -- "6-speed," "8DCT," "smooth 10-speed" -- that the API never asserted.
This post is about honest display: pass through the catalog string, refuse invented gear counts, and allow a clean "not provided" state when the field is empty.
What TransmissionStyle is (and is not)
TransmissionStyle is a manufacturer / catalog attribute associated with the VIN decode. It answers a narrow question: which transmission style did the decode associate with this vehicle pattern?
It does not answer:
- How many forward gears the unit has
- Whether the fluid is due, the clutch is worn, or the CVT belt is healthy
- Whether a dealer option package swapped the transmission after the VIN was stamped
- Shift quality, tow mode behavior, or paddle-shift availability
- Whether "Automatic" here means a traditional planetary box, a dual-clutch, or something else
Empty TransmissionStyle does not mean "probably automatic." It means vPIC did not give you a value. Do not invent a default from make/model folklore or from a Wikipedia gearbox table keyed by trim.
Normalize empties, do not invent ratios
Treat blank, "Not Applicable", "N/A", and similar tokens as missing. Do not rewrite "Automatic" into "6-Speed Automatic" or append a gear count because a sibling field looked similar on another VIN.
const EMPTY = new Set([
"",
"not applicable",
"n/a",
"na",
"null",
"none",
"unknown",
]);
export type TransmissionView = {
label: string | null;
source: "vpic" | "missing";
};
export function viewTransmissionStyle(fields: {
TransmissionStyle?: string | null;
TransmissionSpeeds?: string | null;
}): TransmissionView {
const raw = (fields.TransmissionStyle ?? "").trim();
if (!raw || EMPTY.has(raw.toLowerCase())) {
return { label: null, source: "missing" };
}
// Do not merge TransmissionSpeeds into the label unless product
// shows speeds as a separate, sourced row -- never invent counts.
return { label: raw, source: "vpic" };
}
export function transmissionLines(view: TransmissionView): string[] {
if (view.source === "missing" || !view.label) {
return ["Transmission style: not provided by decode."];
}
return [
`Transmission style: ${view.label}`,
"Catalog label from decode -- not a gear count or shop diagnosis.",
];
}
If vPIC also exposes TransmissionSpeeds (or a similar field), show it as its own row with the same empty rules. Never concatenate "Automatic" + guessed "6" into one marketing chip. When speeds are missing, leave the speeds row empty -- do not fill from trim name regexes like /(\d)[- ]?speed/i.
UI patterns that stay honest
- Sourced or missing. Every transmission row either quotes a non-empty vPIC string or says "not provided."
- No synonym upgrades. Do not map "Automatic" to "Smart Auto" or "CVT" to "Seamless e-CVT" unless that exact phrase came from the API.
-
Separate speeds. If you show speeds, label the source field explicitly (
TransmissionSpeeds) so support can see which column failed. - No redline copy. Avoid "buttery shifts," "race-ready DCT," or "bulletproof 10-speed" next to catalog data.
- Tests forbid inventions. Assert that display helpers never emit digit-speed phrases unless the digit appeared in a sourced field.
import assert from "node:assert/strict";
assert.deepEqual(
transmissionLines(viewTransmissionStyle({ TransmissionStyle: "" })),
["Transmission style: not provided by decode."],
);
assert.ok(
transmissionLines(
viewTransmissionStyle({ TransmissionStyle: "Automatic" }),
).some((l) => /Automatic/.test(l)),
);
assert.ok(
!transmissionLines(
viewTransmissionStyle({ TransmissionStyle: "Automatic" }),
).some((l) => /\d[\s-]*speed/i.test(l)),
);
assert.ok(
!transmissionLines(
viewTransmissionStyle({
TransmissionStyle: "Continuously Variable Transmission (CVT)",
}),
).some((l) => /e-cvt|seamless|bulletproof/i.test(l)),
);
Add a review rule: the transmission display module must not contain hardcoded gear counts except inside tests that forbid inventing them.
Copy that stays catalog-shaped
When you need a short card subtitle, reuse the vPIC string. Do not paraphrase into "smooth automatic drive" or "manual for enthusiasts." Paraphrase is where marketing sneaks in without a code review noticing.
If product wants a one-word chip, whitelist only tokens that already appear in the raw field (for example taking the first word when it is Automatic, Manual, or CVT). Never map the chip through a synonym table that upgrades "Automatic" to "10AT."
Document the rule in the component README: TransmissionStyle rows are sourced or missing -- never inferred from trim names, package codes, or forum gearbox cheat sheets.
Takeaway
TransmissionStyle is a catalog label. Display it with clear sourcing, allow "not provided," and never use it as a key into invented gear counts. Your free VIN UI stays trustworthy when transmission style is either a real vPIC string with a modest footnote -- or absent.
I maintain VIN Lookup, a free VIN decode based on NHTSA data.
Top comments (0)