Building my portfolio blog with Dev.to and Next.js
View on dev.toCheck out my website here: stevenborrie.com
Previously I had experimented with tools like nextra, however I was unhappy with the lack of simplicity, and the default themes.
Dev.to API
Turns out, the dev.to API is incredibly simple. You can give it a try:
- JSON array of all my posts: https://dev.to/api/articles?username=saborrie
- This post: https://dev.to/api/articles/saborrie/building-my-portfolio-blog-with-devto-and-nextjs-268f
I realised I can just put all my posts on dev.to, and use it as a CMS database for my website.
Building my blog in Next.js
All I wanted to create was 2 pages: a home page, and a blog post page. The home page would be at /
and the blog page at /post/[slug]
. On the home page, I wanted to show a list of links to all of my blog posts, and on the blog post page, I wanted to show the content based on the [slug]
parameter in the URL.
After setting up my project using yarn create next-app
selecting typescript and the new app router, I added the following code to the homepage in src/app/page.tsx
:
import Link from "next/link";
export default async function Home() {
const posts = await fetch("https://dev.to/api/articles?username=saborrie", {
next: { revalidate: 10 },
}).then((x) => x.json());
return (
<main>
<h2>Posts</h2>
{posts.map(({ slug, title, description }: any) => (
<Link href={`/post/${slug}`} className="post-list-item">
<h3>{title}</h3>
<small>{description}</small>
</Link>
))}
</main>
);
}
The new app router supports server side fetching by making your page components an async
function. By default, Next.js will cache the results of the fetch
at build time. We can configure the fetch
to rerun during server rendering by setting the revalidate
setting - I've set it to revalidate every 10 seconds in the code above.
To create the blog post page at /post/[slug]
I added the file src/app/post/[slug]/page.tsx
. Using the following code I am able to write out the title, cover_image, url, and body_html from the dev.to API:
export default async function Post({ params }: any) {
const post = await fetch(`https://dev.to/api/articles/francescoxx/${params.slug}`, {
next: { revalidate: 10 },
}).then((x) => x.json());
return (
<div className="post">
<img title="cover image" className="cover-image" src={post.cover_image} />
<main>
<h1>{post.title}</h1>
<small>
<a href={post.url}>View on dev.to</a>
</small>
<div dangerouslySetInnerHTML={{ __html: String(post.body_html) }} />
</main>
</div>
);
}
This worked great, except that I needed to do some work to get syntax highlighting in the code snippets. As dev.to is open source you can just go get the scss file at https://github.com/forem/forem/blob/main/app/assets/stylesheets/components/syntax.scss. To import scss in Next.js you need to run yarn add sass
. And that's it, it worked. I was then able to copy my existing css from my old nextra portfolio in and I was done.