Skip to main content
Version: 1.0

Content Service

Repo: o-apps/content-service (fluxcd app directory: content-api) · Port: 2088

A general-purpose CMS/community backend: articles, blog posts, documents, videos, and a discussion forum, backed by S3-compatible object storage for file uploads.

Key Capabilities​

  • Articles & blog — CRUD for articles; blog posts additionally support slugs, categories, and a view counter
  • Documents & videos — upload, list, get, download, and delete, with presigned S3 URLs for downloads (expiry configurable via PRESIGN_EXPIRY_SECONDS)
  • Forum — posts and threaded replies, upvoting, "accept answer," and per-course/per-user post listings — the course-context fields suggest this backs discussion threads tied to course-service content
  • Image uploads — a dedicated endpoint for inline image uploads (e.g. for article/blog body content)

Auth​

A single API_KEY gates every route uniformly (router.Use(authMiddleware.Handler) applied globally, before any route registration) — there's no split between public and admin routes the way customer-service has for its contact form.

REST API​

MethodPathDescription
POST | GET | PUT | DELETE/articles, /articles/{id}Article CRUD
POST | GET | PUT | DELETE/blogs, /blogs/{id}Blog post CRUD
GET/blogs/slug/{slug}Get a blog post by slug
GET/blogs/category/{category}List by category
POST/blogs/slug/{slug}/viewsIncrement view count
POST | GET | DELETE/documents, /documents/{id}Document CRUD
GET/documents/{id}/downloadPresigned download URL
POST | GET | PUT | DELETE/videos, /videos/{id}Video CRUD
GET/videos/{id}/downloadPresigned download URL
POST/upload/imageInline image upload
POST | GET | PUT | DELETE/forum/posts, /forum/posts/{postId}Forum post CRUD
POST/forum/posts/{postId}/views | /upvoteView count / upvote
GET/forum/posts/course/{courseId} | /user/{userId} | /searchFiltered post listings
POST | GET | PUT | DELETE/forum/replies, /forum/replies/{replyId}Reply CRUD
GET/forum/posts/{postId}/repliesReplies for a post
POST/forum/replies/{replyId}/upvoteUpvote a reply
POST/forum/posts/{postId}/accept/{replyId}Accept a reply as the answer
GET/healthHealth check (unauthenticated)
GET/docs, /swaggerSwagger UI

Environment Variables​

VariableDescription
DATABASE_URLPostgreSQL connection — required, no fallback
API_KEYShared secret every route requires
AWS_REGIONDefault: eu-north-1
AWS_S3_BUCKETDefaults to <environment>-kubeopera-content-service
AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEYS3 credentials
AWS_USE_STATIC_CREDSUse static credentials instead of the instance/pod role
PRESIGN_EXPIRY_SECONDSDownload URL expiry (default: 900)
HTTP_PORTHTTP port (default: 2088)