Is this thing on?
What is even happening right now?
I'm getting a little static blog space set up with next.js so I can finally maybe start doing a thing that I've been wanting to do for many years: write.
Go on...
I really want to avoid that thing where I get stuck fiddling around, trying to learn new stuff (like GraphQL), or coming up with a clever design, or some fancy widgets, or hooking up to a WordPress API or whatever. So I decided to roll with next.js hosted on Netlify, becuase it's just so darn easy.
I was all about Gatsby for awhile, but for this little blog project I've been down those roads so many times, and it always ends up with me not actually finishing anything because the reality is I don't have a whole lot of free time. I've got young kids and a full time job. But the cool thing is that my new job allows for a bit more time to learn and explore, so I can actually do this kind of thing at work when things are slow.
So I'm just rolling with the bare minimum setup and styling that came out of the basic next.js hello world tutorial. And we'll see what happens from there.
It took some time, but I finally got code syntax highlighting to work:
// javascript weeeeeee
const poop = () => {
return 💩;
}
// what about .scss?
$greenish: #bada55;
.thing {
color: $greenish;
}
Since we're using remark to process these markdown files to HTML, it seemed best to find a remark thing. remark-prism seemed like the best thing to try first, and it worked fine locally, but Netlify borked on the deploy for some reason. I got this error:
ModuleNotFoundError: Module not found: Error: Can't resolve 'canvas' in '/opt/build/repo/node_modules/jsdom/lib/jsdom'
I googled around and found some hints at various solutions, like npm installing canvas, adding a next.config.js with various things in it, but none of it worked. In the end I went with remark-highlight.js instead, and that worked just fine, once I figured out that I could import the different stylesheets to get a decent theme. It would be cool if you could try them out on the highlight.js website, more than just clicking the style name to get a random sample, but nbd. In the end, this is how I have it set up:
// in lib/posts.ts
...
import remark from "remark";
import html from "remark-html";
import highlight from "remark-highlight.js";
...
export async function getPostData(id: string) {
const fullPath = path.join(postsDirectory, `${id}.md`);
const fileContents = fs.readFileSync(fullPath, "utf8");
// Use gray-matter to parse the post metadata section
const matterResult = matter(fileContents);
// Use remark to convert markdown into HTML string
const processedContent = await remark()
.use(html)
.use(highlight)
.process(matterResult.content);
const contentHtml = processedContent.toString();
// Combine the data with the id and contentHtml
return {
id,
contentHtml,
...(matterResult.data as { date: string; title: string }),
};
}
// in pages/posts/[id].tsx
import Layout from "../../components/layout";
import { getAllPostIds, getPostData } from "../../lib/posts";
import Head from "next/head";
import Date from "../../components/date";
import "highlight.js/styles/tomorrow-night-eighties.css";
import utilStyles from "../../styles/utils.module.scss";
import { GetStaticProps, GetStaticPaths } from "next";
export default function Post({
postData,
}: {
postData: {
title: string;
date: string;
contentHtml: string;
};
}) {
return (
<Layout>
<Head>
<title>{postData.title}</title>
</Head>
<article>
<h1 className={utilStyles.headingXl}>{postData.title}</h1>
<div className={utilStyles.lightText}>
<Date dateString={postData.date} />
</div>
<div dangerouslySetInnerHTML={{ __html: postData.contentHtml }} />
</article>
</Layout>
);
}
export const getStaticPaths: GetStaticPaths = async () => {
const paths = getAllPostIds();
return {
paths,
fallback: false,
};
};
export const getStaticProps: GetStaticProps = async ({ params }) => {
const postData = await getPostData(params.id as string);
return {
props: {
postData,
},
};
};