Guillaume Duvernay

Open source

jev-table-import-mapper

Your users upload a CSV. Its columns are never your columns.

A small JavaScript library for the import screen every product ends up building. It matches an uploaded file's columns onto your destination table, returns a probability for each match, and hands back the ones it is not sure about. Two files, no dependencies.

Role
Author
Year
2026
Stack
JavaScript, OpenRouter, Jev

Code first, and only for what code can settle

Stage one normalises case, accents and separators, then matches on strict equality. First Name and first_name are the same word typed differently, so that pair is locked for free and can never be wrong. Company Name and company are not the same word, and neither are team and department: those are questions, so they go downstream. On a clean HubSpot export that settles 7 columns out of 10 before any network call.

One call for everything left, as a matrix

Stage two asks one independent yes/no per remaining pair rather than one multiple choice per column, plus a guard question asking whether a column belongs nowhere. That shape is the design decision. A multiple choice has to name a winner even when nothing fits; a matrix is allowed to score low everywhere, which is what a missing field looks like. A 23 column export against a 10 column table is 253 questions, one call, 675 ms and about a tenth of a cent.

The decision stays in your code

The call returns the whole matrix, not a verdict. The threshold is a constant you move, not a behaviour you prompt for, and anything below it becomes a ranked dropdown instead of a guess. Because the number exists anyway the interface can print it, so a match at 81% reads differently from one at 98%.

Where it stops

Tested on nine real exports against three destination tables of ten columns each. A destination schema of around 40 columns would need more than one call, and the second budget in the model's context window does not split, so a very wide table is a hard limit rather than a slow path. I have not tried it.

The shape of the questions is the whole thing

One yes/no per pair, not one multiple choice per column. It sounds like a detail and it decides whether the library can say "this column belongs nowhere".

Roughly a third of the columns on a real export belong nowhere in your table. Only the second shape can say so.

A 23 column warehouse export, end to end

Twenty-one times the questions costs 1.45 times the wait: 12 questions take 464 ms and 253 take 675. If each question were its own call this file would be a two minute wait.

7 of 10columns settled in code, before any call

675 msfor 253 questions in a single call

$0.0012to map a 23 column warehouse export