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
- Visit
- Source code
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".
One choice per columnThe obvious shape
- Has to pick a destination, always
- When nothing fits it still names one, confidently
- Nothing in the answer means "none of these"
A yes/no per pair, plus a guardWhat it does
- Every pair scored on its own
- A column can score low everywhere, which is what a missing field looks like
- The guard asks directly whether it belongs nowhere
A 23 column warehouse export, end to end
- Normalise and match exactlyCase, accents, separators. Nothing that is a judgementfree
- Ask about everything left23 columns × 10 destinations, plus one guard each253 questions
- One callThe whole matrix comes back as numbers675 ms
- Apply the threshold, in your codeBest free pair first, repeat. Below the bar becomes a dropdown0.75
Mapped, and cost10 of 10, $0.0012
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

