# blog (https://docs.salla.dev/twilight/react/api/modules/blog)



Use `blog` for a blog index, an article page, or the category, tag and author listings. All calls are public.

```ts
import { blog } from '@salla.sa/twilight-theme-engine/api/blog';

const overview = await blog.get();
const { data, cursor } = await blog.articles.list({ category: categoryId }); // categoryId: string
```

## Methods [#methods]

| Method                      | Parameters                           | Returns                             | Request                  | Login needed |
| --------------------------- | ------------------------------------ | ----------------------------------- | ------------------------ | ------------ |
| `blog.get`                  | `signal?: AbortSignal`               | `Promise<BlogOverview>`             | `GET blog`               | No           |
| `blog.articles.list`        | `params?: BlogArticlesListParams`    | `Promise<BlogArticlesListResponse>` | `GET blog/articles?...`  | No           |
| `blog.articles.find`        | `id: string`, `signal?: AbortSignal` | `Promise<ArticleDetail>`            | `GET blog/articles/{id}` | No           |
| `blog.articles.findOrThrow` | `id: string`, `signal?: AbortSignal` | `Promise<ArticleDetail>`            | Same as `find`           | No           |

* `BlogArticlesListParams`: `category`, `author`, `tag` (strings), `page`, `cursor`, `signal`. Only the fields you set go into the query string.
* `BlogOverview`: `{ categories, slides, articles, popular }`, each an array.
* `BlogArticlesListResponse`: `{ data, categories?, category, author, tag, cursor }`, where `cursor` is `{ next?, previous?, current }`.

## Queries [#queries]

| Query                       | Key                            |
| --------------------------- | ------------------------------ |
| `queries.overview()`        | `['blog', 'overview']`         |
| `queries.articles(params?)` | `['blog', 'articles', params]` |
| `queries.article(id)`       | `['blog', 'article', id]`      |

No key includes the locale or the active scope. Blog content is language-specific, so add the locale to your own key if the language can change without a reload. Each query passes TanStack Query's `signal`, so leaving the page cancels the request.

```tsx title="app/components/BlogList.tsx"
import { useQuery } from '@tanstack/react-query';
import { blog } from '@salla.sa/twilight-theme-engine/api/blog';

export function BlogList({ categoryId }: { categoryId: string }) {
  const { data } = useQuery(blog.queries.articles({ category: categoryId }));
  const next = data?.cursor.next; // pass as `cursor` for the following page

  return <p>{data?.data.length} articles{next ? ', more available' : ''}</p>;
}
```

## Gotchas [#gotchas]

* `blog.get` replaces missing lists with `[]`, and `articles.list` replaces a missing `data` with `[]`.
* `articles.find` throws `Error("Article {id} not found")` when the API returns no `data`. HTTP errors throw the client's `HTTPError`. `findOrThrow` only turns a 404 or 410 into a not-found page, so the missing-article `Error` above (which has no HTTP status) still reaches the error boundary.
* Paging is by cursor: pass `cursor.next` from the previous response as `cursor`.

## See also [#see-also]

* [Blog route](https://docs.salla.dev/twilight/react/routes/blog) and [Blog article route](https://docs.salla.dev/twilight/react/routes/blog-article)
* [Making requests](https://docs.salla.dev/twilight/react/api#make-a-request)
