Modules
Tayori (便り) is product news for Phoenix: what the app has to say to its people, written in an admin the app mounts, and read in the app, on a public page, in feeds and in emails.
Writing the news with AI, with the key of the app: a draft from what shipped, a translation into another language, and changes to a passage (rewrite, shorter, warmer, fix the spelling).
The news as JSON, for a frontend that Phoenix does not render (React,
Vue, Svelte, a mobile app), and as HTML for <tayori-news>, the
element of Tayori's script. Mounted with Tayori.Router.tayori_api/2
An entry announced in the app, as a popup, a toast or a banner, until
its date (Tayori.Entry's :announce): the :announcements feature.
The categories of the news (Tayori.Category), in their order. The
admin manages them; a script or a seed can too
A category of entries ("New", "Improved", "Fixed"): a key, its name in each language, a colour and its place in the list. Entries keep the keys of their categories.
A change in the inbox (Tayori.Inbox): one thing that shipped, as a
source brought it, before it becomes an entry or part of one.
The news in a LiveView: a button with the count of unread entries, the
panel it opens, and the announcement of the moment. They read @tayori,
from Tayori.Live.
The options of Tayori, given to its child in the app's supervision tree
An entry made of the inbox's changes (Tayori.Inbox): the changes
waiting, for the public, put in an entry for the people who use the app.
The news on another origin than the app's: a marketing site, a help
centre, a page the app does not serve. The :embed feature.
Writes the news: what the admin does, for a script or a seed too.
An entry of the news: one thing the app has to say, in one or more
languages (Tayori.Translation).
Changes from GitHub: a webhook of the repository, at
POST /hooks/github of the JSON API (Tayori.API). The
Automation guide adds it in GitHub.
The changes that shipped, before they become entries: what the app's
sources bring (Tayori.Source), what its CI, GitHub and its own code
add, what an agent adds over MCP. The admin reads them in the inbox,
puts aside what readers need not know, and a digest makes an entry of
the rest (Tayori.Digest).
Changes sent to the inbox over HTTP, by CI or another service:
POST /changes of the JSON API (Tayori.API), with the ingest token.
What a publication sends, and how: the emails to the subscribers (the
:subscriptions feature), the webhooks (the :webhooks feature) and
the call to the app's :notifier.
The news in the app's LiveViews: an on_mount hook that gives each
LiveView of a live_session the @tayori assign, for the components of
Tayori.Components.
The @tayori assign
The names of the languages of the entries, in their own language, for the admin's tabs and the readers' language links.
An MCP server for the news, built on Sake: an MCP client (Claude Code, Claude Desktop, an agent) reads the news and the inbox, adds what shipped, drafts entries, writes them in each language with their screenshots, and publishes them when it is asked to, as the admin of the app it acts for.
The words around the news: the button, the panel, the public page and the feeds ("What's new", "Show more"). The entries are the app's own, written in the admin in each language.
The tables of Tayori, in a migration of the app.
What the app does when an entry is published, beyond what Tayori sends
itself (the emails of the :subscriptions feature, the webhooks of the
:webhooks feature): a push, an email to the app's own users, a post
elsewhere. The app knows its readers, its mailer and its voice.
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
Readers react to an entry with an emoji, one of the app's (:reactions
of Tayori.Config), and each reaction counts once per reader. The
:reactions feature.
Who reads the news, as the app knows them. The app's resolver builds it
from the app's own user (Tayori.Resolver.resolve_reader/1)
How Tayori knows the people of the app: who may write the news in the
admin, and who reads it. The app writes one module, from what it
already has (its users, their plans and roles, its admin session), and
gives it to the router macros (Tayori.Router) and to Tayori.Live
Mounts Tayori in the app's router.
The news as JSON, mounted with tayori_api/2 (imported with
Tayori.Router). See Tayori.API for the routes, and the
Any frontend guide.
The public page of the news, each entry's page, and the feeds, mounted
with tayori_page/2 (imported with Tayori.Router). See Tayori.Page
for the routes, and The public page guide.
Where the changes of the inbox come from: a file of the app, a folder of
files, a service. A source is a module with changes/1, named in the
:sources of the :inbox config with its options
The changes of a CHANGELOG.md in the Keep a
Changelog format: each item of each
release is a change.
The changes of a folder of Markdown files, one change in each: written in the pull request that makes the change, read when it ships. The pattern of Changesets and towncrier, whose files it reads.
Readers who get the news by email, from the public page: the
:subscriptions feature.
Helpers for Phoenix.LiveViewTest, to test the news in an app's
LiveViews with no browser: write entries, read the count of unread
entries, open the panel and read it.
An entry in one language: its title, an optional summary (what the
panel and the emails show), and its body, a Kotoba.Content.
The views of the entries, by day and by where they were read: the
:analytics feature.
Tells other places of each entry when it is published: the :webhooks
feature. The admin adds them in Settings
The Oban worker of Tayori: an email to a subscriber, a webhook, or the
call to the app's notifier, when an entry is published; a digest of the
inbox, or the email of a period's entries, on schedule. Tayori enqueues
its jobs itself, with the :oban option of Tayori.Config; see
Tayori.Jobs.
Mix Tasks
Builds the bundles and style sheets of Tayori into priv/static.
Generates the migration of Tayori's tables in the app's repo: the one that installs them, or, after an upgrade of Tayori, the one that brings them to its latest version.
Adds changes to Tayori's inbox (Tayori.Inbox), in two ways.
Installs Tayori in a Phoenix application.
Checks the built files before a release of Tayori.