voxblog/BACKEND_UPDATES.md

3.3 KiB

Backend Updates Summary

Database Schema Changes

Posts Table - New Fields Added

  1. ghost_slug (VARCHAR(255), nullable)

    • Stores the Ghost post slug for association
    • Used to link VoxBlog posts with their Ghost counterparts
  2. ghost_published_at (DATETIME(3), nullable)

    • Timestamp when the post was published to Ghost
    • Helps track publication history
  3. selected_image_keys (TEXT, nullable)

    • JSON array of selected image keys for the post
    • Persists user's image selection for the Generate step
    • Stored as JSON string, parsed on retrieval

Migration File

  • Location: apps/api/drizzle/0001_jittery_revanche.sql
  • Status: Migration has been generated and applied
ALTER TABLE `posts` ADD `ghost_slug` varchar(255);
ALTER TABLE `posts` ADD `ghost_published_at` datetime(3);
ALTER TABLE `posts` ADD `selected_image_keys` text;

To apply this migration (if needed on other environments):

cd apps/api
pnpm drizzle:migrate

API Endpoint Changes

1. GET /api/posts/:id

Added Response Fields:

  • ghostPostId: string | null
  • ghostSlug: string | null
  • ghostPublishedAt: Date | null
  • ghostUrl: string | null
  • selectedImageKeys: string[] (parsed from JSON)

2. POST /api/posts

Added Request Body Fields:

  • selectedImageKeys: string[] (optional)
  • ghostPostId: string (optional)
  • ghostSlug: string (optional)
  • ghostPublishedAt: string (optional, ISO date string)
  • ghostUrl: string (optional)

Behavior:

  • selectedImageKeys is serialized to JSON before storage
  • Ghost fields are only updated if provided in the request
  • All fields are nullable and optional

3. GET /api/media/list

Added Query Parameters:

  • page: number (default: 1, min: 1)
  • pageSize: number (default: 50, min: 1, max: 200)

Updated Response:

{
  "items": [...],
  "total": number,
  "page": number,
  "pageSize": number
}

Note: Due to S3 limitations, pagination fetches page * pageSize items and slices them. For large datasets, consider implementing cursor-based pagination or caching.

Files Modified

  1. apps/api/src/db/schema.ts

    • Added new fields to posts table definition
  2. apps/api/src/posts.ts

    • Updated GET endpoint to return new fields
    • Updated POST endpoint to accept and store new fields
    • Added JSON serialization/deserialization for selectedImageKeys
  3. apps/api/src/media.ts

    • Added pagination support to /list endpoint
    • Implemented page and pageSize query parameters

Testing Checklist

  • Run database migration
  • Test POST /api/posts with selectedImageKeys array
  • Test GET /api/posts/:id returns selectedImageKeys as array
  • Test POST /api/posts with Ghost fields
  • Test GET /api/media/list?page=1&pageSize=50
  • Test GET /api/media/list?page=2&pageSize=50
  • Verify selectedImageKeys persists across save/load cycles
  • Verify Ghost fields update correctly on publish

Frontend Integration

The frontend has been updated to:

  1. Send selectedImageKeys when saving posts
  2. Load selectedImageKeys when opening posts
  3. Use pagination for media library
  4. Update post status after Ghost publish
  5. Auto-upload audio recordings

All frontend changes are complete and ready to work with these backend updates.