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

90 lines
4.4 KiB
Markdown

# 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)