# Wat een route teruggeeft

De standaardpagina, je eigen HTML, JSON, XML, tekst, CSV, bestanden en PDF, en hoe je elk maakt.

Elke route is een leeg canvas. Een route is een map met een `index.tpl`, en wat die template maakt, is het antwoord, verder niets. Nimbly voegt geen eigen layout, omhulling of formaat toe.

- Wil je de standaardpagina, met de head, de assets en inline bewerken, eindig de template dan met `[#html#]`.
- Wil je je eigen HTML-document, schrijf het dan.
- Wil je JSON, XML, platte tekst, CSV, een bestand of een PDF, maak dat dan.

Ze gebruiken allemaal dezelfde shortcodes, data, templates, libraries en rechten. Een site kan ze vrij combineren: een publieke site met de standaardshell, een landingspagina met een eigen document, een JSON-feed, een sitemap en een download voor alleen leden, naast elkaar.

| De route geeft terug | Hoe |
|---|---|
| De standaardpagina | `[#html#]` aan het eind van `index.tpl` |
| Je eigen HTML-document | Schrijf het document in `index.tpl`; zie [Je eigen HTML](/nl/docs/guides/html-shell/) |
| JSON | `[#http-header json#]` en de JSON |
| XML, een feed | `[#http-header xml#]` en de XML |
| Platte tekst | `[#http-header txt#]` en de tekst |
| CSV | `[#http-header csv#]` en de rijen |
| Een bestand | Een library die de headers en inhoud van het bestand stuurt |
| Een PDF | De PDF-module, vanuit een HTML-template |
| Een redirect | `[#redirect url#]` |
| Een statuscode | `[#http-header 404#]`, `403` of `500` |

## Het adres

Een routemap mag een punt bevatten, dus het adres kan een extensie hebben:

```text
ext/uri/projects.json/index.tpl     /projects.json
ext/uri/feed.xml/index.tpl          /feed.xml
ext/uri/export/projects.csv/        /export/projects.csv
```

Een dynamische route werkt op dezelfde manier, bijvoorbeeld `ext/uri/api/projects/(slug)/` die JSON geeft voor één project. Zie [Routing](/nl/docs/concepts/routing/).

## Het contenttype

`[#http-header type#]` aan het begin van een template zet het `Content-Type`:

| Type | Content-Type |
|---|---|
| `json` | `application/json` |
| `xml` | `application/xml; charset=UTF-8` |
| `txt` | `text/plain; charset=UTF-8` |
| `csv` | `application/csv; charset=UTF-8` |
| `css` | `text/css` |
| `js` | `application/javascript` |

Gebruik voor elk ander type, of voor extra headers, een library met de PHP-functie `header()`, zoals hieronder.

## JSON

`ext/uri/projects.json/index.tpl`:

```html
[#http-header json#]
[#data projects filter=published:1 sort=year|numeric|desc#]
[#fmt var=data.projects empty={} type=json#]
```

`[#fmt ... type=json#]` codeert een variabele; `[#get project.title json#]` codeert één waarde, met aanhalingstekens en escaping. De regeleinden tussen de shortcodes kunnen geen kwaad: JSON staat witruimte toe.

Schrijf voor een eigen vorm de JSON in de template:

```html
[#http-header json#][#data .config.site#]{"site": [#get data.config.site.name json#], "projects": [#data-count projects#]}
```

Heeft het antwoord logica nodig, bouw het dan in een library:

```php
<?php
// ext/lib/project-stats.php

function project_stats_sc($params)
{
    load_library('data');
    $projects = data_read('projects') ?: [];
    header('Content-Type: application/json');
    return json_encode([
        'total' => count($projects),
        'per_sector' => array_count_values(array_column($projects, 'sector')),
    ]);
}
```

`ext/uri/stats.json/index.tpl` bevat één regel: `[#project-stats#]`.

## XML en feeds

`ext/uri/feed.xml/index.tpl`:

```html
[#http-header xml#]<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Fieldwork projects</title>
    [#data projects filter=published:1 sort=year|numeric|desc limit=20#]
    [#repeat data.projects tpl=feed-item#]
  </channel>
</rss>
```

met een template per item, `ext/uri/feed.xml/feed-item.tpl`:

```html
<item>
  <title>[#fmt var=item.title type=plain#]</title>
  <link>[#base-url#]/projects/[#item.title_slug#]</link>
  <description>[#fmt var=item.description type=plain#]</description>
</item>
```

Elke site antwoordt al op `sitemap.xml` en `robots.txt`. Een resource voegt zijn records toe aan de sitemap met een instelling `sitemap` in zijn `.meta`.

## Platte tekst

```html
[#http-header txt#][#data .config.site#][#get data.config.site.name#]
Projects: [#data-count projects#]
```

## CSV

```html
[#http-header csv#]title,sector,year
[#data projects filter=published:1#][#repeat data.projects tpl=csv-row#]
```

met `csv-row.tpl` dat één regel per record bevat. De admin exporteert ook elke resource voor gebruikers met `export-<resource>`.

## Bestanden

Bestanden die naar de mediabibliotheek zijn geüpload, worden geleverd op `/download/<uuid>`, met hun opgeslagen type en naam.

Om een bestand te leveren volgens je eigen regels, zoals een document voor alleen leden of een bestand dat op verzoek wordt gemaakt, laat je een library het sturen:

```php
<?php
// ext/lib/member-document.php

function member_document_sc($params)
{
    load_library('access');
    if (!access_by_feature('view-member-documents')) {
        http_response_code(403);
        exit();
    }
    $path = $GLOBALS['SYSTEM']['file_base'] . 'ext/data/.member-files/handbook.pdf';
    header('Content-Type: application/pdf');
    header('Content-Disposition: attachment; filename="Member handbook.pdf"');
    header('Content-Length: ' . filesize($path));
    readfile($path);
    exit();
}
```

`ext/uri/members/handbook.pdf/index.tpl` bevat `[#member-document#]`. Met hetzelfde patroon stuur je een ZIP, een afbeelding die ter plekke wordt gemaakt of een agendabestand: de headers en de bytes zijn van jou.

## PDF-documenten

De PDF-module maakt van HTML uit je eigen templates een PDF, cachet het resultaat en stuurt het als download:

```bash
./nimbly module:install pdf
```

```php
load_library('pdf');
$pdf = pdf_render_cached_document([
    'paper_size' => 'a4',
    'orientation' => 'portrait',
    'pages' => [$html],
]);
pdf_send_download($pdf, 'Project-overview.pdf');
exit();
```

De cachesleutel omvat het document en de renderer, dus een gewijzigde tekst of template levert vanzelf een nieuwe PDF op.

## Afbeeldingen

Geüploade afbeeldingen worden geleverd op `/img/<uuid>/<size>`, in het formaat dat het adres vraagt en als WebP: `800w` voor een breedte, `400x400c` voor een uitsnede. In templates schrijft `[#get-img-html#]` de responsieve markup. Zie [Media en inline bewerken](/nl/docs/guides/media/).

## Redirects en statuscodes

```html
[#redirect [#base-url#]/en/#]
```

```html
[#http-header 404#][#http-header json#]{"error": "not found"}
```

Een dynamische route die een request niet accepteert, valt door naar de 404-pagina van de site, die `ext/uri/errors/404/` kan vervangen.

## De REST API

Elke resource antwoordt ook op `/api/v1/<resource>` met JSON, om te tonen, lezen, maken, wijzigen en verwijderen, met de rechten van de aanroeper. Gebruik die voor apps en integraties, en schrijf eigen routes voor wat de API niet dekt. Zie de [naslag van de REST API](/nl/docs/reference/api/).
