Import

Bulk-create animals from an Excel template. Built for breeders moving from a spreadsheet, importing a hatching season, or seeding a new space with an existing collection.

The import lives at Animals → Import in the app sidebar.

Flow

The import is a three-step wizard:

  1. Upload. Drop an .xlsx file. Download the template if you need it — the same template works for any species.
  2. Preview. Every row is validated. The preview shows errors (red), warnings (amber), and valid rows (green) per row, with the row number and a summary of detected fields. Errors are clickable to see the exact rule that failed.
  3. Confirm. If there are no errors, click Import. Animals are created in a single database transaction — either every row lands, or nothing does. Warnings don't block; they're preserved on the animal's notes when relevant.

Up to 1000 rows per import. The example rows at the top of the template are placeholders — clear their contents before importing, don't delete the rows themselves (deleting breaks the dropdown ranges).

The template

The template is generated server-side from the live catalog and the app's enums. It always reflects the current species, trait names, and inheritance rules — there's nothing to keep in sync manually.

It includes:

  • Two-row grouped headers. Top row groups columns logically (e.g., Date of Birth spans Month + Year; each Trait N spans Name + Type + Het%). Bottom row is the actual field name. Headers are frozen so they stay visible while scrolling.
  • Dropdowns for every enum field: species, sex, maturity, origin, state, birth month, birth year, trait names, trait types, het percentages. Each dropdown also has a "-" option to clear a value you accidentally picked.
  • 12 trait slots per animal, grouped and collapsible. Most animals use 1–4; the rest stay tucked away.
  • A "Traits Reference" sheet listing every trait name available per species and its inheritance type.
  • An "Instructions" sheet with batch-entry shortcuts and a quick recap of the rules.

The template works in Excel desktop, Excel web, and Google Sheets. Long dropdowns (species, years, trait names) use named ranges so they aren't dropped by Excel's 255-character formula limit.

Mixed species in one file

Mix species freely in the same file (up to 1000 rows). Each row's Species column tells the importer which catalog to validate trait names against. "Albino" on a corn-snake row resolves to the corn-snake Albino; the same name on a ball-python row resolves to the ball-python entry.

Excel/Sheets shortcuts that save time

  • Cmd+D / Ctrl+D — fill down. Select a cell with a value, extend the selection downwards, hit the shortcut. Useful for filling sex on a run of male animals.
  • Drag-fill — small square at the bottom-right of a selected cell. Drag it down to copy.
  • Cmd+Enter / Ctrl+Enter — fill a multi-cell selection with one typed value. Select the range first, type, then hit the shortcut.

Validation philosophy

The validator is intentionally permissive on data, strict on structure. Specifically:

  • Trait expression vs inheritance is enforced by default. Recessive → visual or het; codominant → visual or super; dominant / polygenic / unknown → visual only. If a trait carries inheritanceDisputed: true in the catalog (e.g., Pied-Sided, Aztec), any expression is accepted with a warning preserved on the row. See Disputed claims for the rationale.
  • Trait names are resolved against the catalog by species. "Albino" on a ball-python row resolves to ball-python:albino; the same name on a corn-snake row resolves to corn-snake:amelanistic's alias. Cross-species typos surface as errors.
  • Duplicate codes block the import. Both within the file and against codes that already exist in your space. A code collision raises an error on the row; you can't accidentally overwrite an existing animal.
  • Birth month + year combine to the 1st of the month. Stored as UTC midnight, matching how the rest of the app stores date-of-birth (the new-animal form has the same shape).
  • Polygenic with bloodline hint. Polygenic lines (Okeetee, Miami, Red Factor, Pied-Sided) are recorded as expressed traits; the bloodline string on the animal is built from the trait expressions.

For the full set of rules see docs/architecture.md in the developer docs.

What's NOT imported

The importer covers the animal record itself: identity, species, sex, maturity, origin, birth month/year, breeder info, license/chip numbers, locality, notes, state, traits, and optional initial weight. It does not import:

  • Housing (rack/tub/cage) — assigned in the app after import, so existing housing layouts don't constrain the file format.
  • Feedings, weighings, sheddings, medications — these are activities tied to specific timelines; importing them in bulk is a separate flow not shipped yet.
  • Clutches and sales history — historical breeding records and past sales are recorded in the app, not imported.
  • Photos — added per-animal through the gallery after import.

Errors you might hit

The preview groups errors by row. Common ones:

  • "Code already exists in this space" — pick a different code, or fix the duplicate inside the file.
  • "Trait 'Banana' is codominant — only visual / super allowed" — change the trait's type column to visual or super.
  • "Unknown trait 'XYZ' for species 'Corn Snake'" — the trait isn't in the catalog for that species. Check the Traits Reference sheet inside the template for the available list, or open an issue if a real morph is missing.
  • "Invalid date of birth" — Month and Year columns are dropdowns; if you pasted a different format, clear the cells and use the dropdowns.

If an error doesn't make sense, the row's expanded view shows the field name and the resolved (canonicalised) value the validator saw — useful when you're not sure why something was rejected.