# Previews

> Open PDFs, DOCX, images, syntax-highlighted code, CSV and XLSX tables, audio waveforms and video in the browser, and draw charts in Markdown from your data files. No download, no extra software.

Hyperfile renders rich previews for many file types directly in the browser.

## Supported Formats

### Images
JPEG, PNG, GIF, WebP, SVG, TIFF, and BMP.

### Documents
PDF, DOCX, and plain text / Markdown. Markdown files can draw charts from your data files — see [Charts in Markdown](#charts-in-markdown).

### Code
Syntax-highlighted previews for JavaScript, TypeScript, Python, Go, Rust, Java, C/C++, PHP, HTML, CSS, SQL, JSON, XML, Markdown, and more.

### Tabular Data
CSV, TSV, XLSX, and XLS files render as interactive data tables with sorting and filtering.

### Audio & Video
MP3, WAV, FLAC, OGG, MP4, WebM, and MOV with native playback controls and waveform visualization for audio.

## Preview Panel

Click any file to open the preview panel on the right side of the screen. The panel adapts to the file type and provides download, version history, and metadata controls.

## Charts in Markdown

A code block that opens with `` ```chart `` in a Markdown file draws a chart from a CSV, TSV, XLSX, XLS, JSON or JSONL file in the same filesystem. CSV, TSV and JSONL files can be any size, since they are read as they download. JSON, XLSX and XLS files are read whole in your browser, so a very large one can be slow to draw. Charts draw in the file preview and in the editor's preview pane, and they print.

### Quick form

```chart
type: bar
sources:
  sales: ../data/sales.csv
x: sales.Month
y:
  - sales.Revenue
  - sales.Cost
title: Sales by month
```

`sources` names each file once. `x` and `y` always start with a source name, like `sales.Month`, and `y` can be one column or a list of them. `type` is `line` (the default), `bar`, `scatter`, `pie`, `doughnut` or `area`, which is a filled line.

Paths are relative to the Markdown file (`./`, `../`) or from the top of the filesystem (`/data/sales.csv`). Unlike an image link, a source path is a plain file path rather than a URL: `%`, `#` and `?` are ordinary characters, so `./50%.csv` and `./Q1#2.csv` name exactly those files, and `%20` stays `%20` rather than becoming a space.

### Full form

For more control, write a [Chart.js](https://www.chartjs.org/docs/latest/) config and put references where the data goes:

```chart
type: line
sources:
  sales: ../data/sales.csv
  forecast:
    path: ../data/forecast.xlsx
    sheet: FY26
data:
  labels: sales.Month
  datasets:
    - label: Revenue
      data: sales.Revenue
    - label: Forecast
      data: forecast[C2:C13]
options:
  plugins:
    legend:
      position: bottom
```

References are read at `data.labels` and at each dataset's `data`. A value there that is not a reference, like `sales report`, stays as written. A source name followed by `.` or `[` is always read as a reference, so a label like `sales.Q1 (est)` is reported as a bad reference rather than drawn as text. Everything else goes to Chart.js as written, so any [Chart.js option](https://www.chartjs.org/docs/latest/) works, with two additions: a dataset that sets no colours gets the theme's, and a long line chart of sorted number points on a `linear` x axis is thinned out (Chart.js decimation) so it draws quickly. Setting your own `parsing` or `decimation` option, or `parsing` on any dataset, turns the thinning off. The config is YAML or JSON, so options that need a function (callbacks) are not possible.

### A chart in its own file

Put either form in a `.yaml` or `.json` file and point the block at it:

```chart
../charts/sales.chart.yaml
```

Paths inside that file are relative to the file itself, not to the Markdown file. A chart file can be up to 1 MB.

### References

| By name | Means |
|---------|-------|
| `sales` | The whole table |
| `sales.Revenue` | The column headed "Revenue" |
| `sales["Unit Price"]` | A heading with spaces, dots or brackets |
| `forecast.FY26.Revenue` | Sheet FY26, then its column "Revenue" |
| `stats.monthly.visits` | JSON: into `monthly`, then the column "visits" |

| Spreadsheet ranges | Means |
|--------------------|-------|
| `sales[B]` | Column B |
| `sales[A2:A13]` | Cells A2 to A13 |
| `sales[2:2]` | Row 2 |
| `sales[A1:C13]` | Columns A to C, rows 1 to 13, without the header row |
| `forecast.FY26[C2:C13]` | A range on sheet FY26 |

| Index slices | Means |
|--------------|-------|
| `sales[:,0]` | The first column |
| `sales[0,:]` | The first data row |
| `sales[1:,0]` | The first column, from the second data row on |
| `sales[:,0:2]` | The first two columns |
| `sales[-12:,1]` | The last twelve rows of the second column |

- **The header row is never data.** It is the first row that is not empty, usually row 1. It names the columns, so `sales[B]` and `sales.Revenue` both start on the row after it.
- **A comma inside the brackets means `[rows, columns]`.** These count from 0 over the data rows, like Python, and a negative number counts from the end. When the header is on row 1, `sales[A2:A13]` and `sales[0:12,0]` are the same cells.
- **Inside brackets, a letter is a column.** `sales[B]` is always column B, while `sales.B` is the column headed "B".

### Source options

A source can be a map instead of a path:

```yaml
sources:
  forecast:
    path: ../data/forecast.xlsx
    sheet: FY26
  raw:
    path: ./readings.csv
    header: false
```

- `sheet` picks a workbook sheet by name, or by number counting from 1. Without it, write the sheet in the reference (`forecast.FY26.Revenue`), or leave it out to read the first sheet.
- `header: false` is for a file with no header row. Every row is then data, and the columns are named A, B, C and so on.

### JSON and JSONL

- An array of objects is a table, with the keys as its columns.
- Reach nested data by its keys: `stats.monthly.visits` is the `visits` column of the `monthly` array.
- With a source named `myData` pointing at a file that holds `{"x": [1, 2, 3]}`, `myData.x` is that list, read as one column.
- A JSONL file is one object per line, and reads like an array of objects. It is already a list, so there are no keys to descend: a JSONL reference takes at most one column name after the source, like `events.visits`.

### Shapes

- One column (or one row) is a series of values, or the labels along the axis.
- On a `scatter` or `bubble` chart, two columns, or a list of two references, become points (x, y). On a `type: bubble` chart, which needs the full form, a third column sets each bubble's size. On any other chart a data position takes one column.
- Blank cells are gaps in the line.
- Numbers stored as text become numbers. A number written with a thousands comma, like `1,000`, stays text.

### Lists of references

Write a list of references in block form, one `- item` per line. Inside a short `[a, b]` list, the `[` and `,` in a reference confuse YAML.

```chart
type: scatter
sources:
  stats: /data/stats.json
data:
  datasets:
    - label: Signups per visit
      data:
        - stats.monthly.visits
        - stats.monthly.signups
```

### If a chart does not render

The block shows its source, with the reason underneath. The usual causes are:

- A path that names no file — "no file at …".
- A column name that is not in the file. The message lists the columns the file does have.
- An `x` or `y` that does not start with a source name, like `x: Month` instead of `x: sales.Month`.

### Checking a chart

Agents connected to Hyperfile over MCP have a `lint_file` tool. It checks every chart block in a file, along with its frontmatter, code blocks and links, and names the line of each problem. If it reports a YAML error on a short `[a, b]` list of references, an item in it holds `[`, `]`, `{`, `}` or `"` — like `[sales[B], sales[C]]`. Quote that item, or write the list in block form instead — see [Lists of references](#lists-of-references).

---

Canonical HTML version: https://hyperfile.io/docs/web/previews/
