CSV Import step-by-step guide
This walks through importing a real dataset — computers, and the offices, countries, and regions they belong to — including the two-pass trick needed for a Workflow attribute.
1. Look at the source file
Say the source file has 8 columns and 50 rows of computer inventory data.
2. Design the data model
Go column by column and decide whether each one should become a type or an attribute:
| Column | Type or attribute? | Reason |
|---|---|---|
| Computer | Type | Worth tracking as its own entity with several attributes. |
| Serial Number | Attribute (Text, set as label) | The unique identifier for a computer. |
| MAC Address | Attribute (Text) | — |
| Status | Attribute (Workflow) | Drives lifecycle/process tracking. |
| Region | Type | Splitting these into their own types makes "which offices do we have in this country?" answerable, and gives a better browsing experience than flattening them into text attributes. |
| Country | Type | |
| Office | Type | |
| Location | Attribute (Location) | CSV import can map an address directly to a Location attribute. |
Serial Number (label)
MAC Address
Status (Workflow)
Location
Office
Country
Region
Conceptual diagram, not a screenshot — this is an entity-relationship sketch of the model above, not a captured UI screen. Each arrow is a Reference attribute pointing from the referencing type to the referenced type, which is exactly why the import order below runs right-to-left: Region first, Computer last.
3. Prepare Starhive for the import
Create the workflow first, matching how the team actually works — this is what the Status column will map to.
Creating the workflow starts with just a name and an optional description:
Mockup, not a screenshot — confirmed against CreateWorkflowModal.tsx.
Creating the workflow opens its editor, where you add the states and the transitions between them:
Mockup, not a screenshot — confirmed against SettingsWorkflowEditor.tsx: a Transitions table (From → Transition → To) on the left and a States list on the right, each with its own "Create" button. The ✓ marks an end state (states.endStateTooltip). "Unassigned", "In Use" and "Retired" are only this guide's example state names, not fixed values — you name your own states to match your team's process.
Then create the types and attributes from the data model above.
Mockup, not a screenshot — confirmed against TypeConfigPanel.tsx and its AttributesTable: an inline-editable type name/description header, a "+ Attribute" button, and a row per attribute with its type badge. System attributes (Avatar, Created, Updated, Creator) also appear here on every type but are omitted above for brevity — see the Getting Started guide for those.
4. Import in dependency order
Because Computer references Office, which references Country, which references Region, import in this order:
- Regions
- Countries
- Offices
- Computers, with every Status temporarily set to the workflow's initial state
- Computers again, with the real Status values
Steps 4 and 5 are both needed because the workflow engine requires every object created with a Workflow attribute to start in that workflow's initial state — you can't create an object directly into an arbitrary later state.
Importing Regions
From the type's context menu, choose CSV Import, select the file, and map its single column to the Region type. Turn on Identifier for that column so re-running the import doesn't create duplicate regions.
Mockup, not a screenshot — confirmed against ImportCsv.tsx: this button lives on the type's objects view, next to the object list, rather than in a dedicated dropdown menu.
Selecting it opens the file upload step:
Mockup, not a screenshot — confirmed against ImportFileUpload.tsx (csvImport.fileUpload.instructions.* strings).
Then the field mapping step, with Identifier turned on for the single Region column:
| Identifier | CSV header name | Attribute | |
|---|---|---|---|
| Region | → | Name |
Mockup, not a screenshot — confirmed against ImportMapping.tsx (the "Field mapping" modal title is csvImport.mapping.modal.title). The Identifier toggle is a Mantine Switch per row, disabled when the mapped attribute can't act as an identifier.
Importing Countries, then Offices
Same process, using a file with Country, Region columns (mapping Region as a reference to the
regions you just imported), then a file with Office, Country columns.
Importing Computers (two passes)
Pass one: import with every Status value overwritten to the workflow's initial state (e.g. "Unassigned"). Region, Country, and Office are already imported and don't reference Computer, so Starhive can auto-map Office, Status, Location, and Computer — only Serial Number and MAC Address need manual mapping.
Pass two: re-import the original file, unchanged, so the real Status values are applied. Since every object already exists (matched by the Serial Number identifier), this pass only updates the Status field.
Its field mapping screen:
| Identifier | CSV header name | Attribute | |
|---|---|---|---|
| Serial Number | → | Not mapped | |
| MAC Address | → | Not mapped | |
| Status | → | Status | |
| Office | → | Office | |
| Location | → | Location |
Mockup, not a screenshot — confirmed against ImportMapping.tsx. Every Status value in this pass's file was overwritten to "Unassigned" beforehand, so it's safe to create every Computer object before real statuses are known. Serial Number is the identifier for the second pass, so its toggle is on.
Its field mapping screen, now with every header auto-mapped:
| Identifier | CSV header name | Attribute | |
|---|---|---|---|
| Serial Number | → | Serial Number | |
| MAC Address | → | MAC Address | |
| Status | → | Status |
Mockup, not a screenshot — same ImportMapping.tsx screen as pass one; Office and Location rows are omitted here since they're unchanged. Matching every object by the Serial Number identifier is what turns this into an update instead of a second set of duplicate Computers.
The final result — every Computer now carries its real Status:
| Serial Number | Office | Status |
|---|---|---|
| SN-10231 | Stockholm | In Use |
| SN-10232 | Stockholm | In Use |
| SN-10198 | Berlin | Retired |
Mockup, not a screenshot — illustrative data only. "In Use" and "Retired" are this guide's own example workflow states from the workflow editor mockup above, not fixed product values.
Notes
- CSV files must be UTF-8 encoded.
- Multi-cardinality attributes (Reference, Option) accept several values in one cell, separated by
|:
Name,Continent,Neighbour
Sweden,Europe,Norway|Finland|Denmark
Germany,Europe,Poland|Belgium|Austria|France|Netherlands|Czech Republic
Turkey,Europe|Asia,Greece|Bulgaria|Georgia|Armenia|Iran|Iraq|Syria