24
loading...
This website collects cookies to deliver better user experience
next-mdx-remote
from Hashicorp for the parsing and rendering of my MDX files and with the latest major version, v3, it got to be a little tricky so hopefully you'll find this helpful!feed
package and installed it as a dev dependency.# Using yarn
yarn add feed -D
# or using NPM
npm install feed --save-dev
feeds.tsx
in my utils
directory. And we'll start off with this:import fs from 'fs';
import { Feed } from 'feed';
import { serialize } from 'next-mdx-remote/serialize';
import { MDXRemote } from 'next-mdx-remote';
import { renderToStaticMarkup } from 'react-dom/server';
import { MDXComponents } from '@components/MDX';
import { getPosts } from '@utils/mdx';
const generateFeeds = async () => {
}
data
directory.// ...
const generateFeeds = async () => {
const domain = process.env.NEXT_PUBLIC_MAIN_DOMAIN || process.env.VERCEL_URL;
const posts = await getPosts();
const siteURL = `https://${domain}`;
const date = new Date();
const author = {
name: 'Kevin Langley Jr.',
email: '[email protected]',
link: 'https://kevinlangleyjr.dev',
};
}
// ...
// ...
const feed = new Feed( {
title: 'Kevin Langley | Web Engineer',
description: '',
id: siteURL,
link: siteURL,
image: `${siteURL}/kevinlangleyjr.jpg`,
copyright: `All rights reserved ${date.getFullYear()}, Kevin Langley Jr.`,
updated: date,
generator: 'Next.js',
feedLinks: {
rss2: `${siteURL}/rss/feed.xml`,
json: `${siteURL}/rss/feed.json`,
atom: `${siteURL}/rss/atom.xml`,
},
author,
} );
// ...
next-mdx-remote
package and no longer having the renderToString
method in v3, we are using renderToStaticMarkup
from react-dom/server
to generate the markup to add to our feeds.// ...
for ( const post of posts ) {
const url = `${siteURL}/blog/${post.slug}`;
const { content, ...postData } = post;
const mdxSource = await serialize( content, {
scope: postData as Record<string, any>, // Scope expects a <Record> here.
mdxOptions: {
remarkPlugins: [
// I use a few different remark plugins, check out my "How I built my blog" article for more information!
],
},
} );
const markup = renderToStaticMarkup(
<MDXRemote components={ MDXComponents } { ...mdxSource } />
);
feed.addItem(
{
title: post.title,
guid: post.slug,
id: url,
link: url,
description: post.excerpt,
content: markup,
author: [author],
contributor: [author],
date: new Date( post.published_date ),
}
);
}
// ...
// ...
fs.mkdirSync( './public/rss', { recursive: true } );
fs.writeFileSync( './public/rss/feed.xml', feed.rss2() );
fs.writeFileSync( './public/rss/atom.xml', feed.atom1() );
fs.writeFileSync( './public/rss/feed.json', feed.json1() );
// ...
getStaticProps
method in the blog index and it will generate on build. I like to wrap it in a check for the VERCEL
environment variable which will then only run when building on the Vercel platform, or if I pass in the environment variable when building locally.// ...
export const getStaticProps: GetStaticProps = async () => {
const { posts, hasNextPage } = getPostsForPage();
if ( process.env?.VERCEL ) {
await generateFeeds();
}
return {
props: {
posts,
hasNextPage,
},
};
};
// ...
feed.tsx
file with all the steps completed.import fs from 'fs';
import { Feed } from 'feed';
import { serialize } from 'next-mdx-remote/serialize';
import { MDXRemote } from 'next-mdx-remote';
import { renderToStaticMarkup } from 'react-dom/server';
import { MDXComponents } from '@components/MDX';
import { getPosts } from '@utils/mdx';
const generateFeeds = async () => {
const domain = process.env.NEXT_PUBLIC_MAIN_DOMAIN || process.env.VERCEL_URL;
const posts = await getPosts();
const siteURL = `https://${domain}`;
const date = new Date();
const author = {
name: 'Kevin Langley Jr.',
email: '[email protected]',
link: 'https://kevinlangleyjr.dev',
};
const feed = new Feed( {
title: 'Kevin Langley | Web Engineer',
description: '',
id: siteURL,
link: siteURL,
image: `${siteURL}/kevinlangleyjr.jpg`,
copyright: `All rights reserved ${date.getFullYear()}, Kevin Langley Jr.`,
updated: date,
generator: 'Next.js',
feedLinks: {
rss2: `${siteURL}/rss/feed.xml`,
json: `${siteURL}/rss/feed.json`,
atom: `${siteURL}/rss/atom.xml`,
},
author,
} );
for ( const post of posts ) {
const url = `${siteURL}/blog/${post.slug}`;
const { content, ...postData } = post;
const mdxSource = await serialize( content, {
scope: postData as Record<string, any>, // Scope expects a <Record> here.
mdxOptions: {
remarkPlugins: [
// I use a few different remark plugins, check out my "How I built my blog" article for more information!
],
},
} );
const markup = renderToStaticMarkup(
<MDXRemote components={ MDXComponents } { ...mdxSource } />
);
feed.addItem(
{
title: post.title,
guid: post.slug,
id: url,
link: url,
description: post.excerpt,
content: markup,
author: [author],
contributor: [author],
date: new Date( post.published_date ),
}
);
fs.mkdirSync( './public/rss', { recursive: true } );
fs.writeFileSync( './public/rss/feed.xml', feed.rss2() );
fs.writeFileSync( './public/rss/atom.xml', feed.atom1() );
fs.writeFileSync( './public/rss/feed.json', feed.json1() );
}
next-sitemap
which provides a simple API to create a sitemap from your static, dynamic, and server side pages in Next.js.# Using yarn
yarn add next-sitemap -D
# or using NPM
npm install -D next-sitemap
next-sitemap.js
and I provided a basic configuration within. You can find the different configuration options supported in the READMEmodule.exports = {
siteUrl: `https://${ process.env.VERCEL\_URL }`,
generateRobotsTxt: true,
};
package.json
, I added next-sitemap
to the postbuild
script.{
"build": "next build",
"postbuild": "next-sitemap"
}
sitemap.xml
and if you set generateRobotsTxt
to true
in the configuration, a robots.txt
generated into your public
directory.