# Knowledge base (direct)

URL: https://developers.uidu.org/docs/domains/kb

> Fetch KB collections and articles directly, outside the help-center channel scope.

* **Use it for:** [Public website](https://developers.uidu.org/docs/paths/public-website.md) · [Server integration](https://developers.uidu.org/docs/paths/server-integration.md)
* **Reads:** public token — works in the browser
* **Writes:** Bearer (`apiKey`) — server-side only
* **CLI:** `uidu kb-collections`, `uidu kb-articles`
* **Auth:** what each token can do and where it may run — [Authentication](https://developers.uidu.org/docs/foundations/authentication.md)

The knowledge base is the content behind the [Help Center](https://developers.uidu.org/docs/domains/help-center.md):
**collections** of **articles**. The functions on this page read and write them at the workspace
level, with no channel in between — use them to list every collection across channels, to fetch an
article without knowing its collection, or to go past the 100-per-level cap of `getChannel`.

## Mental model

```
Workspace
├── KbCollection     { id, name, description, iconData, position, createdAt, updatedAt }
│   └── KbArticle    { id, name, body, position, isDraft, createdAt, updatedAt, kbCollection { id, name } }
└── Channel          a help center: shows some collections, in its own order (see Help Center)
```

* **Lists are flat arrays**, one Relay page at a time: `listKbCollections` and `listKbArticles` take
  `first`/`after` (or `last`/`before`). For all of them, `paginate` with `ListKbCollectionsDocument`
  or `ListKbArticlesDocument` — see [Pagination](https://developers.uidu.org/docs/foundations/pagination-and-field-values.md).
* **`listKbArticles` spans every collection** and returns summaries — `name`, `position`, `isDraft`,
  `kbCollection { id, name }`, timestamps — &#x2A;*without `body`**. Only `getKbArticle` returns the body.
* **`getKbCollection` embeds its first 50 articles** (`id`, `name`, `position`, `isDraft`,
  `updatedAt`) with their `pageInfo`, ordered by `position`. A bigger collection needs
  `listKbArticles`, filtered on `kbCollection.id`.
* **Drafts are left out** of the article lists server-side, so `isDraft` is `false` on everything a
  list returns.
* **Field shapes.** A collection's `name` and `description` are JSON — often a string, possibly a
  localization map like `{ en, it }`; `iconData` is JSON. An article's `name` is a string when you
  read it; its `body` is Tiptap JSON, rendered with [`<RichText>`](https://developers.uidu.org/docs/tools/react/components.md).
* **Writes** need the Bearer client. `createKbCollection` returns the new collection at
  `kbCollection.node`; `createKbArticle` creates the article in `attributes.kbCollectionId` and
  returns it at `kbArticle.node`. `update*` take `{ input: { id, attributes } }`, `delete*`
  `{ input: { id } }`. Validation failures come back in `errors`, not as a throw:
  [Writes](https://developers.uidu.org/docs/foundations/writes.md). Collection attributes: `name`, `description`, `iconData`,
  `position`. Article attributes: `name`, `body`, `isDraft`, `kbCollectionId`, `position`,
  `workspaceTagIds`.

For a ready-made help center (channel → collections → articles in one request), use
[`getChannel`](https://developers.uidu.org/docs/domains/help-center.md); reach for these functions when you don't want channel
scoping.

## Use cases

### Cross-channel article index

Goal: one page listing every published article in the workspace, grouped by collection.

```tsx
// src/app/kb/page.tsx
import Link from 'next/link';
import {
  ListKbArticlesDocument,
  listKbCollections,
  paginate,
} from '@uidu/client';
import { uidu } from '@/lib/uidu';

export default async function KbIndexPage() {
  const [collections, articles] = await Promise.all([
    listKbCollections(uidu, { first: 100 }),
    paginate(uidu, ListKbArticlesDocument, {
      variables: { first: 100 },
      extract: (data) => data.currentWorkspace?.kbArticles,
    }),
  ]);

  return collections
    .sort((a, b) => a.position - b.position)
    .map((c) => (
      <section key={c.id}>
        <h2>{typeof c.name === 'string' ? c.name : c.name?.en}</h2>
        <ul>
          {articles
            .filter((a) => a.kbCollection?.id === c.id)
            .sort((a, b) => a.position - b.position)
            .map((a) => (
              <li key={a.id}>
                <Link href={`/kb/article/${encodeURIComponent(a.id)}`}>{a.name}</Link>
              </li>
            ))}
        </ul>
      </section>
    ));
}
```

* `paginate` walks every page of articles; `listKbArticles(uidu, { first: 100 })` would stop at the
  first 100.
* The article page is `getKbArticle(uidu, { id })` + `<RichText doc={article.body} />` — the same
  route as the [Help Center article page](https://developers.uidu.org/docs/domains/help-center.md).

### Sync articles from your own docs

Goal: a server job that creates an article in a collection, then publishes it once its body is in.

```ts
// scripts/sync-kb.ts — runs with the apiKey client, never in a browser
import { createKbArticle, updateKbArticle } from '@uidu/client';
import { uiduAdmin } from '@/lib/uidu-admin';

export async function upsertArticle(kbCollectionId: string, title: string, body: unknown) {
  const created = await createKbArticle(uiduAdmin, {
    input: { attributes: { kbCollectionId, name: title, body, isDraft: true } },
  });
  if (!created || created.errors?.length) {
    throw new Error(created?.errors?.map((e) => e.name).join(', ') ?? 'createKbArticle failed');
  }

  const id = created.kbArticle!.node!.id;
  const published = await updateKbArticle(uiduAdmin, {
    input: { id, attributes: { isDraft: false } },
  });
  if (published?.errors?.length) {
    throw new Error(published.errors.map((e) => e.name).join(', '));
  }
  return id;
}
```

* The new article is at `kbArticle.node` on create, but at `kbArticle` on update — the payloads
  differ.
* `body` is Tiptap JSON (`{ type: 'doc', content: [...] }`), the same shape `getKbArticle` returns.
* While `isDraft` is `true` the article stays out of `listKbArticles`, `getKbCollection` and the
  Help Center's `getChannel`.
* From the terminal: `uidu kb-articles create --attributes '{"kbCollectionId":"…","name":"…"}' --json`.
  Server client set-up: [Server integration](https://developers.uidu.org/docs/paths/server-integration.md).

## API at a glance

Every `@uidu/client` function in **Knowledge base**, generated from the source — the [full reference](https://developers.uidu.org/docs/reference/client.md#kb) has the rest of the SDK.

| Function                                                                                              | Kind  | Auth         | CLI                     | Description                                                                                                                                          |
| ----------------------------------------------------------------------------------------------------- | ----- | ------------ | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`createKbArticle`](https://github.com/uidu-org/api.js/blob/main/packages/client/src/mutations.ts)    | write | Bearer       | `kb-articles create`    | Create a knowledge-base article in `attributes.kbCollectionId`. Returns the payload (with `errors`) or null. The new article is at `kbArticle.node`. |
| [`createKbCollection`](https://github.com/uidu-org/api.js/blob/main/packages/client/src/mutations.ts) | write | Bearer       | `kb-collections create` | Create a knowledge-base collection. Returns the payload (with `errors`) or null. The new collection is at `kbCollection.node`.                       |
| [`deleteKbArticle`](https://github.com/uidu-org/api.js/blob/main/packages/client/src/mutations.ts)    | write | Bearer       | `kb-articles delete`    | Delete a knowledge-base article by `{ input: { id } }`. Returns the payload (with `errors`) or null.                                                 |
| [`deleteKbCollection`](https://github.com/uidu-org/api.js/blob/main/packages/client/src/mutations.ts) | write | Bearer       | `kb-collections delete` | Delete a knowledge-base collection by `{ input: { id } }`. Returns the payload (with `errors`) or null.                                              |
| [`getKbArticle`](https://github.com/uidu-org/api.js/blob/main/packages/client/src/kb.ts)              | read  | public token | `kb-articles get`       | One knowledge-base article with its rich-text `body` and its collection, or null.                                                                    |
| [`getKbCollection`](https://github.com/uidu-org/api.js/blob/main/packages/client/src/kb.ts)           | read  | public token | `kb-collections get`    | One knowledge-base collection with its first 50 articles, or null.                                                                                   |
| [`listKbArticles`](https://github.com/uidu-org/api.js/blob/main/packages/client/src/kb.ts)            | read  | public token | `kb-articles list`      | Knowledge-base articles across every collection, as a flat array; page with `first`/`after` (or `last`/`before`).                                    |
| [`listKbCollections`](https://github.com/uidu-org/api.js/blob/main/packages/client/src/kb.ts)         | read  | public token | `kb-collections list`   | The workspace's knowledge-base collections as a flat array; page with `first`/`after` (or `last`/`before`).                                          |
| [`updateKbArticle`](https://github.com/uidu-org/api.js/blob/main/packages/client/src/mutations.ts)    | write | Bearer       | `kb-articles update`    | Update a knowledge-base article: `{ input: { id, attributes } }`. Returns the payload (with `errors`) or null.                                       |
| [`updateKbCollection`](https://github.com/uidu-org/api.js/blob/main/packages/client/src/mutations.ts) | write | Bearer       | `kb-collections update` | Update a knowledge-base collection: `{ input: { id, attributes } }`. Returns the payload (with `errors`) or null.                                    |

**Types:** `KbArticle`, `KbCollection`

**CLI:**

| Entity           | list | get | create | update | delete |
| ---------------- | :--: | :-: | :----: | :----: | :----: |
| `kb-collections` |   ✓  |  ✓  |    ✓   |    ✓   |    ✓   |
| `kb-articles`    |   ✓  |  ✓  |    ✓   |    ✓   |    ✓   |
