Last updated dates with Contentlayer

@sirajchokshi

Table of Contents

  1. Getting the last updated date
  2. Defining a computed field
  3. Using the lastEdited field

When building documentation and blog sites in fields where recency is important (like technology), it’s useful to display the last updated date of a post. While not supported at the framework level, last edited labels are easy to implement with Contentlayer’s computed fields.

Getting the last updated date

Contentlayer document types give us reference to the raw source file, which we can use to get the last modified date using Node functions.

contentlayer/utils.ts
import fs from "node:fs";
import path from "node:path";
 
import { DocumentGen } from "contentlayer/core";
 
/**
 * Check when a contentlayer document's source
 * file was last updated
 */
export function getLastEditedDate(doc: DocumentGen): Date {
  const filepath = path.join("posts/", doc._raw.sourceFilePath);
  const stats = fs.statSync(filepath);
  return stats.mtime;
}

Defining a computed field

This helper can be used to define a lastEdited field on the Post document type which will resolve at build time.

contentlayer/types/post.ts
import { getLastEditedDate } from "../utils";
import { defineDocumentType } from "contentlayer/source-files";
 
export const Post = defineDocumentType(() => ({
  name: "Post",
  contentType: "mdx",
  filePathPattern: `**/*.mdx`,
  fields: {
    title: { type: "string", required: true },
    date: { type: "date", required: true },
  },
  computedFields: {
    lastEdited: {
      type: "date",
      resolve: getLastEditedDate,
    },
  },
}));

Using the lastEdited field

After generating types again the lastEdited field is available on the Post type and can be rendered on posts. The field is a Date object, so it can be formatted using a library like date-fns.

pages/blog/[slug].tsx
import { Post, allPosts } from "contentlayer/generated";
import { useMDXComponent } from "next-contentlayer/hooks";
import { format } from "date-fns";
 
export default function Post({ post }: { post: Post }) {
  const MDXContent = useMDXComponent(post.body.code);
 
  return (
    <article>
      <h1>{post.title}</h1>
      <MDXContent />
      <footer>
        Last updated
        <time dateTime={post.lastEdited}>
          {format(post.lastEdited, "LLLL d, yyyy")}
        </time>)
      </footer>
    </article>
  );
}