Skip to content
This repository was archived by the owner on May 15, 2026. It is now read-only.

MKT-69: Add /blog/[slug] post page with dynamic rendering - #11019

Draft
ghost wants to merge 6 commits into
mainfrom
feature/MKT-69-blog-post-page
Draft

ghost wants to merge 6 commits into
mainfrom
feature/MKT-69-blog-post-page

Conversation

@ghost

@ghost ghost commented Jan 27, 2026 •

Copy link
Copy Markdown

Related GitHub Issue

Linear issue: MKT-69

Roo Code Task Context (Optional)

View task on Roo Code Cloud

Description

Adds the /blog/[slug] page that renders individual blog posts with request-time publish gating.

Key implementation details:

  1. Dynamic rendering: export const dynamic = "force-dynamic" ensures publish gating at request time
  2. Node.js runtime: export const runtime = "nodejs" for filesystem reads
  3. Security: Returns 404 for drafts, future-scheduled posts, or invalid slugs (no leakage)
  4. Markdown rendering: Uses react-markdown + remark-gfm (no raw HTML)
  5. Typography: Consistent styling with custom component overrides
  6. Metadata: Dynamic OG tags with title, description, and publish date

Build output shows dynamic rendering:

ƒ /blog/[slug]                           176 B         104 kB

Test Procedure

  1. Build passes: pnpm -C apps/web-roo-code build
  2. Visit /blog/prds-are-becoming-artifacts-of-the-past in dev
  3. Verify markdown renders with proper formatting
  4. Verify 404 returned for non-existent slugs
  5. Verify 404 returned for draft/future posts (change post status to test)

Pre-Submission Checklist

  • Issue Linked: This PR is linked to Linear issue MKT-69
  • Scope: Blog post page only
  • Self-Review: Verified 404 logic and markdown rendering
  • Testing: Build and lint pass
  • Documentation Impact: N/A
  • Contribution Guidelines: Reviewed

Screenshots / Videos

N/A - requires full stack for visual testing

Documentation Updates

  • No documentation updates required

Additional Notes

Dependencies (included via merge):

  • MKT-67: Content pipeline
  • MKT-73: First post
  • MKT-68: Blog index

Security:

  • No raw HTML rendering (safe by default)
  • Drafts and future posts return 404
  • No generateStaticParams (preserves request-time gating)

Get in Touch

Via Roo Code Cloud task link above


Important

Adds a dynamic /blog/[slug] page with publish gating, markdown rendering, and metadata handling, including content management and validation in content.ts.

  • Behavior:
    • Adds /blog/[slug] page with dynamic rendering and publish gating using dynamic = "force-dynamic" and runtime = "nodejs" in page.tsx.
    • Returns 404 for drafts, future-scheduled posts, or invalid slugs in page.tsx.
    • Renders markdown using react-markdown and remark-gfm without raw HTML in page.tsx.
  • Content Management:
    • Implements getAllBlogPosts() and getBlogPostBySlug() in content.ts for loading and filtering posts.
    • Validates frontmatter using zod in content.ts.
    • Adds BlogContentError for handling content validation errors in content.ts.
  • Metadata and SEO:
    • Generates dynamic metadata including OG tags in page.tsx.
    • Uses ogImageUrl for generating image URLs for metadata in page.tsx.
  • Dependencies:
    • Adds gray-matter for frontmatter parsing in package.json.

This description was created by Ellipsis for aa4c2d9. You can customize this summary. It will automatically update as commits are pushed.

- Add gray-matter for frontmatter parsing
- Create BlogPost type and zod schema for validation
- Implement PT timezone helpers (getNowPt, parsePublishTimePt)
- Implement content loading (getAllBlogPosts, getBlogPostBySlug)
- Implement isPublished for request-time publish gating
- Add validation for frontmatter and duplicate slugs
- Create content/blog directory for markdown files

Closes: MKT-67
…he Past

Adds the first canonical blog post to validate the content pipeline:
- Title: PRDs Are Becoming Artifacts of the Past
- Slug: prds-are-becoming-artifacts-of-the-past
- Status: published
- Publish date: 2026-01-12 at 9:00am PT

Content sourced from Office Hours S01E15 with Paige Bailey.

Closes: MKT-73
- Create blog index page at /blog
- Use force-dynamic for request-time publish gating
- Require Node.js runtime for filesystem reads
- Display posts with title, description, and date
- Add empty state when no posts are published
- Include tags display (up to 3)

Closes: MKT-68
- Create dynamic route for individual blog posts
- Use force-dynamic for request-time publish gating
- Require Node.js runtime for filesystem reads
- Return 404 for drafts, future posts, or invalid slugs
- Render Markdown with react-markdown + remark-gfm
- No raw HTML rendering (safe by default)
- Include consistent typography and styling

Closes: MKT-69
@ghost

ghost commented Jan 27, 2026 •

Copy link
Copy Markdown
Author

Rooviewer Clock   See task on Roo Cloud

Review complete. Previous issue fixed, but 1 new issue introduced.

  • Fix lexicographic time comparison in content.ts - posts on the same date are sorted incorrectly because publish_time_pt strings are compared alphabetically instead of numerically
  • Add missing import for parsePublishTimePt in content.ts - the function is used on line 160 but not imported, causing a runtime error
Previous reviews

Mention @roomote in a comment to request specific changes to this pull request or fix all unresolved issues.

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Preview deployed!

Your changes have been deployed to Vercel:

Preview URL: https://roo-code-website-fyxsdiwuc-roo-code.vercel.app

This preview will be updated automatically when you push new commits to this PR.

Comment thread apps/web-roo-code/src/lib/blog/content.ts Outdated
@mp-roocode mp-roocode self-assigned this Jan 27, 2026
Co-authored-by: roomote[bot] <219738659+roomote[bot]@users.noreply.github.com>
if (dateCompare !== 0) {
return dateCompare
}
return parsePublishTimePt(b.publish_time_pt) - parsePublishTimePt(a.publish_time_pt)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parsePublishTimePt is used here but not imported. The import statement on line 7 only includes getNowPt from "./pt-time". This will cause a runtime error when getAllBlogPosts is called. Update line 7 to: import { getNowPt, parsePublishTimePt } from "./pt-time"

Fix it with Roo Code or mention @roomote and request a fix.

This branch has not been deployed

No deployments
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

No open projects
Status: Triage

Development

Successfully merging this pull request may close these issues.

2 participants