| description | Convert a Freshdesk helpdesk solution article into a Docusaurus tutorial page for the ns8-docs repository. Use when the user wants to import a Freshdesk article, mentions "/freshdesk", or asks to convert a helpdesk solution to documentation. Supports: (1) Fetching article content via Freshdesk API, (2) Filtering content relevant to NethServer 8 only, (3) Downloading and saving screenshots, (4) Creating both English and Italian versions, (5) Placing files in the correct tutorial directories |
| name | freshdesk-to-tutorial |
Freshdesk Solution → NS8 Tutorial
Overview
Fetch a Freshdesk helpdesk article and convert it into a Docusaurus tutorial page
for the ns8-docs repository, in both English and Italian.
Step 1 — Collect inputs
1a. Auth token
Check whether the auth token is already stored in the session SQL database:
SELECT value FROM session_state WHERE key = 'freshdesk_token';
If the row exists, use that token for all API calls.
If it does not exist, ask the user:
"Please provide your Freshdesk API token (it will be kept only for this session and never stored permanently)."
After receiving the token, save it to the session:
CREATE TABLE IF NOT EXISTS session_state (key TEXT PRIMARY KEY, value TEXT);
INSERT OR REPLACE INTO session_state (key, value) VALUES ('freshdesk_token', '<token>');
Never write the token to any file, commit, or memory tool.
1b. Article URL
If the user has not already provided the URL, ask:
"Please paste the Freshdesk article URL (e.g. https://helpdesk.nethesis.it/a/solutions/articles/3000019251)."
Extract the numeric article ID from the URL (last path segment).
Step 2 — Fetch the article
Base URL: https://nethesis.freshdesk.com/api/v2
Auth: HTTP Basic with <token>:X (token as username, literal X as password).
curl -s -u "<TOKEN>:X" \
-H "Content-Type: application/json" \
"https://nethesis.freshdesk.com/api/v2/solutions/articles/<ARTICLE_ID>"
The response is JSON with at least these fields:
| Field | Description |
|---|
title | Article title |
description | Full HTML body of the article |
description_text | Plain-text version (no HTML) |
folder_id | Parent folder |
status | 1 = draft, 2 = published |
tags | Array of tag strings |
Fetch the folder and category to understand context:
curl -s -u "<TOKEN>:X" \
"https://nethesis.freshdesk.com/api/v2/solutions/folders/<FOLDER_ID>"
curl -s -u "<TOKEN>:X" \
"https://nethesis.freshdesk.com/api/v2/solutions/categories/<CATEGORY_ID>"
Step 3 — Assess NS8 relevance
Examine description_text and the category/folder names.
The article is relevant to NethServer 8 if it mentions any of:
- "NethServer 8", "NS8", "nethserver8"
- Modules/apps known to run on NS8 (Mail, WebTop, Nextcloud, Mattermost, Samba, OpenVPN, etc.)
- Cluster, node, leader, replica — NS8 architectural concepts
- The category/folder name contains "NethServer 8" or similar
If the article is not relevant to NS8, stop and inform the user:
"This article does not appear to be relevant to NethServer 8. No files were created."
Step 4 — Extract and convert content
4a. Parse the HTML
Use Python with html.parser (stdlib) to parse description:
from html.parser import HTMLParser
import re, textwrap, os, urllib.request, base64
Write a robust HTML-to-Markdown converter inline in the script.
4b. Heading hierarchy
- Page
title (from JSON) → Markdown frontmatter title: + # Title heading
<h1> in the body → ##
<h2> → ###
- … and so on (shift all headings down by one level)
4c. Filter irrelevant sections
Remove entire sections (heading + content until next same-level heading) that:
- Explicitly refer only to NethServer 7 / NS7 (unless they describe migration)
- Refer to unrelated products (NethVoice, NethSecurity) unless the article is specifically about them
- Are generic boilerplate not specific to the product
Keep sections that mention both NS7 and NS8 if they are comparative/migration context.
4d. Admonitions
Convert Freshdesk-style callouts:
<div class="note"> / <aside class="note"> → :::note
<div class="warning"> / <aside class="warning"> → :::warning
<div class="tip"> → :::tip
<div class="info"> → :::info
4e. Rewrite docs.nethserver.org links
If the converted content contains links to docs.nethserver.org that point to content already
present in this repository, replace them with internal relative links instead of keeping
external URLs.
Examples:
https://docs.nethserver.org/projects/ns8/en/latest/mail.html#rspamd-web-interface
→ ../administrator-manual/applications/mail.md#rspamd-web-interface
https://docs.nethserver.org/projects/ns8/en/latest/install.html#pre-built-image
→ ../administrator-manual/installation/install.md#pre-built-image
Rules:
- Prefer relative links to files under
docs/ or i18n/it/.../current/ when the target page
exists in this repository.
- Preserve heading anchors when converting the link.
- Keep the external URL only if there is no matching local documentation page.
Step 5 — Handle screenshots
For every <img> tag in the HTML:
- Download the image with
curl (or Python urllib).
- Save to
static/_static/tutorial/<slug>/ where <slug> is derived from the article title
(lowercase, spaces→hyphens, strip special chars).
- Reference in Markdown as
.
- Skip images that are clearly UI chrome, icons, or decorative (tiny size < 5 KB, or filename
suggests icon:
icon, logo, avatar, bullet).
- If downloading fails, insert a comment
<!-- image: <original-url> --> instead.
mkdir -p static/_static/tutorial/<slug>
curl -s -o "static/_static/tutorial/<slug>/<filename>" "<image-url>"
Step 6 — Generate the English file
Target path: docs/tutorial/<slug>.md
Frontmatter template:
---
title: "<article title>"
sidebar_position: 99
---
Use sidebar_position: 99 as a placeholder (user can adjust).
Full file structure:
---
title: "Article Title"
sidebar_position: 99
---
# Article Title
<converted markdown body>
Do not include:
- Author names
- "Last updated" timestamps from Freshdesk
- Freshdesk-specific footer links
- Tags or category breadcrumbs
- External
docs.nethserver.org links when an internal relative link is available
Step 7 — Generate the Italian file
The Freshdesk account does not have multilingual API support, so always translate yourself.
Translate the English Markdown output into Italian following these guidelines:
- Use informal second person ("tu") consistent with the rest of the ns8-docs Italian translation.
- Keep all code blocks, command names, config keys, file paths, and UI element names in English.
- Translate prose naturally; do not translate product names (NethServer, WebTop, Samba, etc.).
- Preserve all Markdown syntax, admonitions, and image references unchanged.
- If the original Freshdesk article was already written in Italian (check
description_text
for Italian text), use that content directly as the Italian version and translate it to English
for the English file instead.
Target path: i18n/it/docusaurus-plugin-content-docs/current/tutorial/<slug>.md
Use the same frontmatter structure as the English file (translate title: value to Italian).
Step 8 — Write the files
- Create the image directory and download all images.
- Write the English
.md file.
- Write the Italian
.md file.
- Print a summary:
✅ Created: docs/tutorial/<slug>.md
✅ Created: i18n/it/docusaurus-plugin-content-docs/current/tutorial/<slug>.md
📁 Images: static/_static/tutorial/<slug>/ (<N> files)
Next steps:
- Review and adjust sidebar_position in both files
- Run: yarn build (to validate the new pages)
Step 9 — Validation
After creating the files, run:
cd /path/to/ns8-docs && yarn build 2>&1 | tail -30
Fix any MDX or broken-link errors before declaring the task complete.
Reference: Freshdesk API endpoints used
| Purpose | Method | URL |
|---|
| Get article | GET | /api/v2/solutions/articles/{id} |
| List translations | GET | /api/v2/solutions/articles/{id}/translations |
| Get folder | GET | /api/v2/solutions/folders/{id} |
| Get category | GET | /api/v2/solutions/categories/{id} |
Authentication: curl -u "<token>:X" (Basic Auth, literal X as password).
NS8 docs conventions (apply to generated Markdown)
- One
# heading per file (the page title); use ## and below for sections.
- UI elements in bold:
**Save**, **Next**.
- File paths, commands, config keys in
inline code.
- Admonitions:
:::note, :::warning, :::tip, :::info.
- Images: absolute path from repo root
/….
- Cross-links: relative paths like
../administrator-manual/installation/install.md.
- Replace
docs.nethserver.org links with internal relative links whenever the referenced page
exists in this repository.
- Write in second person, present tense, imperative mood for procedures.