Skip to Content
Data LayerDataSchema

DataSchema

The DataSchema is the contract that drives presentation and validation for a tenant’s records — browse cards, search & filters, and the detail page. It validates the data on every record.

Fields

When you apply a schema, each field carries:

  • a label — what the field is called on cards and the detail page;
  • a typestring | number | boolean | date | url | image | enum | array. There is no location / geo type — geo is handled by the auto-pair on lat/lng columns. There is no multi-value-enum — compound values like "Mon, Tue" need preprocessing in the source CSV;
  • searchable — whether the field is included in the full-text index;
  • facetable — whether the field is exposed as a sidebar filter on /explore;
  • an optional premium flag — gates the field’s value behind a subscription on /explore (locked for non-subscribers, redacted server-side). See Search & Explore → Premium columns;
  • an optional role — see below;
  • an optional card-visibility hint — see below.

Roles

A field’s role tells the renderer where it belongs — you tag what a field means, and the card and detail templates place it accordingly. You don’t author layout.

For the full list of roles you can assign, run:

shipmore schema field set --help

cardVisibility

Solves the “we have 30 fields, what shows on the card?” problem. cardVisibility decides what surfaces on the card versus what stays on the detail page:

ValueMeaning
primaryMust show on card; ordered first
secondaryShow on card if room allows
detail-onlyOnly on detail page
nullLet the platform auto-rank (default)

Auto-inference at import

shipmore schema infer proposes a starting type, role, searchable, and facetable for each column. It’s a best-effort starting point — review the proposed fields and adjust with shipmore schema field set / schema field drop, then re-run shipmore schema apply.

Schema and data stay separate

The schema — field definitions, roles, and the searchable / facetable flags — is kept separate from the rows themselves and from how source columns map in. That separation is what lets you re-run an import after renaming a source column without rebuilding the schema, and update the schema without re-importing your data.