Frontend Development 10 min read

Building a Real‑Time Editable Documentation Site with EggJS, Marked, Highlight.js and Docsify

This article describes how a front‑end team can create a markdown‑based documentation site that updates automatically via GitLab webhooks, using EggJS with marked and highlight.js for server‑side rendering or NestJS with docsify for client‑side rendering, and provides complete code examples and deployment steps.

政采云技术
政采云技术
政采云技术
Building a Real‑Time Editable Documentation Site with EggJS, Marked, Highlight.js and Docsify

Introduction

The post explains why the team needs a documentation site that supports markdown authoring, real‑time editing, and automatic HTML generation after each commit, and reviews existing solutions such as docsify, gitbook and vuepress.

Requirements

Write documentation in Markdown and generate HTML.

Allow real‑time editing without touching HTML.

Automatically update the site when Markdown files change.

Method 1: EggJS + marked + highlight.js

Documentation markdown files are stored in a GitLab repository. A GitLab webhook (push event) notifies the server of changes. The webhook payload provides { ref: '', commits: [{ added: [], modified: [], removed: [] }] } . The server extracts changed file paths, fetches each file via the GitLab API, decodes the base64 content to UTF‑8, and converts markdown to HTML using marked with highlight.js for syntax highlighting.

import * as marked from "marked";
import * as hljs from "highlight.js";
marked.setOptions({
  highlight(code, lang) {
    if (lang && hljs.getLanguage(lang)) {
      return hljs.highlight(lang, code, true).value;
    } else {
      return hljs.highlightAuto(code).value;
    }
  }
});
const htmlStr = marked(markdownStr, { renderer: new marked.Renderer() });

The server also provides two endpoints: /api/hook to receive the webhook and /api/batchUpdate for manual batch generation. Full‑generation pulls the whole repository with git-clone , reads markdown files, injects them into an EJS template, and serves the resulting HTML.

gitClone(repo, targetPath, {}, () => { ... });

Webhook Handling

Only push events on the master branch are processed. Updated and removed file lists are deduplicated using Set , then each file is fetched via the GitLab API endpoint ${gitLabhost}/api/v3/projects/${projectId}/repository/files?file_path=${filePath}&ref=master&private_token=${accessToken} , which returns a base64‑encoded content object.

{
  file_name: "",
  file_path: "",
  size: 700,
  encoding: "base64",
  content: "",
  ref: "master",
  ...
}

The content is decoded with new Buffer(content, "base64").toString("utf8") and then rendered to HTML as described above.

Method 2: NestJS + docsify

The second approach uses a lightweight Node.js server built with NestJS to receive GitLab webhooks and pull the latest repository. Docsify runs in the browser, converting markdown to HTML on the client side, eliminating server‑side rendering.

// app.controller.ts
import { Controller, Post } from "@nestjs/common";
import * as execa from "execa";
@Controller()
export class AppController {
  @Post("hook")
  async hook() {
    const { stdout } = await execa("git", ["pull"]);
    return stdout;
  }
}
// main.ts
import { NestFactory } from "@nestjs/core";
import { AppModule } from "./app.module";
import { join } from "path";
import { Logger } from "@nestjs/common";
const port = parseInt(process.env.PORT, 10) || 3001;
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.setGlobalPrefix("api");
  app.useStaticAssets(join(__dirname, "..", "docs"));
  await app.listen(port);
  Logger.log(`服务已启动,请访问 http://localhost:${port}`);
}
bootstrap();

When a webhook triggers, the server runs git pull to fetch the latest markdown files. Docsify then renders them in the browser, providing instant updates after a page refresh.

Conclusion

The article offers two practical solutions for automatically updating a documentation site without relying on GitLab CI, allowing the team to focus on writing markdown while the server handles webhook processing and optional server‑side rendering.

frontenddocumentationMarkdownwebhookNestJSdocsifyeggjs
政采云技术
Written by

政采云技术

ZCY Technology Team (Zero), based in Hangzhou, is a growth-oriented team passionate about technology and craftsmanship. With around 500 members, we are building comprehensive engineering, project management, and talent development systems. We are committed to innovation and creating a cloud service ecosystem for government and enterprise procurement. We look forward to your joining us.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.