Docs
Help center — Tenantx kernel

Help center — Tenantx kernel

This document explains **how the in-app help center works** in Tenantx: who can read it, how content is stored, how categories are shaped, and how it differs from **platform** management.

Help center — Tenantx kernel

This document explains how the in-app help center works in Tenantx: who can read it, how content is stored, how categories are shaped, and how it differs from platform management.


Roles in one sentence

ActorWhat they do
End user (tenant)Browse and search published articles when they have help_center.read.
Author (optional tenant)Some write APIs exist under the authenticated tenant API but are gated by subscription:write and controller checks (e.g. help_center.create / update / delete). In typical kernels, only platform operators curate global content.
Platform operatorFull category + article CRUD under /api/platform/help-center/* (requires subscription.admin via platform.admin middleware).

Always enforce the same rules on the API; sidebar visibility is UI-only.


Three API surfaces

1. Public (no auth)

Under GET /api/help-center/… (no auth:sanctum):

  • GET /api/help-center/articles/context — contextual article hints for the SPA.
  • GET /api/help-center/articles/{id} — single article by UUID.
  • GET /api/help-center/s/{categorySlug} — category by slug.
  • GET /api/help-center/s/{categorySlug}/{articleSlug} — article by category + article slug (canonical public URLs).

Use these for marketing pages or unauthenticated previews if you wire them; the main app uses authenticated routes for the full UI.

2. Tenant (auth + organization)

Under auth:sanctum, organization, and subscription:read (see backend/routes/api.php):

  • Read: GET /api/help-center/categories, GET /api/help-center/articles, featured/popular, single article routes as exposed.
  • Feedback: POST /api/help-center/articles/{id}/helpful and …/not-helpful.
  • Writes: POST/PUT/DELETE categories and articles (plus publish/unpublish/archive) sit in a group protected by subscription:write. Controllers should still check Spatie permissions such as help_center.create / help_center.update / help_center.delete where applicable.

The React app gates the Help Center page with help_center.read (PermissionRoute + useHasPermission).

3. Platform (global operator)

Under auth:sanctum + platform.admin + prefix /api/platform:

  • GET/POST /api/platform/help-center/categories and PUT/DELETE …/categories/{id}**
  • GET/POST /api/platform/help-center/articles and PUT/DELETE …/articles/{id}**

These ignore tenant org boundaries for global rows (organization_id null). The platform UI lives under /platform and uses platformApi + usePlatformAdminPermissions, not the tenant permission hook.


Where content lives (filesystem + DB)

  1. Markdown source (recommended for kernel demos and CI)

    • Directory: backend/resources/help-center/articles/{category-folder}/{lang}/*.md
    • Kernel convention: ship at least en (and ar when you have translated markdown). The DB/API language column may still accept ps / fa for article bodies (legacy TenantX / multi-locale content); the React app UI is en + ar only — see docs/I18N.md.
    • HelpCenterCategorySeeder creates one category per top-level folder name (slug = folder name). Metadata (title, description, icon, color, order) is defined in HelpCenterCategorySeeder::folderMeta().
    • HelpCenterArticleSeeder loads each .md file into help_center_articles (global articles: organization_id null). It soft-deletes previous global articles first, then upserts from disk.
  2. Runtime edits
    Platform admins can change categories/articles via API/UI; that data lives in PostgreSQL. Re-running HelpCenterArticleSeeder overwrites global articles from markdown—use a deliberate process in production (export/import or avoid re-seeding content you edited only in DB).

See also backend/resources/help-center/MANIFEST.md for the current kernel folder layout.


Frontend usage (tenant)

  • Route: /help-center (and article routes under /help-center/…).
  • Hooks: useHelpCenterCategories, useHelpCenterArticles, etc. (frontend/src/hooks/help-center/useHelpCenter.tsx).
  • Language: Send the active SPA locale (en or ar) where the API expects it; the client reads tenantx-language (and legacy TenantX-language fallback) for /help-center/ requests.
  • Canonical links inside markdown often use /help-center/s/{categorySlug}/{articleSlug}.

Visibility and safety

  • Articles support visibility (e.g. org users vs staff-only) and published state; the controller filters by permission (help_center.read, help_center.read_staff, etc.).
  • Do not expose platform-only actions on tenant routes without mirroring the same checks on the server.

Quick commands

cd backend
php artisan db:seed --class=HelpCenterCategorySeeder
php artisan db:seed --class=HelpCenterArticleSeeder

Requires PostgreSQL for a full demo dataset aligned with other seeders; SQLite may skip some related demo rows.


Related docs