October 29, 2020 | 2 minutes read
Using Dev.to as a CMS with Next.js
#react#nextjs#cms#devto
Thanks to @swyx for the idea and most of the logic. Check his post out.
Dev.to is a great place to share and learn from others.
It can get pretty tedious if you're busy posting blogs in two places. Luckily, Dev.to provides an API that allows you to get all your posted content for free!
If you want a full implementation, check out my website code
Here's the code I used to get it working. It has some minor changes from Swyx's code.
1// postsApi.tsx23let normalizePost = (post: Post): Post => {4 const { data, content } = matter(post.body_markdown);5 return {6 ...post,7 // remove the last bit (its a 4 digit identifier, not needed here)8 slug: post.slug.split("-").slice(0, -1).join("-"),9 matter: { data, content },10 };11};1213let sleep = async (ms: number = 0) => new Promise(resolve => setTimeout(resolve,ms))1415export let query = async () => {16 // next does parallel builds17 // dev.to doesnt allow more than 2 requests per second (as far as I can tell18 // we gotta slow it down19 await sleep(1000)20 // we cache the response21 // otherwise we'll hit the 429 error "Too many requests" during build times22 let cached = cache.get<Post[]>();23 if (cached) return cached;2425 let posts: Post[] = [];26 let page = 0;27 let per_page = 30; // can go up to 100028 let latestResult = [];2930 do {31 page += 1; // bump page up by 1 every loop32 latestResult = await fetch(33 `https://dev.to/api/articles/me/published?page=${page}&per_page=${per_page}`,34 {35 headers: {36 "api-key": process.env.dev_token as string,37 },38 }39 )40 .then((res) =>41 res.status !== 200 ? Promise.reject(res.statusText) : res.json()42 )43 .then((x) => (posts = posts.concat(x)))44 .catch((err) => {45 throw new Error(`error fetching page ${page}, ${err}`);46 });47 } while (latestResult.length === per_page);48 posts = posts.map(normalizePost);49 cache.set(posts);50 return posts;51};
Here you can see it's a simple loop aggregating all of our posts.
I've added a cache because, on my website, Dev.to would return a
status code because the requests were happening too fast.1429
This is fine since there's almost no chance our posts will become stale while we are building.
After that I call
to get a list of my posts:1query
1// pages/blog.tsx23export async function getStaticProps() {4 let posts = await postsApi.query();5 return {6 props: {7 posts,8 },9 revalidate: 1,10 };11}
Tada! It was much smoother than I expected. Thanks a lot dev.to!