# `Tayori.Page`
[🔗](https://github.com/hattoriai/tayori/blob/v0.1.0/lib/tayori/page.ex#L1)

The public page of the news, its entries one by one, and its feeds
(Atom and JSON Feed), mounted with `Tayori.Router.tayori_page/2`:

    scope "/" do
      pipe_through :browser
      tayori_page "/changelog", title: "Atelier news", description: "What we ship, every week."
    end

It shows the entries for everyone (those with no segments), unless it
has a resolver and the reader it gives sees more. It is in the reader's
language when the entry has it: the reader's, `?lang=`, or the
browser's (`Accept-Language`).

## The routes

  * `GET /` - the newest entries, whole, the pinned ones first; the
    categories to filter by (`?category=`), a search (`?q=`), and the
    older ones (`?before=<slug>`).
  * `GET /:slug` - one entry, with the entries on either side.
  * `GET /feed.xml` and `GET /feed.json` - Atom and JSON Feed, of the
    newest 20 entries (`?category=` for a category's).
  * `GET /sitemap.xml` - the entries, for search engines.
  * `GET /preview/:token` - an entry before it is published, from the
    admin's preview link: valid a week, never indexed.
  * `POST /:slug/react` - a reaction of the reader (the `:reactions`
    feature), and back to where it was.
  * `POST /subscribe`, `GET /subscription/confirm/:token`,
    `GET` and `POST /subscription/unsubscribe/:token` - the emails (the
    `:subscriptions` feature).

It renders its own document, in Tayori's theme or Sumi's, light or dark
as the reader's system is, with the tags of search engines and shared
links (a description, Open Graph, the cover as its image, the languages
and a JSON-LD article), unless the app gives its own root layout
(`layout: {MyAppWeb.Layouts, :root}`), which then gets
`@inner_content`, `@conn`, `@page_title`, `@locale`, `@description`,
`@canonical`, `@feed`, `@meta` (the tags, as a list of maps) and `@head`
(the same tags rendered, `head/1`), and the app's page loads
`tayori.css` itself.

The forms (reactions, subscribe) post with the session's CSRF token: the
page belongs behind the app's `:browser` pipeline.

# `head`

The tags of a page for the `<head>` of the app's own layout (the
`:layout` of `tayori_page`): its canonical address, the description,
Open Graph and Twitter cards, the addresses of its languages, an
entry's JSON-LD and the link to the Atom feed. Not the `<title>`, which
the layout writes from `@page_title`.

The layout gets them rendered, as `@head`:

    <head>
      <title>{@page_title}</title>
      {@head}
    </head>

## Attributes

* `meta` (`:list`) (required) - the tags, as the layout's `@meta` has them.
* `canonical` (`:string`) (required)
* `feed` (`:string`) (required)
* `title` (`:string`) (required) - the title of the feed's link.
* `nonce` (`:string`) - the nonce of the JSON-LD script. Defaults to `nil`.

# `preview_token`

```elixir
@spec preview_token(term(), Ecto.UUID.t()) :: String.t()
```

The token of a preview link of an entry, signed with the endpoint's
secret: the admin makes it. `endpoint` is a conn, a socket or an
endpoint module.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
