knowledge-base

Self-hosted markdown documentation site with categories, full-text search, and version history

7 stars

Best use case

knowledge-base is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Self-hosted markdown documentation site with categories, full-text search, and version history

Teams using knowledge-base should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/knowledge-base/SKILL.md --create-dirs "https://raw.githubusercontent.com/heldernoid/agentic-build-templates/main/projects/web-applications/knowledge-base/skills/knowledge-base/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/knowledge-base/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How knowledge-base Compares

Feature / Agentknowledge-baseStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Self-hosted markdown documentation site with categories, full-text search, and version history

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# knowledge-base skill

## Overview

knowledge-base is a single-binary self-hosted documentation platform. Authors write documents in Markdown via an admin UI. Readers browse published content on a public site with full-text search. Documents are organized into categories and every save creates an immutable version snapshot.

## Base URL

```
http://localhost:3000
```

Admin routes are all under `/api/admin/`. Public routes are under `/api/pub/`.

## TypeScript interfaces

```typescript
interface Category {
  id: number;
  name: string;          // display name
  slug: string;          // URL-safe identifier
  description: string;
  color: string;         // hex color for UI icon, e.g. "#2563eb"
  icon: string;          // SVG path string or named preset
  doc_count: number;     // live count of published docs
  created_at: string;    // ISO 8601
}

interface Doc {
  id: number;
  category_id: number | null;
  title: string;
  slug: string;          // auto-generated from title, URL-safe
  summary: string;       // 200-char plain-text excerpt; auto-extracted if blank
  body_md: string;       // raw markdown source
  body_html: string;     // sanitized HTML rendered from body_md
  status: 'draft' | 'published';
  version_num: number;   // increments per doc on each save
  word_count: number;
  read_time_min: number;
  published_at: string | null;
  updated_at: string;
  created_at: string;
}

interface DocVersion {
  id: number;
  doc_id: number;
  version_num: number;
  title: string;
  body_md: string;
  body_html: string;
  saved_at: string;
}

interface SearchResult {
  id: number;
  title: string;
  slug: string;
  summary: string;
  snippet: string;       // FTS5 snippet() with <mark> tags for matched terms
  category_id: number | null;
  category_name: string | null;
  rank: number;          // FTS5 rank, lower is better match
}

interface Settings {
  site_name: string;
  site_description: string;
  site_url: string;
  docs_per_page: number;
  search_enabled: number;   // 0 or 1
  fts_last_rebuilt: string | null;
}
```

## Admin API

### Categories

**List categories**
```bash
curl http://localhost:3000/api/admin/categories
```

Response: `Category[]`

**Create category**
```bash
curl -X POST http://localhost:3000/api/admin/categories \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "API Reference",
    "description": "Complete endpoint documentation",
    "color": "#2563eb",
    "icon": "code"
  }'
```

Response: `Category`

**Update category**
```bash
curl -X PUT http://localhost:3000/api/admin/categories/1 \
  -H 'Content-Type: application/json' \
  -d '{ "name": "API Reference", "description": "Updated description" }'
```

**Delete category**
```bash
curl -X DELETE http://localhost:3000/api/admin/categories/1
```

Docs in the deleted category have `category_id` set to `null`.

### Documents

**List docs (all statuses)**
```bash
curl 'http://localhost:3000/api/admin/docs?page=1&per_page=20&status=all'
```

Query params:
- `status`: `all` | `published` | `draft` (default: `all`)
- `category_id`: filter by category
- `page`: 1-indexed (default: 1)
- `per_page`: 1-100 (default: 20)

Response:
```json
{
  "docs": [Doc],
  "total": 42,
  "page": 1,
  "per_page": 20
}
```

**Get single doc**
```bash
curl http://localhost:3000/api/admin/docs/7
```

**Create doc**
```bash
curl -X POST http://localhost:3000/api/admin/docs \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "Deploying with Docker Compose",
    "category_id": 2,
    "body_md": "# Deploying with Docker Compose\n\nThis guide walks through...",
    "status": "draft"
  }'
```

Response: `Doc` with auto-generated `slug`, `body_html`, and `summary`.

**Update doc**
```bash
curl -X PUT http://localhost:3000/api/admin/docs/7 \
  -H 'Content-Type: application/json' \
  -d '{
    "title": "Deploying with Docker Compose",
    "body_md": "Updated content...",
    "status": "draft"
  }'
```

Every PUT that changes `body_md` or `title` creates a new `DocVersion` snapshot and increments `version_num`.

**Publish doc**
```bash
curl -X POST http://localhost:3000/api/admin/docs/7/publish
```

Sets `status` to `published`, records `published_at`, updates FTS5 index.

**Unpublish doc**
```bash
curl -X POST http://localhost:3000/api/admin/docs/7/unpublish
```

Sets `status` to `draft`. Doc is immediately removed from public site and FTS index.

**Delete doc**
```bash
curl -X DELETE http://localhost:3000/api/admin/docs/7
```

Deletes all versions. Cascades to FTS5 via DELETE trigger.

### Version history

**List versions for a doc**
```bash
curl http://localhost:3000/api/admin/docs/7/versions
```

Response: `DocVersion[]` ordered by `version_num DESC`.

**Get specific version**
```bash
curl http://localhost:3000/api/admin/docs/7/versions/5
```

**Restore a version**
```bash
curl -X POST http://localhost:3000/api/admin/docs/7/versions/5/restore
```

Copies `body_md` and `title` from version 5 into the doc, increments `version_num`, creates a new snapshot. Does not change `status`.

### Settings

**Get settings**
```bash
curl http://localhost:3000/api/admin/settings
```

**Update settings**
```bash
curl -X PUT http://localhost:3000/api/admin/settings \
  -H 'Content-Type: application/json' \
  -d '{
    "site_name": "Acme App Docs",
    "site_description": "Documentation for Acme App",
    "site_url": "https://docs.acmeapp.com",
    "docs_per_page": 20,
    "search_enabled": 1
  }'
```

**Rebuild FTS index**
```bash
curl -X POST http://localhost:3000/api/admin/settings/rebuild-fts
```

Runs `INSERT INTO docs_fts(docs_fts) VALUES('rebuild')`. Updates `fts_last_rebuilt`. Returns `{ ok: true, rebuilt_at: "..." }`.

## Public API

**Home: recent published docs**
```bash
curl 'http://localhost:3000/api/pub/docs?page=1&per_page=10'
```

**List published docs in category**
```bash
curl 'http://localhost:3000/api/pub/categories/guides/docs'
```

**Get single published doc by slug**
```bash
curl http://localhost:3000/api/pub/docs/deploying-with-docker-compose
```

Returns `404` if doc is in `draft` status.

**Get all categories (public)**
```bash
curl http://localhost:3000/api/pub/categories
```

Returns only categories that have at least one published doc.

## Error responses

| HTTP status | `code` field | Meaning |
|------------|--------------|---------|
| 400 | `VALIDATION_ERROR` | Invalid request body; `details` array has per-field messages |
| 404 | `NOT_FOUND` | Doc or category does not exist |
| 404 | `DOC_NOT_PUBLISHED` | Public request for a draft doc |
| 409 | `SLUG_CONFLICT` | Auto-generated slug already exists; append `-2` suffix |
| 500 | `INTERNAL_ERROR` | Unexpected server error |

Error response shape:
```json
{
  "error": "VALIDATION_ERROR",
  "message": "title is required",
  "details": [{ "field": "title", "message": "Required" }]
}
```

## Markdown rendering pipeline

1. Parse `body_md` with `marked` (GFM enabled, line breaks enabled).
2. Sanitize rendered HTML with `DOMPurify` (Node adapter), allowing `id` attributes on headings so ToC anchor links work.
3. Store sanitized HTML in `body_html`.
4. Extract `summary`: strip all HTML tags from `body_html`, take first 200 characters, trim at last word boundary.
5. Update FTS5 index with new `title` and plain-text `summary`.

## Slug generation

```typescript
function toSlug(title: string): string {
  return title
    .toLowerCase()
    .replace(/[^a-z0-9\s-]/g, '')
    .trim()
    .replace(/\s+/g, '-')
    .replace(/-+/g, '-')
    .substring(0, 80);
}
```

On conflict, append `-2`, `-3`, etc. until unique.

## Environment variables

| Variable | Default | Description |
|----------|---------|-------------|
| `PORT` | `3000` | HTTP port |
| `DATABASE_PATH` | `./data/kb.db` | SQLite file path |
| `NODE_ENV` | `development` | Set to `production` for prod builds |

## Docker

```bash
docker compose up -d
```

Data volume: `./data:/app/data`. The SQLite file is at `/app/data/kb.db` inside the container.

Related Skills

food-database

7
from heldernoid/agentic-build-templates

No description provided.

database-size-monitor

7
from heldernoid/agentic-build-templates

Dashboard for monitoring PostgreSQL and MySQL table sizes over time, with growth tracking, threshold alerts, and snapshot comparison

Skill: Uptime Monitoring

7
from heldernoid/agentic-build-templates

## Overview

Skill: Status Page

7
from heldernoid/agentic-build-templates

## Overview

Skill: unit-conversion

7
from heldernoid/agentic-build-templates

## Overview

Skill: recipe-scaler

7
from heldernoid/agentic-build-templates

## Overview

reading-list

7
from heldernoid/agentic-build-templates

Operate the reading-list API to save, manage, tag, search, and export articles.

email-digest

7
from heldernoid/agentic-build-templates

Configure, test, and troubleshoot the reading-list daily email digest delivered via nodemailer.

websocket-realtime

7
from heldernoid/agentic-build-templates

Use the WebSocket connection in poll-builder to receive live vote updates. Use when you need to stream real-time poll results, monitor a poll for new votes, or build a live dashboard. Triggers include "live results", "real-time updates", "stream votes", "watch poll", or "WebSocket".

poll-builder

7
from heldernoid/agentic-build-templates

Self-hosted poll creation tool with real-time results. Use when you need to create a poll, check vote counts, close a poll, export results, or get the shareable link for a poll. Triggers include "create poll", "vote", "poll results", "survey", "collect votes", "share poll", or any task involving polling or voting.

Skill: personal-finance

7
from heldernoid/agentic-build-templates

## Overview

Skill: csv-import

7
from heldernoid/agentic-build-templates

## Overview