# Data types: files, documents, tables, links, dates and colors

Take uploaded files and structured data in a Block and return tables, documents, charts and downloads, with generated controls and checked conversions.

Ports can carry general files and structured data, not only media and text.
Each type has a checked value shape, a generated control and a result layout,
so a Block that declares them needs no custom view.

| Type | Value | Generated control | Default result layout |
| --- | --- | --- | --- |
| `file` | `{kind: "file", assetId, versionId, mimeType, url?, name?, bytes?}`; `mimeType` is `application/pdf`, `text/plain`, `text/csv`, `text/markdown`, `application/json` or `application/zip` | `file` (upload) | `download` |
| `document` | `{schemaVersion: 1, format: "markdown" \| "plain", text, title?}`, up to 1,000,000 characters | `richtext` | `document` |
| `table` | `{columns: [name], rows: [{name: text \| number \| boolean \| null}]}`, up to 500 columns and 100,000 rows | `grid` | `table` (with CSV download) |
| `url` | An absolute `http` or `https` address without credentials | `url` | a link |
| `date` | ISO 8601: `2026-10-09` or `2026-10-09T14:30` (seconds and an offset optional) | `date` (`time: true` for date and time) | a formatted date |
| `color` | `#rrggbb` or `#rrggbbaa` | `color` | a swatch |

Lists of these types (`file[]`, `url[]`, `date[]`, `color[]`) work like other
lists; the `list` control edits `text[]`, `number[]`, `integer[]`, `url[]`,
`date[]` and `color[]` item by item.

Output presentations in `manifest.ui` choose a layout for an output:
`{control: "table", port}`, `{control: "document", port}` (a `document` or
Markdown `text`), `{control: "chart", port, chart: "bar" | "line", x, y}` (a
`table` with optional column names, or a `number[]`), `{control: "code", port,
language}` (`text`, `json` or `object`), `{control: "player", port}` (`audio` or
`video`) and `{control: "download", port}` (`file`, `file[]` or `file-bundle`).
Each control is checked against its port's type when the manifest is
validated. Layouts show Block data as text: links in a document are displayed,
not followed, and downloads go through the host's export policy.

### Files

People upload files to a `file` input from the Block's controls. The host
checks the extension, the declared type, the size (50 MB) and the bytes (a PDF
or ZIP signature, valid UTF-8 text, parseable JSON) before the Block receives a
saved reference. Module Blocks read the bytes with
`stillmade.files.read(input.script)` and save new files with
`stillmade.files.write(bytes, {mediaType: "text/csv", name: "shots.csv"})`,
which returns a `file` value. Files a person uploaded to a Block, or a Block
saved, are indexed in project context as `files` (`file[]`, permission
`context.files.read`), apart from media so media lists stay media.

### Helpers

`@stillmade/block-sdk/data` (also exported from the main entry) has the checks
and builders: `isFileValue`, `isDocumentValue`, `isTableValue`, `isUrlValue`,
`isDateValue`, `isColorValue`, `createTable(columns, rows)`,
`createDocument(text, {format, title})`, `tableToCsv(table)`,
`fileFormatFor(name)`, `checkFileSignature(bytes, mimeType)`, and the
`DATA_VALUE_LIMITS`, `FILE_FORMATS`, `FILE_MEDIA_TYPES` and `DOCUMENT_FORMATS`
tables. `IMPORT_FORMATS` lists every upload the host stores (media and files),
and `inspectMediaImportFile(file, {kinds: ["file"]})` checks a chosen file.

### Conversions

Connections convert between these types with host-owned conversions, version 1:

| Conversion | From | To |
| --- | --- | --- |
| `text-to-url`, `url-to-text` | `text` | `url` (checked), and back |
| `text-to-table`, `table-to-text` | CSV `text` | `table`, and back to CSV |
| `object-to-table`, `table-to-object` | an `object` shaped as a table (for example from `csv-to-table`) | `table`, and back |
| `text-to-document`, `document-to-text` | `text` | a plain `document`, and back |
| `shots-to-shot-plan` | `shot[]` | the Shots workspace's version 1 `shot-plan` |

A shot list reaches the Shots workspace when the output declares the
workspace's meaning: `{"type": "shot[]", "semantic": "production_shot_plan"}`.

### Example: PDF to shot list

`examples/module-pdf-shot-list` is a module Block that takes an uploaded PDF,
reads its text with pdf.js (bundled, its worker code imported directly so
nothing is fetched), plans the shots with one `text.generate` call that has a
JSON schema, and returns a `table` and a `shot[]` the Shots workspace accepts.
