Skip to content

feat: get latest version spacedf docs#33

Merged
kinhdev24 merged 2 commits into
mainfrom
feat/get-latest-version-spacedf-docs
Apr 17, 2026
Merged

feat: get latest version spacedf docs#33
kinhdev24 merged 2 commits into
mainfrom
feat/get-latest-version-spacedf-docs

Conversation

@huyphan02
Copy link
Copy Markdown
Member

No description provided.

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 17, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spacedf-docs Ready Ready Preview, Comment Apr 17, 2026 8:10am

Request Review

@kinhdev24 kinhdev24 merged commit cb5dd3d into main Apr 17, 2026
2 checks passed
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request replaces hardcoded version strings with dynamic versioning by fetching the latest release information from blog post metadata. It introduces a getLatestVersion utility to parse MDX frontmatter and updates the VersionLabel component and root layout to use this data. Feedback suggests handling cases where version data is missing in VersionLabel to prevent rendering errors and refactoring the version utility to use asynchronous file system operations to improve performance and prevent blocking the event loop.

Comment on lines +3 to 6
export default function VersionLabel({ latestVersion }) {
const handleClick = () => {
window.location.href = "/blog/v2026.02.13"
window.location.href = `/blog/${latestVersion?.version}`
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The component should return null if latestVersion or its version property is missing. This prevents rendering an empty styled label and avoids navigating to an invalid URL (e.g., /blog/undefined).

export default function VersionLabel({ latestVersion }) {
  if (!latestVersion?.version) return null

  const handleClick = () => {
    window.location.href = "/blog/" + latestVersion.version
  }

Comment thread src/lib/version.ts
Comment on lines +1 to +45
import fs from "fs"
import path from "path"
import matter from "gray-matter"

type LatestVersion = {
slug: string
version: string
date?: string
title?: string
type?: string
author?: string
description?: string
}

export const getLatestVersion = async (): Promise<LatestVersion | null> => {
const POSTS_DIR = path.join(process.cwd(), "src/app/blog/(post)")

if (!fs.existsSync(POSTS_DIR)) return null

const results: LatestVersion[] = []
const folders = fs.readdirSync(POSTS_DIR)

for (const folder of folders) {
const fullPath = path.join(POSTS_DIR, folder, "page.mdx")
if (!fs.existsSync(fullPath)) continue

const raw = fs.readFileSync(fullPath, "utf-8")
if (!raw) continue

const { data } = matter(raw)

results.push({
...(data as Omit<LatestVersion, "slug" | "version">),
version: folder,
slug: `/blog/${folder}`,
})
}

const latest =
results.sort(
(a, b) => new Date(b.date ?? 0).getTime() - new Date(a.date ?? 0).getTime(),
)[0] ?? null

return latest
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Since getLatestVersion is an asynchronous function, it is best practice to use asynchronous file system operations (fs/promises) to avoid blocking the Node.js event loop. Additionally, adding error handling for file access and parsing ensures the application remains robust if the directory structure or file content is unexpected.

import fs from "fs/promises"
import path from "path"
import matter from "gray-matter"

type LatestVersion = {
  slug: string
  version: string
  date?: string
  title?: string
  type?: string
  author?: string
  description?: string
}

export const getLatestVersion = async (): Promise<LatestVersion | null> => {
  const POSTS_DIR = path.join(process.cwd(), "src/app/blog/(post)")

  try {
    const stats = await fs.stat(POSTS_DIR)
    if (!stats.isDirectory()) return null
  } catch {
    return null
  }

  const folders = await fs.readdir(POSTS_DIR)
  const results: LatestVersion[] = []

  for (const folder of folders) {
    const fullPath = path.join(POSTS_DIR, folder, "page.mdx")
    try {
      const raw = await fs.readFile(fullPath, "utf-8")
      const { data } = matter(raw)

      results.push({
        ...(data as Omit<LatestVersion, "slug" | "version">),
        version: folder,
        slug: "/blog/" + folder,
      })
    } catch {
      continue
    }
  }

  return (
    results.sort((a, b) => {
      const timeA = a.date ? new Date(a.date).getTime() : 0
      const timeB = b.date ? new Date(b.date).getTime() : 0
      return timeB - timeA
    })[0] ?? null
  )
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants