Integrate ContentLayer to NextJs

To manage typed writings, Integrated the next content-layer to project. It automates TypeScript type generation and simplifies content querying, allowing you to focus on creating and delivering high-quality content effortlessly.

Why Content Layer?

Content layer helps to transform data into the type-safed JSON data, which can easily imported in the project and build application arround it.

Don't you had any other alternatives?

Yes!. There are library I personlly checked and commpared

  1. Content Layer
  2. Velite
  3. Content Collections

there may be more which I may not aware of...

But why i choose content layer the main reason is the community support to this sdk compare to the velite. Even though velite is the open source tool, it has potential. In future I may go for the as the light wieght tool velite.

How to Set it up?

Install the packages, as we are using the NextJs we need to install the extra package that is officaly supported from the content layer

yarn add contentlayer next-contentlayer date-fns

Next.js Configuration

To hook Contentlayer into the next dev and next build processes, you'll want to wrap the Next.js configuration using the withContentlayer method.

next.config.mjs
import { withContentlayer } from "next-contentlayer";
 
/** @type {import('next').NextConfig} */
const nextConfig = { reactStrictMode: true }
 
export default withContentlayer(nextConfig)

Follow official document next-contentlayer

create the config file contentlayer.config.ts, and pasted the sample file of this project

contentlayer.config.ts
import { type ComputedFields, defineDocumentType, makeSource } from 'contentlayer/source-files'
 
const computedFields = {
 path: {
   type: "string",
   resolve: (post) => `/${post._raw.flattenedPath}`,
 },
 slug: {
   type: "string",
   resolve: (post) => post._raw.flattenedPath.split("/").slice(1).join("/"),
 },
} satisfies ComputedFields
 
export const Project = defineDocumentType(() => ({
 name: 'Project',
 filePathPattern: `./project/**/*.mdx`,
 contentType: "mdx",
 fields: {
   title: { type: 'string', required: true },
   date: { type: 'date', required: true },
   description: {
     type: "string",
     required: true,
   },
   published: {
     type: "boolean",
   },
   repository: {
     type: "string",
   },
   url: {
     type: "string",
   },
 },
 computedFields,
}))
 
export default makeSource({ contentDirPath: 'src/content', documentTypes: [Project] })

Then create the page file on the directory app/projects/page.tsx and create basic page with layout, import the

import { allProjects, type Project } from 'contentlayer/generated'

if you want to use the import like contentlayer/generated then you need to modify the tsconfig.json file; check here is the sample

tsconfig.json
{
 "compilerOptions": {
   "target": "ES2015",
   "lib": [
     "dom",
     "dom.iterable",
     "esnext"
   ],
   "allowJs": true,
   "skipLibCheck": true,
   "strict": true,
   "forceConsistentCasingInFileNames": true,
   "noEmit": true,
   "esModuleInterop": true,
   "module": "esnext",
   "moduleResolution": "bundler",
   "resolveJsonModule": true,
   "isolatedModules": true,
   "jsx": "preserve",
   "incremental": true,
   "plugins": [
     {
       "name": "next"
     }
   ],
   "baseUrl": ".",
   "paths": {
     "@/*": [
       "./src/*"
     ],
     "contentlayer/generated": [
       "./.contentlayer/generated"
     ]
   }
 },
 "include": [
   "next-env.d.ts",
   "additional.d.ts",
   "**/*.ts",
   "**/*.tsx",
   ".next/types/**/*.ts",
   ".contentlayer/generated"
 ],
 "exclude": [
   "node_modules"
 ]
}