GuideComponentsHooksFunctionsTypesTokensSource code on GitHub
Appearance
Language
Pages
Slots

readerAction

A button under an open article, next to Read the original. It is for doing something with that very article: report it, send it somewhere, rate it…

Where in Hodi

When someone opens an article in Hodi's reader, a row of buttons follows the article's text, with Read the original. The plugin's button joins this row.

Example

This button sends the article's id to a route of the plugin:

web/index.tsx
import { ReaderButton, definePlugin, usePluginApi } from 'hodi:sdk'
import { Flag } from 'lucide-react'

const Report = ({ article }) => {
  const api = usePluginApi()
  const send = () => api('/report', { method: 'POST', body: JSON.stringify({ id: article.id }) })
  return (
    <ReaderButton icon={<Flag size={12} />} onClick={send}>
      Report
    </ReaderButton>
  )
}

definePlugin({ readerAction: Report })

Props

Hodi gives the component a single prop, article: the open article. Here are the fields of article:

Props?: optional
article.idstring

The article's id in Hodi.

article.titlestring

The article's title.

article.urlstring

The article's address on the original site.

article.sourceIdstring

The id of the article's source.

article.sourceNamestring

The source's name, such as The Guardian.

Server side

The plugin's route receives the article's id, never an address to open. With the articles permission, the route finds the article again in Hodi:

server/index.ts
'POST /report': async (request, ctx) => {
  const article = await ctx.articles.get(request.body.id)
  const page = await ctx.articles.page(request.body.id)
  …
}
  • ctx.articles.get(id) returns the article, or null if Hodi never listed it.
  • ctx.articles.page(id) returns the article's page, as the site serves it.

So a plugin can't use the reader to open any address it likes.

Good to know

  • How the button is drawn: a ReaderButton, like Hodi's buttons in the same place.
  • Who sees the button: the profiles allowed by audience.