Why I Stopped Using Ghost
I liked the idea of opening up my iPad, sipping on a caramel latte in an overly-hipster Brooklyn cafe, writing a new tech post. Ghost CMS was my way to do that ( -- my favorite full stack framework
-- to use React within my markdown (probably won't use much JSX, but hey why not at least have it)
-- deployment
Getting Started
I've started using the T3 CLI to make my apps these days because the stack generally is one I enjoy and I love the cohesion together.
npm create t3-app@latest
Only select Tailwind, we don't need the other packages
After installation, we can clear up the homepage
import { type NextPage } from 'next';
import Head from 'next/head';
const Home: NextPage = () => {
return (
<>
<Head>
<title>Create T3 App</title>
<meta name="description" content="Generated by create-t3-app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className="flex min-h-screen flex-col items-center bg-gradient-to-b from-[#2e026d] to-[#15162c] pt-20">
<h1 className="text-7xl font-bold text-white">My Cool Blog</h1>
</main>
</>
);
};
export default Home;
Configuring MDX
To be able to write .mdx files, we'll need a few plugins
- @next/mdx -- to use with Next
- @mdx-js/loader -- required package of @next/mdx
- @mdx-js/react -- required package of @next/mdx
- gray-matter -- to ignore frontmatter from rendering
- rehype-autolink-headings -- allows to add links to headings with ids on there already
- rehype-slug -- allows to add links to headings for documents that don't already have ids
- rehype-pretty-code -- makes code pretty with syntax highlighting, line numbers, etc
- remark-frontmatter -- plugin to support frontmatter
- shiki -- coding themes we can use for rendering code snippets
yarn add @next/mdx @mdx-js/loader @mdx-js/react gray-matter rehype-autolink-headings rehype-slug rehype-pretty-code remark-frontmatter shiki
Setting Up Contentlayer
yarn add -D @tailwindcss/typography
Add that to your tailwind.config.cjs
module.exports = {
theme: {
// ...
},
plugins: [
require('@tailwindcss/typography'),
// ...
],
};
Now, how do we actually render the blog post? Contentlayer gives us a NextJS specific hook
We can modify some of the styles in globals.css
First lets fix the typography
.prose :is(h1, h2, h3, h4, h5, h6) > a {
@apply no-underline text-white;
}
.prose {
@apply text-white;
}
And lets style our code plugins
code[data-line-numbers] {
padding-left: 0 !important;
padding-right: 0 !important;
}
code[data-line-numbers] > .line::before {
counter-increment: line;
content: counter(line);
display: inline-block;
width: 1rem;
margin-right: 1.25rem;
margin-left: 0.75rem;
text-align: right;
color: #676e95;
}
div[data-rehype-pretty-code-title] + pre {
@apply !mt-0 !rounded-tl-none;
}
div[data-rehype-pretty-code-title] {
@apply !mt-6 !max-w-max !rounded-t !border-b !border-b-slate-400 !bg-[#2b303b] !px-4 !py-0.5 !text-gray-300 dark:!bg-[#282c34];
}
Much better :)

SOCIAL SHARE CARD GENERATOR