Files
Kordant/tasks/landing-pages-and-admin/03-blog-database-integration.md
2026-05-26 09:38:54 -04:00

4.4 KiB

03. Blog Route With DB Integration, Featured Post, And Chronological Feed

meta: id: landing-pages-and-admin-03 feature: landing-pages-and-admin priority: P1 depends_on: [landing-pages-and-admin-02] tags: [implementation, routes, blog, database, tRPC]

objective:

  • Refactor the /blog route to fetch posts from the database via tRPC instead of hardcoded data, support a featured post display at the top, and show remaining posts in chronological order with tag filtering and pagination.

deliverables:

  • Rewritten /web/src/routes/blog.tsx with database-backed data
  • tRPC query blog.list for fetching posts with filtering, pagination, and featured flag
  • Featured post hero section at top of blog listing
  • Chronological feed with tag filtering and pagination
  • Updated /web/src/routes/blog/[slug].tsx to fetch from database
  • tRPC query blog.bySlug for fetching individual post
  • tRPC mutation blog.incrementViews for tracking view counts

steps:

  • Create tRPC router procedure blog.list:
    • Accept optional tag, limit, offset parameters
    • Query blogPosts table for published posts only
    • Order by publishedAt descending (chronological)
    • Return posts with all fields including featured flag
  • Create tRPC router procedure blog.bySlug:
    • Accept slug parameter
    • Query blogPosts table for published post by slug
    • Increment viewCount on each view
    • Return post with related posts (same tags, excluding current)
  • Create tRPC router procedure blog.tags:
    • Return all unique tags from published posts with counts
  • Refactor /blog.tsx:
    • Replace hardcoded blogPosts array with tRPC query
    • Add featured post section at top (large card with full excerpt, shown only if a post is marked featured)
    • Show remaining posts in chronological grid below featured post
    • Preserve tag filtering UI (fetch tags from database)
    • Preserve pagination ("Load More Posts" button)
    • Add loading states and error handling
  • Refactor /blog/[slug].tsx:
    • Replace hardcoded data with tRPC query by slug
    • Preserve markdown rendering, author sidebar, related posts, social sharing
    • Add 404 handling for non-existent slugs
    • Track view count on page load
  • Add database migration for featured column on blogPosts table
  • Ensure publishedAt is properly set on all existing posts

tests:

  • Unit: tRPC queries return correct data shapes
  • Integration: Blog list page loads posts from database
  • Integration: Featured post displays at top when one is marked featured
  • Integration: Tag filtering correctly filters posts
  • Integration: Pagination loads next batch of posts
  • Integration: Individual post page loads by slug and increments view count
  • Integration: 404 shown for non-existent slug

acceptance_criteria:

  • /blog fetches posts from blogPosts database table (no hardcoded data)
  • One post can be marked as featured and displays prominently at the top of the blog listing
  • Remaining posts display in chronological order (newest first)
  • Tag filtering works with tags sourced from the database
  • Pagination ("Load More") loads additional posts in batches
  • /blog/[slug] fetches individual post from database
  • View count increments each time a post is viewed
  • Related posts section shows posts with matching tags
  • 404 page shown for non-existent blog slugs
  • Loading states displayed while data is being fetched

validation:

  • cd /Users/mike/Code/Kordant/web && pnpm dev then navigate to /blog
  • Verify posts load from database (not hardcoded)
  • Mark a post as featured via admin and verify it appears at top
  • Test tag filtering by clicking different tag buttons
  • Click "Load More" and verify additional posts load
  • Navigate to individual post and verify content renders correctly
  • Refresh post page and verify view count increments
  • Navigate to non-existent slug and verify 404

notes:

  • Current blog schema in marketing.ts has: id, slug, title, excerpt, content, authorName, coverImageUrl, tags (JSON), published, publishedAt, viewCount
  • Need to add featured boolean column (default: false)
  • publishedAt should be used for chronological ordering
  • tags is stored as JSON array in database
  • Existing markdown parser in [slug].tsx should be preserved
  • Related posts logic: find other published posts sharing at least one tag
  • Use createQuery from @trpc/client (SolidJS adapter) for data fetching
  • Consider server-side rendering for initial blog list (SolidStart supports this)