How I Custom-built My Markdown Blog

Austin Central Library. © 2021 John Apostol

The Use Case

Joy in coding

Joy in writing

My Tech Choices

TypeScript

Next.js

Vercel

Hosting, caching, preview deployments; all for the price of free.

Markdown

Why not Gatsby?

Main Concepts

Thinking as a user

Code

// [slug].tsx
import React from "react";
import ReactMarkdown from "react-markdown";
import CodeBlock from "../../components/CodeBlock";
import Heading from "../../components/Heading";
import Image from "../../components/Image";
import Link from "../../components/Link";
import Paragraph from "../../components/Paragraph";
const Post = () => {
const renderers = {
code: CodeBlock,
heading: Heading,
image: Image,
link: Link,
paragraph: Paragraph,
};
return (
<ReactMarkdown source={postBody} renderers={renderers} />
)
}
...
--- 
title: "Using Redux with Vanilla JS"
preview: "What follows is an explanation of how I've used Redux to make a production vanilla JS app more maintainable."
slug: "using-redux-with-vanilla-js"
tags: ["software", "javascript"]
---
![wide](hero.jpg)Redux is a popular state management library for JavaScript apps that is routinely paired with frameworks like React or Angular. What follows is an explanation of how I’ve used Redux to make a production vanilla JS app more maintainable. I’m hoping this is useful for anyone out there who is looking for a real-world Redux + vanilla JS example beyond a button incrementer or to-do app.
// package.json
...
"scripts": {
...
"watch:posts": "processmd posts/*.md --outputDir content --summaryOutput content/summary.json --watch"
},
...
Post.getInitialProps = async ({
query: { date, preview, slug },
}) => {
const { bodyContent, title } = await import(`../content/${date}.json`);
return {
date,
postBody: bodyContent,
preview,
slug,
title,
};
};
// summary.json{ 
"fileMap": {
"content/2019-01-30.json": {
"title": "Using Redux with Vanilla JS",
"preview": "What follows is an explanation of how I've used Redux to make a production vanilla JS app more maintainable.",
"slug": "using-redux-with-vanilla-js",
"tags": ["software", "javascript"],
"dir": "content",
"base": "2019-01-30.json",
"ext": ".json",
"sourceBase": "2019-01-30.md",
"sourceExt": ".md"
},
...
}
...
export const getStaticProps = async () => {
const summary = await import("../content/summary.json");
const { sourceFileArray, fileMap } = summary;
const recent = sourceFileArray.slice(-5).reverse();
const posts = recent.map((sourceFile) => {
const destFile = sourceFile
.replace("posts/", "content/")
.replace(".md", ".json");
return {
...fileMap[destFile],
date: fileToDate(destFile),
};
});
return { props: { posts } };
};

Inspired by Medium

On the left is Medium. On the right is my blog.

Polishing

Not yet done

Engineering Manager at The Zebra — johnapostol.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store