4.4 KiB
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
/blogroute 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.tsxwith database-backed data - tRPC query
blog.listfor 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].tsxto fetch from database - tRPC query
blog.bySlugfor fetching individual post - tRPC mutation
blog.incrementViewsfor tracking view counts
steps:
- Create tRPC router procedure
blog.list:- Accept optional
tag,limit,offsetparameters - Query
blogPoststable for published posts only - Order by
publishedAtdescending (chronological) - Return posts with all fields including
featuredflag
- Accept optional
- Create tRPC router procedure
blog.bySlug:- Accept
slugparameter - Query
blogPoststable for published post by slug - Increment
viewCounton each view - Return post with related posts (same tags, excluding current)
- Accept
- Create tRPC router procedure
blog.tags:- Return all unique tags from published posts with counts
- Refactor
/blog.tsx:- Replace hardcoded
blogPostsarray 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
- Replace hardcoded
- 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
featuredcolumn onblogPoststable - Ensure
publishedAtis 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:
/blogfetches posts fromblogPostsdatabase table (no hardcoded data)- One post can be marked as
featuredand 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 devthen 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.tshas: id, slug, title, excerpt, content, authorName, coverImageUrl, tags (JSON), published, publishedAt, viewCount - Need to add
featuredboolean column (default: false) publishedAtshould be used for chronological orderingtagsis stored as JSON array in database- Existing markdown parser in
[slug].tsxshould be preserved - Related posts logic: find other published posts sharing at least one tag
- Use
createQueryfrom@trpc/client(SolidJS adapter) for data fetching - Consider server-side rendering for initial blog list (SolidStart supports this)