npm package: @monok/server
Description: Monok server integration helpers (Express router + linkback client)
Latest version: 1.3.0

---

# `@monok/server`

Monok server integration helpers for Node.js/Express.
Easily connect your backend to Monok to receive articles, expose site info, and send linkbacks.

---

## ⚡ Quick Start

```ts
import express from "express";
import { createMonokRouter, type MonokArticle } from "@monok/server";

const app = express();

app.use(
  "/monok",
  createMonokRouter({
    apiKey: process.env.MONOK_API_KEY!,
    onArticle: async (article: MonokArticle, { saveThumbImage, action }) => {
      const imagePath = await saveThumbImage();

      if (action === "publish") {
        // auto-publish in your CMS
      } else {
        // save as draft (default)
      }
    }
  })
);

app.listen(3000);
```

---

## 📦 Install

```bash
npm install @monok/server express
```

---

## 📚 Usage

### Express setup (TypeScript)

```ts
import express from "express";
import {
  createMonokRouter,
  sendMonokLinkback,
  type MonokArticle
} from "@monok/server";

const app = express();

app.use(
  "/monok",
  createMonokRouter({
    apiKey: process.env.MONOK_API_KEY!,
    imageDir: "./uploads", // optional
    // Optional: provide site info if you want Monok to query it
    getSiteInfo: {
      js_scripts: "Enabled",
      version: "1.0.0",
      name: "My Site",
      logo: "https://example.com/logo.png",
      categories: ["Content", "News Articles", "Uncategorized"],
      post_types: ["post", "page"],
      tags: ["Tech", "Health", "News"],
      authors: [
        {
          name: "Jane Doe",
          profile: "Editor-in-chief",
          id: "1",
          avatar: "https://example.com/avatars/jane.png",
          roles: ["administrator"]
        }
      ]
    },
    onArticle: async (article: MonokArticle, { saveThumbImage, action }) => {
      const imagePath = await saveThumbImage();
      console.log("Received article:", article.title);

      if (action === "publish") {
        // publish immediately
      } else {
        // save as draft
      }

      // when you publish later, notify Monok:
      // await sendMonokLinkback({
      //   monokId: article.id,
      //   publicUrl: "https://example.com/blog/" + (article.slug ?? article.id),
      //   title: article.title,
      //   articleTextSample: article.text?.slice(0, 500),
      //   thumbnailUrl: imagePath
      //     ? "https://example.com/uploads/" + require("path").basename(imagePath)
      //     : undefined
      // });
    }
  })
);

app.listen(3000);
```

### CommonJS (JavaScript)

```js
const express = require("express");
const { createMonokRouter } = require("@monok/server");

const app = express();

app.use(
  "/monok",
  createMonokRouter({
    apiKey: process.env.MONOK_API_KEY,
    onArticle: async (article, { saveThumbImage, action }) => {
      const img = await saveThumbImage();
      console.log("Got article:", article.title, "Saved image:", img);

      if (action === "publish") {
        // publish immediately
      } else {
        // save as draft
      }
    }
  })
);

app.listen(3000);
```

---

## 🔑 Endpoints

* **`POST /monok/push[?action=draft|publish]`**
  Monok pushes new article data here.
  Header: `token: <your-api-key>`
  Body: JSON payload of the article.

  * `action` query param may be `draft` or `publish` depending on GUI dropdown selection.

* **`GET /monok/info?apikey=<your-api-key>`**
  If `getSiteInfo` is configured, Monok fetches this to learn your site branding, categories, tags, and authors.
  If `getSiteInfo` is not provided, this route responds with `404`.

---

## 🔗 Linkback after publishing

```ts
import { sendMonokLinkback } from "@monok/server";

await sendMonokLinkback({
  monokId: article.id,
  publicUrl: "https://example.com/blog/" + (article.slug ?? article.id),
  title: article.title,
  articleTextSample: article.text?.slice(0, 500),
  thumbnailUrl: "https://example.com/uploads/" + imageFile
});
```

---

## ⚙️ Options (`createMonokRouter`)

| Option        | Type                                      | Required | Description                                                                       |
| ------------- | ----------------------------------------- | -------- | --------------------------------------------------------------------------------- |
| `apiKey`      | `string`                                  | ✅        | Token Monok sends in headers / query.                                             |
| `onArticle`   | `(article, ctx) => void \| Promise<void>` | ✅        | Handle new article pushes. `ctx` includes `saveThumbImage` and optional `action`. |
| `getSiteInfo` | `SiteInfo \| () => SiteInfo`              | ❌        | Return site info in the Monok format. If omitted, `GET /info` responds 404.       |
| `imageDir`    | `string`                                  | ❌        | Directory to save `thumbImageData`.                                               |
| `basePath`    | `string`                                  | ❌        | Custom prefix for routes (default "").                                            |

---

## 🛠 Development

Build the package:

```bash
npm run build
```