Content Engine Architecture & API Guide¶
Detailed technical documentation covering the database schema, FlightPHP REST endpoints, markdown rendering pipeline, backup synchronization, and frontend integration for the TidyFactor-Go Content Engine.
1. System Architecture & Overview¶
The Content Engine is a core module in TidyFactor-Go designed to manage digital publications, blog posts, news articles, technical documentation, and multimedia press releases.
┌──────────────────────────────────────────────────────────────────┐
│ React 19 Frontend Components │
│ (ContentHubPage.tsx, ContentDetailPage.tsx, ContentManager) │
└─────────────────────────────────┬────────────────────────────────┘
│ API Requests via resolveApiUrl()
┌─────────────────────────────────▼────────────────────────────────┐
│ FlightPHP REST API Gateway │
│ (routes/content_engine.php & Http) │
└─────────────────────────────────┬────────────────────────────────┘
│ Prepared Statements & PDO
┌─────────────────────────────────▼────────────────────────────────┐
│ SqliteContentEngineRepository Data Layer │
│ (content_items, content_categories, content_types) │
└──────────────────────────────────────────────────────────────────┘
2. Database Schema Reference¶
The Content Engine persists data across four normalized tables in backend/cms-api/storage/database.sqlite.
A. content_items Table¶
Stores published and draft publication records.
| Column | Type | Constraints | Description |
|---|---|---|---|
id |
INTEGER |
PRIMARY KEY AUTOINCREMENT |
Unique integer record ID |
slug |
TEXT |
NOT NULL UNIQUE |
URL-safe article slug (e.g. ai-vision-2026) |
type |
TEXT |
DEFAULT 'article' |
Article type (article, guide, news, video) |
title |
TEXT |
NOT NULL |
Article headline |
summary |
TEXT |
NULLABLE |
Short article excerpt |
body |
TEXT |
NOT NULL |
Markdown formatted body content |
cover_image |
TEXT |
NULLABLE |
Hero image URL or path |
video_url |
TEXT |
NULLABLE |
Embedded video URL |
gallery_images |
TEXT |
NULLABLE |
JSON array string of image gallery URLs |
takeaways |
TEXT |
NULLABLE |
Key takeaways list |
category |
TEXT |
DEFAULT 'general' |
Category slug reference |
author_name |
TEXT |
DEFAULT 'Editorial Team' |
Author display name |
author_avatar |
TEXT |
NULLABLE |
Author avatar image URL |
author_role |
TEXT |
NULLABLE |
Author title/role |
author_bio |
TEXT |
NULLABLE |
Author short biography |
is_featured |
INTEGER |
DEFAULT 0 |
1 = Featured item, 0 = Standard |
is_sticky |
INTEGER |
DEFAULT 0 |
1 = Pinned to top of feed, 0 = Standard |
status |
TEXT |
DEFAULT 'published' |
Status (published, draft, archived) |
reading_time_min |
INTEGER |
DEFAULT 1 |
Estimated reading duration in minutes |
published_at |
TEXT |
NOT NULL |
ISO 8601 UTC timestamp (2026-08-02T10:00:00Z) |
created_at |
TEXT |
DEFAULT CURRENT_TIMESTAMP |
Record creation timestamp |
updated_at |
TEXT |
DEFAULT CURRENT_TIMESTAMP |
Last update timestamp |
B. content_categories Table¶
| Column | Type | Constraints | Description |
|---|---|---|---|
slug |
TEXT |
PRIMARY KEY |
Category key (engineering, product) |
name_en |
TEXT |
NOT NULL |
English category title |
name_ar |
TEXT |
NOT NULL |
Arabic category title |
description |
TEXT |
NULLABLE |
Category description |
C. content_types Table¶
| Column | Type | Constraints | Description |
|---|---|---|---|
slug |
TEXT |
PRIMARY KEY |
Type key (article, guide, case-study) |
name_en |
TEXT |
NOT NULL |
English type title |
name_ar |
TEXT |
NOT NULL |
Arabic type title |
description |
TEXT |
NULLABLE |
Content type description |
D. content_tags Table¶
| Column | Type | Constraints | Description |
|---|---|---|---|
item_id |
INTEGER |
NOT NULL |
Foreign key referencing content_items.id |
tag |
TEXT |
NOT NULL |
Tag keyword string |
3. FlightPHP REST API Specification¶
Public Endpoints¶
GET /api/content/items¶
Retrieves published content items with dynamic filtering and pagination.
Query Parameters
- type (optional): Filter by type slug (article, guide). Pass all to ignore filter.
- category (optional): Filter by category slug. Pass all to ignore filter.
- tag (optional): Filter by tag keyword.
- featured (optional): 1 for featured only.
- sticky (optional): 1 for sticky only.
- search (optional): Search query string matching title or summary.
- page (optional): Page number (Default: 1).
- limit (optional): Items per page (Default: 10, Max: 100).
Response Example
{
"items": [
{
"id": 1,
"slug": "welcome-to-tidyfactor",
"type": "article",
"title": "Welcome to TidyFactor-Go",
"summary": "Platform announcement and feature overview.",
"body": "# Welcome...",
"coverImage": "/uploads/welcome.jpg",
"category": "news",
"authorName": "Editorial Team",
"isFeatured": 1,
"isSticky": 1,
"status": "published",
"readingTimeMin": 3,
"publishedAt": "2026-08-02T10:00:00Z",
"tags": ["announcement", "platform"]
}
],
"pagination": {
"page": 1,
"limit": 10,
"totalItems": 1,
"totalPages": 1
}
}
GET /api/content/item/@slug¶
Fetches a single published publication by its unique slug.
Response (200 OK): Single article JSON object.
Errors (404 Not Found): {"error": "Content item not found"}.
GET /api/content/categories¶
Returns array of registered category objects.
GET /api/content/types¶
Returns array of registered content type objects.
GET /api/content/tags¶
Returns list of unique tags with published item counts.
Admin Endpoints (Session Authenticated)¶
GET /api/admin/content/items¶
Lists all items regardless of status (includes draft, scheduled, archived).
POST /api/admin/content/items¶
Creates a new content item.
Request Body
{
"title": "New Research Guide",
"slug": "new-research-guide",
"type": "guide",
"category": "engineering",
"summary": "Technical research summary.",
"body": "## Executive Summary\n\nContent details...",
"coverImage": "/uploads/guide.jpg",
"authorName": "Engineering Lead",
"isFeatured": 0,
"isSticky": 0,
"status": "published",
"tags": ["engineering", "research"]
}
PUT /api/admin/content/items/@id¶
Updates an existing content item matching @id.
DELETE /api/admin/content/items/@id¶
Deletes a content item matching @id and prunes associated tags.
4. Performance & Core Architectural Guards¶
- Payload Un-bloating:
GET /api/content/siteexcludes full article bodies from the main site configuration payload, ensuring instant homepage load times. - Double Storage Bloat Elimination:
ContentService::updateContent()unsetscontentEnginebefore writing to the single-rowcontenttable, preventing redundant article duplication betweencontentandcontent_items. - ISO 8601 UTC Standardization: All timestamp properties (
publishedAt,createdAt,updatedAt) are formatted with standard ISO 8601'T'delimiters to guarantee cross-browser compatibility across Safari, Chrome, and Mobile WebKit. - Subfolder API Path Resolution: All frontend requests wrap relative paths using
resolveApiUrl('api/content/...')fromsrc/lib/apiUrl.ts.