Importer Scaffolder
People switch tools when leaving costs them nothing, and an importer is how a small project removes that cost. Importers fail quietly: a column is renamed, a date is in another format, a record has no match, and data disappears without anyone noticing. This skill builds an importer from a real sample export, with a mapping that is explicit and a rule that nothing is silently dropped.
Required Inputs
Ask for these if not provided:
- A sample export: a few rows of CSV or a JSON excerpt, with any personal data replaced
- The source tool and how users produce the export
- Your data model: the target fields, types and required fields
- Your language and stack for the importer
- Where unmatched data should go: a notes field, an extras column, or a separate file
Output Structure
1. Source profile
What the sample shows: format, encoding, delimiter, header names, date and number formats, nested fields, and anything ambiguous. List assumptions explicitly.
2. Field mapping table
Every source field appears in the table, mapped or not. Unmapped fields go to the extras destination named in the inputs.
3. The keep-everything rule
State it in the code and the docs: no source record is dropped. A record that fails validation is imported with what could be parsed, flagged, and listed in an import report; its raw source is preserved in the extras destination.
4. Importer skeleton
Code in the requested language with these parts, each a small function:
read(source): streams rows; detects encoding and delimiter; never loads a huge file whole
mapRow(row): applies the mapping table; returns { record, warnings, extras }
validate(record): required fields and types; returns problems without throwing
write(record): idempotent upsert keyed on a stable source ID, so re-running an import does not duplicate data
report(): counts of imported, imported with warnings, and per-warning examples
Include a dry-run mode that prints the report without writing.
5. Test fixtures
Fixture files plus the expected result for each:
- the happy path (three normal rows)
- a renamed or reordered header
- an empty required field
- a malformed date and a number with a thousands separator
- non-ASCII text (accents, Chinese characters, emoji)
- a duplicate row (checks idempotency)
- a row with extra unknown columns (checks they land in extras)
6. User-facing instructions
Five to eight steps telling users how to export from the source tool and import, including what the import report means.
Quality Checks
Anti-Patterns
- Silent drops. A skipped row is lost data the user may never notice.
- Mapping by column position. Exports reorder columns; map by header name.
- Loading the whole file into memory. Real exports are bigger than samples.
- Guessing ambiguous dates. If 03/04 could be either order, ask or detect from the whole file, and record the choice.
Example Trigger Phrases
- "Build an importer for Trello JSON exports into my app."
- "Here's a CSV export from Notion, map it onto my data model."
- "Make it easy for users to switch from [competitor] to my project."
- "Write a CSV importer that never drops rows."