Table of Contents
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.
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.
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.
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>
);
}