Skip to content

CMS Overview

The CMS (cms-myeasyguide) is a standalone Next.js 16 application for managing blog posts, travel guides, authors, categories, and AI-powered content generation. It operates independently from the main Express API with its own PostgreSQL database and admin UI.

Purpose

The CMS was extracted from the main API to provide:

  • Dedicated content management — Rich text editing, post scheduling, SEO management
  • AI content generation — Batch blog post generation via Claude API
  • Independent deployments — Content updates don't require API deployments
  • Focused admin experience — Tailored for content editors, not commerce operations

Key Features

FeatureDescription
Post CRUDCreate, edit, publish, schedule, trash blog posts and travel guides
Rich Text EditorLexical-based editor with HTML output
Categories & SubcategoriesHierarchical content organization
Author ManagementAuthor profiles, authentication, dashboard
AI GenerationClaude API batch generation for bulk blog creation
City & Country ManagementGeographic tagging for content
Tag ManagementContent tagging system
Image UploadFile upload for post cover images
Scheduled Publishingnode-cron checks every minute for scheduled posts
OpenAPI SpecAuto-generated API documentation
SEO ToolsMeta titles/descriptions, canonical URLs, JSON-LD schema

Admin UI

The CMS admin is at /admin and includes:

RoutePurpose
/admin/postsPost list with status filtering
/admin/posts/editCreate/edit post
/admin/posts/edit/{slug}Edit specific post
/admin/authorsAuthor CRUD
/admin/post-categoriesCategory management
/admin/subcategoriesSubcategory management
/admin/manage-citiesCity management
/admin/manage-countriesCountry management
/admin/generateAI blog generation

CMS API Routes

The CMS exposes a RESTful API for the admin UI and for the public frontend:

RoutePurpose
GET /api/posts/{slug}Public: single post with related content
GET /api/posts/publishedPublic: published posts (paginated, searchable)
GET /api/posts/category/{slug}Public: posts by category (blog/travel-guide)
GET /api/posts/author/{id}Public: posts by author
GET /api/posts/resolve/{slug}Public: resolve slug to canonical path
GET /api/postsAuth: all posts (admin)
POST /api/postsAuth: create post
PATCH /api/posts/{slug}Auth: update post
DELETE /api/posts/{slug}Auth: trash/delete post
GET /api/posts/restore/{id}Auth: restore from trash
GET /api/authorsPublic: list authors
POST /api/authorsAuth: create author
PATCH /api/authors/{id}Auth: update author
DELETE /api/authors/{id}Auth: delete author
GET /api/post-categoriesPublic: list categories
POST /api/post-categoriesAuth: create category
PATCH /api/post-categories/{id}Auth: update category
DELETE /api/post-categories/{id}Auth: delete category
GET /api/citiesPublic: list cities
POST /api/citiesAuth: create city
GET /api/countriesPublic: list countries
GET /api/tagsPublic: list tags
POST /api/uploadAuth: upload file
POST /api/auth/loginPublic: author login

Authentication

The CMS uses JWT-based auth with the jose library:

  • Authors log in via POST /api/auth/login
  • JWT stored in httpOnly cookie
  • Protected routes use requireAuth() from lib/auth.ts
  • Session retrieval via getSession() from cookies

Scheduled Publishing

The CMS runs a node-cron job (initialized in instrumentation.ts) that runs every minute:

  1. Queries for posts where status = "scheduled" and scheduledAt <= now
  2. Updates status to "published" and sets publishedAt
  3. Generates canonical URL

Post Status Lifecycle

     ┌─────────┐
     │  DRAFT  │
     └────┬────┘


     ┌───────────┐
     │ SCHEDULED │──(cron)──▶ ┌───────────┐
     └───────────┘            │ PUBLISHED │
                              └─────┬─────┘
          ┌─────────┐               │
          │  TRASH  │◀──────────────┘
          └─────────┘

Separated from API

The CMS was originally part of the Express API. The Editorial Migration page documents the full extraction process, including which API files were removed and why.

Built with VitePress