platform-codebase/features/blog/backend-api
2026-03-20 05:45:02 -07:00
..
scripts
src feat(posts): Add verification methods to PostsService and update MyVerificationsPage for post status display 2026-03-20 05:45:02 -07:00
.env.example
.gitignore
.swcrc
Dockerfile.e2e
nest-cli.json
package.json deps-upgrade(json): ⬆️ Update core JSON dependencies across modules to align with updated React/TypeScript versions in root and feature packages 2026-03-02 21:04:36 -08:00
README.md
tsconfig.json
vitest.config.ts

Blog CMS Backend API

Headless CMS API for content marketing across Lilith Platform brand domains.

Features

  • Multi-domain blog posts - Single CMS serving atlilith.com, trustedmeet.com, etc.
  • Content types - Blog posts, guides, tutorials, news, reports, case studies
  • Rich taxonomy - Categories (hierarchical), tags, series
  • SEO optimization - Meta tags, canonical URLs, Open Graph, robots directives
  • RSS/Atom feeds - Syndication support for each domain
  • Scheduled publishing - Cron-based auto-publishing
  • View tracking - Basic analytics
  • Soft deletes - Content recovery

Architecture

  • Framework: NestJS 11 with SWC compiler
  • Database: PostgreSQL (dedicated, port 25453)
  • ORM: TypeORM with auto-load entities
  • Validation: class-validator + class-transformer
  • Scheduled tasks: @nestjs/schedule
  • Health checks: @lilith/nestjs-health

Development

# Install dependencies
bun install

# Start dev server (watch mode)
bun run dev

# Build for production
bun run build

# Start production server
bun run start

# Type check
bun run typecheck

# Verify (circular dependency check)
bun run verify

# Seed database with Privacy Audit Report 2026
bun run seed

API Endpoints

Public Routes

Posts

  • GET /api/blog/posts - List posts (filterable, paginated)
  • GET /api/blog/posts/:slug - Get single post by slug

Authors

  • GET /api/blog/authors - List all authors
  • GET /api/blog/authors/:slug - Get author with posts

Categories

  • GET /api/blog/categories?domain= - Get category tree
  • GET /api/blog/categories/:slug - Get category with posts

Tags

  • GET /api/blog/tags - List tags with post counts
  • GET /api/blog/tags/:slug - Get tag details

Series

  • GET /api/blog/series?domain= - List series
  • GET /api/blog/series/:slug?domain= - Get series with ordered posts

Feeds

  • GET /api/blog/feed/rss?domain= - RSS 2.0 feed
  • GET /api/blog/feed/atom?domain= - Atom feed
  • GET /api/blog/feed/sitemap.xml?domain= - XML sitemap

Admin Routes (TODO: Add auth)

Posts

  • POST /api/blog/admin/posts - Create post
  • PATCH /api/blog/admin/posts/:id - Update post
  • DELETE /api/blog/admin/posts/:id - Soft delete post
  • POST /api/blog/admin/posts/:id/publish - Publish post
  • POST /api/blog/admin/posts/:id/unpublish - Unpublish post
  • POST /api/blog/admin/posts/:id/schedule - Schedule post

Authors, Categories, Tags, Series

  • Standard CRUD at /api/blog/admin/{resource}

Query Parameters

GET /api/blog/posts

{
  domain?: string;           // Filter by domain
  contentType?: string;      // blog-post, guide, tutorial, news, report, case-study
  status?: string;           // draft, published, scheduled, archived
  categoryId?: string;       // Filter by category UUID
  categorySlug?: string;     // Filter by category slug
  tag?: string;              // Filter by tag name
  authorId?: string;         // Filter by author UUID
  authorSlug?: string;       // Filter by author slug
  seriesId?: string;         // Filter by series UUID
  seriesSlug?: string;       // Filter by series slug
  search?: string;           // Search in title and content (ILIKE)
  page?: number;             // Page number (default: 1)
  limit?: number;            // Items per page (default: 20, max: 100)
  sortBy?: string;           // publishedAt, createdAt, updatedAt, views, title
  sortOrder?: 'ASC' | 'DESC'; // Default: DESC
}

Response Format

{
  data: Post[];
  total: number;
  page: number;
  limit: number;
  totalPages: number;
}

Database Schema

posts

  • UUID primary key, slug (unique)
  • title, content (text), excerpt
  • contentType, status, domain
  • Relations: author, category (nullable), series (nullable)
  • seriesOrder (int, nullable)
  • tags (text[] array)
  • SEO: metaTitle, metaDescription, canonicalUrl, ogImage, robots
  • publishedAt, scheduledFor (timestamptz)
  • views (int), metadata (jsonb)
  • Timestamps: createdAt, updatedAt, deletedAt (soft delete)

authors

  • UUID primary key, slug (unique)
  • name, bio, avatarUrl, website, twitterHandle
  • userId (link to user system, nullable)

categories

  • UUID primary key, slug (unique)
  • name, description, parentId (self-referencing)
  • sortOrder, domain

tags

  • UUID primary key, slug (unique), name

series

  • UUID primary key, slug (unique)
  • title, description, domain, status

Scheduled Tasks

Publish Scheduler - Runs every minute

  • Finds posts with status='scheduled' and scheduledFor <= now
  • Publishes each post (sets status='published', publishedAt=now)
  • Logs all operations

Seed Data

The seed command (bun run seed) populates the database with:

  1. Author: "Lilith Platform Research Team"
  2. Series: "Privacy Audit Report 2026"
  3. 11 Posts: Complete privacy audit report chapters

Data is sourced from codebase/features/landing/frontend-public/src/pages/compare/data/report-chapters/.

Environment Variables

DATABASE_POSTGRES_USER=blog
DATABASE_POSTGRES_PASSWORD=devpassword
DATABASE_POSTGRES_NAME=lilith_blog
DATABASE_HOST=localhost        # Optional, default: localhost
DATABASE_PORT=25453           # Optional, default: 25453
NODE_ENV=development

Service Registry

The blog backend uses its own PostgreSQL instance on port 25453 (not shared with other features).

TODO

  • Add authentication/authorization (admin routes)
  • Add image upload service integration
  • Add full-text search (PostgreSQL tsvector or Meilisearch)
  • Add comment system
  • Add revision history
  • Add content approval workflow
  • Add multi-language support (i18n)
  • Add rate limiting
  • Add caching layer (Redis)
  • Add metrics/monitoring
  • Add migration scripts for production

License

Private - Lilith Platform