{"slug":"how-to-create-an-api-from-markdown-files-with-next-js","highlight":"I've previously talked about how to read markdown files from Next.js' API routes. However, it was only recently, while improving some of my blog's logic, that I realised the true value of this technique. So here's a simple guide on how to create an incredibly powerful content API from your Markdown files and double your build speed while you're at it.\n","content":"I've previously talked about [how to read markdown files from Next.js' API routes](https://ironeko.com/posts/how-to-read-markdown-files-from-next-js-api-routes). However, it was only recently, while improving some of my blog's logic, that I realised the true value of this technique. So here's a simple guide on how to create an incredibly powerful content API from your Markdown files and **double your build speed** while you're at it.\n\n![Hero image with the text \"Speed up your static generation with a Next.js markdown API and ISR\"](/images/frame-139-1-.png)\n\n## The setup\n\nBefore you can actually get started turning your markdown files into an API, you'll need these files in an easily readable and parsable format. I would recommend following my explanation on how to [transform your markdown to JSON at build time](https://ironeko.com/posts/how-to-read-markdown-files-from-next-js-api-routes#how-to-work-around-nextjs-api-filesystem-limitations) but really any way to get your markdown into JSON will probably work.\n\nYou'll need your different categories of content each in a JSON file with each element being part of a larger array. For example I had:\n\n* `posts.json`\n* `authors.json`\n* `categories.json`\n\n## Creating your API endpoints\n\nLet's create endpoints to fetch our posts as an example.\n\n```javascript\n// pages/api/posts/index.js\n\n// You'll need to specify the absolute URL to fetch your file\nconst url = `http://example.com`\n\n/**\n * fetches and returns all posts from json cache\n */\nexport const getAllPosts = async () => {\n    const data = (await fetch(`${url}/cache/posts.json`).then((res) =>\n        res.json()\n    ))\n    return data\n}\n\n/**\n * Returns current page from query string. If undefined, returns 0.\n */\nexport const pagination = (req) => {\n    const { page = '0' } = req.query as { page: string }\n    const actualPage = parseInt(page) <= 0 ? 1 : parseInt(page)\n    return actualPage\n}\n\n/**\n * Returns a list of paginated posts\n */\nconst posts = async (req, res) => {\n    const page = pagination(req)\n    const data = (await getAllPosts())\n        // sort posts by publish date\n        .sort((post1, post2) => (post1.data.date > post2.data.date ? -1 : 1))\n        // only take 10 depending on page value\n        .slice((page - 1) * 10, page * 10)\n    res.status(200).json(data)\n}\n\nexport default posts\n```\n\nIt's fairly straightforward since we don't need to do a whole lot apart from return our entire JSON file. Nonetheless, we *can* implement small UX improvements.\n\n* On line `32` we sort our content by publishing date\n* We paginate all of our content, so we don't have to repeat the code in our pages\n\nYou can check out how [Ironeko's endpoint looks as an example](https://ironeko.com/api/posts).\n\nThe second piece of the puzzle is to then create an endpoint used just to return one singular piece of content. We'll use it to actually create our pages.\n\n```javascript\n// pages/api/posts/[slug].js\n\n// You'll need to specify the absolute URL to fetch your file\nconst url = `http://example.com`\n\n/**\n * fetches and returns all posts from json cache\n */\nexport const getAllPosts = async () => {\n    const data = (await fetch(`${url}/cache/posts.json`).then((res) =>\n        res.json()\n    ))\n    return data\n}\n\n/**\n * Finds and returns a single post\n */\nconst post = async (req, res) => {\n    const { slug } = req.query\n    const data = (await getAllPosts()).find((p) => p.slug === slug)\n    if (data) {\n        res.status(200).json(data)\n    } else {\n        res.status(404)\n        res.end()\n    }\n}\n\nexport default post\n```\n\nThe above is very similar to our endpoint, only with some minor differences:\n\n* We filter our data to find a post that matches the `slug` provided in the API url\n\n  * A `slug` is a unique piece of text that identifies our article. For example you can see the slug for this page in the URL `how-to-create-an-api-from-markdown-files-with-next-js`\n* If we couldn't find a match in our data we return a 404 error, which we'll then handle when trying to display the page\n\nIf you've done it right it'll look something like [the endpoint we use here on Ironeko](https://ironeko.com/api/posts/how-to-create-an-api-from-markdown-files-with-next-js).\n\n## Combining your new endpoints with Next.js' ISR to improve your build time\n\nIf you've managed a static site before you'll no doubt have noticed how **each time a new piece of content is added your builds take a little bit longer**. This blog has just over 100 articles, and the build time has slowly crawled to around 3 minutes... Every. Time. I. Edit. Something.\n\nY﻿ou may have heard of **Incremental Static Regeneration** before. (If not, Smashing Magazine published the fantastic [A Complete Guide To Incremental Static Regeneration (ISR) With Next.js](https://www.smashingmagazine.com/2021/04/incremental-static-regeneration-nextjs/) which is an excellent explanation of the feature.)\n\n<Notice>\n\n\n\nThere's a lot of magic related to how Incremental Static Regeneration works, but it's a fantastic feature and you don't necessarily need to understand how it functions to use it to its full potential.\n\n\n\n</Notice>\n\nThe point of ISR is that rather than telling Next.js how many pages you want to generate at build time, you'll just have to tell it where to get the information to generate them. The pages will then be generated upon request.\n\nThanks to your new endpoint you can replace your `getStaticProps` and `getStaticPaths` with a much simpler:\n\n```javascript\n// pages/posts/[slug].js\n\n// You'll need to specify the absolute URL to fetch your file\nconst url = `http://example.com`\n\nexport const getStaticPaths = async () => {\n    return {\n        paths: [],\n        fallback: 'blocking',\n    }\n}\n\nexport const getStaticProps = async ({ params }) => {\n    const { slug } = params\n\n    const post = (await fetch(`${url}/api/posts/${slug}`)\n        .then((res) => res.json())\n        .catch(() => null))\n\n    if (!post) {\n        return {\n            notFound: true,\n        }\n    }\n\n    return {\n        props: {\n            post,\n        },\n        revalidate: 60,\n    }\n}\n```\n\nYou should see your build time cut down exponentially depending on how much content you have!\n\n## Bonus: Serialize your markdown (or mdx) on build\n\nIdeally with these changes you'll want to keep your serverless function execution time as short as possible (especially if you're on a Vercel Hobby plan). So there's a couple more corners you can cut.\n\nIf you're using markdown or mdx you can actually serialize your markdown into a usable string outside of your `getStaticProps`. When generating your caches, rather than adding your markdown to your cache you can convert it directly to HTML or JSX so you won't have to convert it later while generating your page!\n\n```javascript\n// use this wherever you transform your markdown into JSON\n\nimport matter from 'gray-matter'\nimport { serialize } from 'next-mdx-remote/serialize'\nimport { remark } from 'remark'\nimport html from 'remark-html'\n\n/**\n * Convert a markdown file to JSON\n */\nconst serializeMarkdown = async (markdownFile) => {\n  // we extract the front-matter info from our markdown\n  const matterResult = matter(markdownFile)\n  \n  // convert the markdown body into HTML\n  const html = remark().use(html).processSync(matterResult.content)\n  \n  // or generate a JSX string from your MDX!\n  const mdx = await serialize(matterResult.content)\n\n  return {\n      html,\n      mdx,\n      ...matterResult,\n  }\n}\n```\n\nWith these small changes Ironeko's build time dropped to around 40 seconds. This has improved my quality of life considerably, so you should definitely give it a try if you're falling out of love with static generation.\n","data":{"layout":"blog","title":"How to create an api from markdown files with Next.js","categories":[{"slug":"technology","highlight":"","content":"","data":{"name":"Technology","visible":true,"description":"Frameworks, libraries, interesting new releases in the world of tech and programming. If this sounds good to you, you’re in the right place."},"isEmpty":false,"excerpt":"","mdx":{"compiledSource":"/*@jsxRuntime automatic @jsxImportSource react*/\nconst {Fragment: _Fragment, jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n  return _jsx(_Fragment, {});\n}\nfunction MDXContent(props = {}) {\n  const {wrapper: MDXLayout} = Object.assign({}, _provideComponents(), props.components);\n  return MDXLayout ? _jsx(MDXLayout, Object.assign({}, props, {\n    children: _jsx(_createMdxContent, props)\n  })) : _createMdxContent(props);\n}\nreturn {\n  default: MDXContent\n};\n","frontmatter":{},"scope":{}}},{"slug":"react","highlight":"","content":"","data":{"name":"React","visible":true,"description":"How to's and tutorials on our favorite Javascript library."},"isEmpty":false,"excerpt":"","mdx":{"compiledSource":"/*@jsxRuntime automatic @jsxImportSource react*/\nconst {Fragment: _Fragment, jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n  return _jsx(_Fragment, {});\n}\nfunction MDXContent(props = {}) {\n  const {wrapper: MDXLayout} = Object.assign({}, _provideComponents(), props.components);\n  return MDXLayout ? _jsx(MDXLayout, Object.assign({}, props, {\n    children: _jsx(_createMdxContent, props)\n  })) : _createMdxContent(props);\n}\nreturn {\n  default: MDXContent\n};\n","frontmatter":{},"scope":{}}},{"slug":"ux","highlight":"","content":"","data":{"name":"UX","visible":true,"description":"UX makes the world around. Or at least it does to us."},"isEmpty":false,"excerpt":"","mdx":{"compiledSource":"/*@jsxRuntime automatic @jsxImportSource react*/\nconst {Fragment: _Fragment, jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n  return _jsx(_Fragment, {});\n}\nfunction MDXContent(props = {}) {\n  const {wrapper: MDXLayout} = Object.assign({}, _provideComponents(), props.components);\n  return MDXLayout ? _jsx(MDXLayout, Object.assign({}, props, {\n    children: _jsx(_createMdxContent, props)\n  })) : _createMdxContent(props);\n}\nreturn {\n  default: MDXContent\n};\n","frontmatter":{},"scope":{}}}],"author":{"slug":"leonardo-petrucci","highlight":"@creativiii\n","content":"\n[@creativiii](https://twitter.com/creativiii)\n","data":{"name":"Leonardo Petrucci","avatar":"/images/leonardo-petrucci.jpg"},"isEmpty":false,"excerpt":"","mdx":{"compiledSource":"/*@jsxRuntime automatic @jsxImportSource react*/\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n  const _components = Object.assign({\n    p: \"p\",\n    a: \"a\"\n  }, _provideComponents(), props.components);\n  return _jsx(_components.p, {\n    children: _jsx(_components.a, {\n      href: \"https://twitter.com/creativiii\",\n      children: \"@creativiii\"\n    })\n  });\n}\nfunction MDXContent(props = {}) {\n  const {wrapper: MDXLayout} = Object.assign({}, _provideComponents(), props.components);\n  return MDXLayout ? _jsx(MDXLayout, Object.assign({}, props, {\n    children: _jsx(_createMdxContent, props)\n  })) : _createMdxContent(props);\n}\nreturn {\n  default: MDXContent\n};\n","frontmatter":{},"scope":{}}},"date":"2022-09-12T09:15:36.648Z","thumbnail":"/images/frame-139-1-.png","description":"Markdown can be an incredibly powerful tool, but a lot of content can start slowing down your site. This is a quick guide on how you can mitigate these issues with a static API and ISR.","published":true},"isEmpty":false,"excerpt":"","mdx":{"compiledSource":"/*@jsxRuntime automatic @jsxImportSource react*/\nconst {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n  const _components = Object.assign({\n    p: \"p\",\n    a: \"a\",\n    strong: \"strong\",\n    img: \"img\",\n    h2: \"h2\",\n    ul: \"ul\",\n    li: \"li\",\n    code: \"code\",\n    pre: \"pre\",\n    span: \"span\",\n    em: \"em\"\n  }, _provideComponents(), props.components), {Notice} = _components;\n  if (!Notice) _missingMdxReference(\"Notice\", true);\n  return _jsxs(_Fragment, {\n    children: [_jsxs(_components.p, {\n      children: [\"I've previously talked about \", _jsx(_components.a, {\n        href: \"https://ironeko.com/posts/how-to-read-markdown-files-from-next-js-api-routes\",\n        children: \"how to read markdown files from Next.js' API routes\"\n      }), \". However, it was only recently, while improving some of my blog's logic, that I realised the true value of this technique. So here's a simple guide on how to create an incredibly powerful content API from your Markdown files and \", _jsx(_components.strong, {\n        children: \"double your build speed\"\n      }), \" while you're at it.\"]\n    }), \"\\n\", _jsx(_components.p, {\n      children: _jsx(_components.img, {\n        src: \"/images/frame-139-1-.png\",\n        alt: \"Hero image with the text \\\"Speed up your static generation with a Next.js markdown API and ISR\\\"\",\n        width: \"1200\",\n        height: \"630\"\n      })\n    }), \"\\n\", _jsx(_components.h2, {\n      children: \"The setup\"\n    }), \"\\n\", _jsxs(_components.p, {\n      children: [\"Before you can actually get started turning your markdown files into an API, you'll need these files in an easily readable and parsable format. I would recommend following my explanation on how to \", _jsx(_components.a, {\n        href: \"https://ironeko.com/posts/how-to-read-markdown-files-from-next-js-api-routes#how-to-work-around-nextjs-api-filesystem-limitations\",\n        children: \"transform your markdown to JSON at build time\"\n      }), \" but really any way to get your markdown into JSON will probably work.\"]\n    }), \"\\n\", _jsx(_components.p, {\n      children: \"You'll need your different categories of content each in a JSON file with each element being part of a larger array. For example I had:\"\n    }), \"\\n\", _jsxs(_components.ul, {\n      children: [\"\\n\", _jsx(_components.li, {\n        children: _jsx(_components.code, {\n          children: \"posts.json\"\n        })\n      }), \"\\n\", _jsx(_components.li, {\n        children: _jsx(_components.code, {\n          children: \"authors.json\"\n        })\n      }), \"\\n\", _jsx(_components.li, {\n        children: _jsx(_components.code, {\n          children: \"categories.json\"\n        })\n      }), \"\\n\"]\n    }), \"\\n\", _jsx(_components.h2, {\n      children: \"Creating your API endpoints\"\n    }), \"\\n\", _jsx(_components.p, {\n      children: \"Let's create endpoints to fetch our posts as an example.\"\n    }), \"\\n\", _jsx(_components.pre, {\n      className: \"language-javascript\",\n      children: _jsxs(_components.code, {\n        className: \"language-javascript\",\n        children: [_jsx(_components.span, {\n          className: \"token comment\",\n          children: \"// pages/api/posts/index.js\"\n        }), \"\\n\\n\", _jsx(_components.span, {\n          className: \"token comment\",\n          children: \"// You'll need to specify the absolute URL to fetch your file\"\n        }), \"\\n\", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" url \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsxs(_components.span, {\n          className: \"token template-string\",\n          children: [_jsx(_components.span, {\n            className: \"token template-punctuation string\",\n            children: \"`\"\n          }), _jsx(_components.span, {\n            className: \"token string\",\n            children: \"http://example.com\"\n          }), _jsx(_components.span, {\n            className: \"token template-punctuation string\",\n            children: \"`\"\n          })]\n        }), \"\\n\\n\", _jsx(_components.span, {\n          className: \"token doc-comment comment\",\n          children: \"/**\\n * fetches and returns all posts from json cache\\n */\"\n        }), \"\\n\", _jsx(_components.span, {\n          className: \"token keyword module\",\n          children: \"export\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token function-variable function\",\n          children: \"getAllPosts\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"async\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token arrow operator\",\n          children: \"=>\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" data \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token keyword control-flow\",\n          children: \"await\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token function\",\n          children: \"fetch\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsxs(_components.span, {\n          className: \"token template-string\",\n          children: [_jsx(_components.span, {\n            className: \"token template-punctuation string\",\n            children: \"`\"\n          }), _jsxs(_components.span, {\n            className: \"token interpolation\",\n            children: [_jsx(_components.span, {\n              className: \"token interpolation-punctuation punctuation\",\n              children: \"${\"\n            }), \"url\", _jsx(_components.span, {\n              className: \"token interpolation-punctuation punctuation\",\n              children: \"}\"\n            })]\n          }), _jsx(_components.span, {\n            className: \"token string\",\n            children: \"/cache/posts.json\"\n          }), _jsx(_components.span, {\n            className: \"token template-punctuation string\",\n            children: \"`\"\n          })]\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token method function property-access\",\n          children: \"then\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token parameter\",\n          children: \"res\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token arrow operator\",\n          children: \"=>\"\n        }), \"\\n        res\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token method function property-access\",\n          children: \"json\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token keyword control-flow\",\n          children: \"return\"\n        }), \" data\\n\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), \"\\n\\n\", _jsx(_components.span, {\n          className: \"token doc-comment comment\",\n          children: \"/**\\n * Returns current page from query string. If undefined, returns 0.\\n */\"\n        }), \"\\n\", _jsx(_components.span, {\n          className: \"token keyword module\",\n          children: \"export\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token function-variable function\",\n          children: \"pagination\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token parameter\",\n          children: \"req\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token arrow operator\",\n          children: \"=>\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \" page \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token string\",\n          children: \"'0'\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" req\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token property-access\",\n          children: \"query\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword module\",\n          children: \"as\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token literal-property property\",\n          children: \"page\"\n        }), _jsx(_components.span, {\n          className: \"token operator\",\n          children: \":\"\n        }), \" string \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" actualPage \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token function\",\n          children: \"parseInt\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), \"page\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"<=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token number\",\n          children: \"0\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"?\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token number\",\n          children: \"1\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \":\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token function\",\n          children: \"parseInt\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), \"page\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token keyword control-flow\",\n          children: \"return\"\n        }), \" actualPage\\n\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), \"\\n\\n\", _jsx(_components.span, {\n          className: \"token doc-comment comment\",\n          children: \"/**\\n * Returns a list of paginated posts\\n */\"\n        }), \"\\n\", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token function-variable function\",\n          children: \"posts\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"async\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsxs(_components.span, {\n          className: \"token parameter\",\n          children: [\"req\", _jsx(_components.span, {\n            className: \"token punctuation\",\n            children: \",\"\n          }), \" res\"]\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token arrow operator\",\n          children: \"=>\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" page \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token function\",\n          children: \"pagination\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), \"req\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" data \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token keyword control-flow\",\n          children: \"await\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token function\",\n          children: \"getAllPosts\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n        \", _jsx(_components.span, {\n          className: \"token comment\",\n          children: \"// sort posts by publish date\"\n        }), \"\\n        \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token method function property-access\",\n          children: \"sort\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsxs(_components.span, {\n          className: \"token parameter\",\n          children: [\"post1\", _jsx(_components.span, {\n            className: \"token punctuation\",\n            children: \",\"\n          }), \" post2\"]\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token arrow operator\",\n          children: \"=>\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), \"post1\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token property-access\",\n          children: \"data\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token property-access\",\n          children: \"date\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \">\"\n        }), \" post2\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token property-access\",\n          children: \"data\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token property-access\",\n          children: \"date\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"?\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"-\"\n        }), _jsx(_components.span, {\n          className: \"token number\",\n          children: \"1\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \":\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token number\",\n          children: \"1\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n        \", _jsx(_components.span, {\n          className: \"token comment\",\n          children: \"// only take 10 depending on page value\"\n        }), \"\\n        \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token method function property-access\",\n          children: \"slice\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), \"page \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"-\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token number\",\n          children: \"1\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"*\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token number\",\n          children: \"10\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \",\"\n        }), \" page \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"*\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token number\",\n          children: \"10\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n    res\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token method function property-access\",\n          children: \"status\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token number\",\n          children: \"200\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token method function property-access\",\n          children: \"json\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), \"data\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), \"\\n\\n\", _jsx(_components.span, {\n          className: \"token keyword module\",\n          children: \"export\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword module\",\n          children: \"default\"\n        }), \" posts\\n\"]\n      })\n    }), \"\\n\", _jsxs(_components.p, {\n      children: [\"It's fairly straightforward since we don't need to do a whole lot apart from return our entire JSON file. Nonetheless, we \", _jsx(_components.em, {\n        children: \"can\"\n      }), \" implement small UX improvements.\"]\n    }), \"\\n\", _jsxs(_components.ul, {\n      children: [\"\\n\", _jsxs(_components.li, {\n        children: [\"On line \", _jsx(_components.code, {\n          children: \"32\"\n        }), \" we sort our content by publishing date\"]\n      }), \"\\n\", _jsx(_components.li, {\n        children: \"We paginate all of our content, so we don't have to repeat the code in our pages\"\n      }), \"\\n\"]\n    }), \"\\n\", _jsxs(_components.p, {\n      children: [\"You can check out how \", _jsx(_components.a, {\n        href: \"https://ironeko.com/api/posts\",\n        children: \"Ironeko's endpoint looks as an example\"\n      }), \".\"]\n    }), \"\\n\", _jsx(_components.p, {\n      children: \"The second piece of the puzzle is to then create an endpoint used just to return one singular piece of content. We'll use it to actually create our pages.\"\n    }), \"\\n\", _jsx(_components.pre, {\n      className: \"language-javascript\",\n      children: _jsxs(_components.code, {\n        className: \"language-javascript\",\n        children: [_jsx(_components.span, {\n          className: \"token comment\",\n          children: \"// pages/api/posts/[slug].js\"\n        }), \"\\n\\n\", _jsx(_components.span, {\n          className: \"token comment\",\n          children: \"// You'll need to specify the absolute URL to fetch your file\"\n        }), \"\\n\", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" url \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsxs(_components.span, {\n          className: \"token template-string\",\n          children: [_jsx(_components.span, {\n            className: \"token template-punctuation string\",\n            children: \"`\"\n          }), _jsx(_components.span, {\n            className: \"token string\",\n            children: \"http://example.com\"\n          }), _jsx(_components.span, {\n            className: \"token template-punctuation string\",\n            children: \"`\"\n          })]\n        }), \"\\n\\n\", _jsx(_components.span, {\n          className: \"token doc-comment comment\",\n          children: \"/**\\n * fetches and returns all posts from json cache\\n */\"\n        }), \"\\n\", _jsx(_components.span, {\n          className: \"token keyword module\",\n          children: \"export\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token function-variable function\",\n          children: \"getAllPosts\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"async\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token arrow operator\",\n          children: \"=>\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" data \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token keyword control-flow\",\n          children: \"await\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token function\",\n          children: \"fetch\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsxs(_components.span, {\n          className: \"token template-string\",\n          children: [_jsx(_components.span, {\n            className: \"token template-punctuation string\",\n            children: \"`\"\n          }), _jsxs(_components.span, {\n            className: \"token interpolation\",\n            children: [_jsx(_components.span, {\n              className: \"token interpolation-punctuation punctuation\",\n              children: \"${\"\n            }), \"url\", _jsx(_components.span, {\n              className: \"token interpolation-punctuation punctuation\",\n              children: \"}\"\n            })]\n          }), _jsx(_components.span, {\n            className: \"token string\",\n            children: \"/cache/posts.json\"\n          }), _jsx(_components.span, {\n            className: \"token template-punctuation string\",\n            children: \"`\"\n          })]\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token method function property-access\",\n          children: \"then\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token parameter\",\n          children: \"res\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token arrow operator\",\n          children: \"=>\"\n        }), \"\\n        res\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token method function property-access\",\n          children: \"json\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token keyword control-flow\",\n          children: \"return\"\n        }), \" data\\n\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), \"\\n\\n\", _jsx(_components.span, {\n          className: \"token doc-comment comment\",\n          children: \"/**\\n * Finds and returns a single post\\n */\"\n        }), \"\\n\", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token function-variable function\",\n          children: \"post\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"async\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsxs(_components.span, {\n          className: \"token parameter\",\n          children: [\"req\", _jsx(_components.span, {\n            className: \"token punctuation\",\n            children: \",\"\n          }), \" res\"]\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token arrow operator\",\n          children: \"=>\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \" slug \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" req\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token property-access\",\n          children: \"query\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" data \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token keyword control-flow\",\n          children: \"await\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token function\",\n          children: \"getAllPosts\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token method function property-access\",\n          children: \"find\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token parameter\",\n          children: \"p\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token arrow operator\",\n          children: \"=>\"\n        }), \" p\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token property-access\",\n          children: \"slug\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"===\"\n        }), \" slug\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token keyword control-flow\",\n          children: \"if\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), \"data\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \"\\n        res\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token method function property-access\",\n          children: \"status\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token number\",\n          children: \"200\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token method function property-access\",\n          children: \"json\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), \"data\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword control-flow\",\n          children: \"else\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \"\\n        res\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token method function property-access\",\n          children: \"status\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token number\",\n          children: \"404\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n        res\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token method function property-access\",\n          children: \"end\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), \"\\n\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), \"\\n\\n\", _jsx(_components.span, {\n          className: \"token keyword module\",\n          children: \"export\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword module\",\n          children: \"default\"\n        }), \" post\\n\"]\n      })\n    }), \"\\n\", _jsx(_components.p, {\n      children: \"The above is very similar to our endpoint, only with some minor differences:\"\n    }), \"\\n\", _jsxs(_components.ul, {\n      children: [\"\\n\", _jsxs(_components.li, {\n        children: [\"\\n\", _jsxs(_components.p, {\n          children: [\"We filter our data to find a post that matches the \", _jsx(_components.code, {\n            children: \"slug\"\n          }), \" provided in the API url\"]\n        }), \"\\n\", _jsxs(_components.ul, {\n          children: [\"\\n\", _jsxs(_components.li, {\n            children: [\"A \", _jsx(_components.code, {\n              children: \"slug\"\n            }), \" is a unique piece of text that identifies our article. For example you can see the slug for this page in the URL \", _jsx(_components.code, {\n              children: \"how-to-create-an-api-from-markdown-files-with-next-js\"\n            })]\n          }), \"\\n\"]\n        }), \"\\n\"]\n      }), \"\\n\", _jsxs(_components.li, {\n        children: [\"\\n\", _jsx(_components.p, {\n          children: \"If we couldn't find a match in our data we return a 404 error, which we'll then handle when trying to display the page\"\n        }), \"\\n\"]\n      }), \"\\n\"]\n    }), \"\\n\", _jsxs(_components.p, {\n      children: [\"If you've done it right it'll look something like \", _jsx(_components.a, {\n        href: \"https://ironeko.com/api/posts/how-to-create-an-api-from-markdown-files-with-next-js\",\n        children: \"the endpoint we use here on Ironeko\"\n      }), \".\"]\n    }), \"\\n\", _jsx(_components.h2, {\n      children: \"Combining your new endpoints with Next.js' ISR to improve your build time\"\n    }), \"\\n\", _jsxs(_components.p, {\n      children: [\"If you've managed a static site before you'll no doubt have noticed how \", _jsx(_components.strong, {\n        children: \"each time a new piece of content is added your builds take a little bit longer\"\n      }), \". This blog has just over 100 articles, and the build time has slowly crawled to around 3 minutes... Every. Time. I. Edit. Something.\"]\n    }), \"\\n\", _jsxs(_components.p, {\n      children: [\"Y﻿ou may have heard of \", _jsx(_components.strong, {\n        children: \"Incremental Static Regeneration\"\n      }), \" before. (If not, Smashing Magazine published the fantastic \", _jsx(_components.a, {\n        href: \"https://www.smashingmagazine.com/2021/04/incremental-static-regeneration-nextjs/\",\n        children: \"A Complete Guide To Incremental Static Regeneration (ISR) With Next.js\"\n      }), \" which is an excellent explanation of the feature.)\"]\n    }), \"\\n\", _jsx(Notice, {\n      children: _jsx(_components.p, {\n        children: \"There's a lot of magic related to how Incremental Static Regeneration works, but it's a fantastic feature and you don't necessarily need to understand how it functions to use it to its full potential.\"\n      })\n    }), \"\\n\", _jsx(_components.p, {\n      children: \"The point of ISR is that rather than telling Next.js how many pages you want to generate at build time, you'll just have to tell it where to get the information to generate them. The pages will then be generated upon request.\"\n    }), \"\\n\", _jsxs(_components.p, {\n      children: [\"Thanks to your new endpoint you can replace your \", _jsx(_components.code, {\n        children: \"getStaticProps\"\n      }), \" and \", _jsx(_components.code, {\n        children: \"getStaticPaths\"\n      }), \" with a much simpler:\"]\n    }), \"\\n\", _jsx(_components.pre, {\n      className: \"language-javascript\",\n      children: _jsxs(_components.code, {\n        className: \"language-javascript\",\n        children: [_jsx(_components.span, {\n          className: \"token comment\",\n          children: \"// pages/posts/[slug].js\"\n        }), \"\\n\\n\", _jsx(_components.span, {\n          className: \"token comment\",\n          children: \"// You'll need to specify the absolute URL to fetch your file\"\n        }), \"\\n\", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" url \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsxs(_components.span, {\n          className: \"token template-string\",\n          children: [_jsx(_components.span, {\n            className: \"token template-punctuation string\",\n            children: \"`\"\n          }), _jsx(_components.span, {\n            className: \"token string\",\n            children: \"http://example.com\"\n          }), _jsx(_components.span, {\n            className: \"token template-punctuation string\",\n            children: \"`\"\n          })]\n        }), \"\\n\\n\", _jsx(_components.span, {\n          className: \"token keyword module\",\n          children: \"export\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token function-variable function\",\n          children: \"getStaticPaths\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"async\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token arrow operator\",\n          children: \"=>\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token keyword control-flow\",\n          children: \"return\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \"\\n        \", _jsx(_components.span, {\n          className: \"token literal-property property\",\n          children: \"paths\"\n        }), _jsx(_components.span, {\n          className: \"token operator\",\n          children: \":\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"[\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"]\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \",\"\n        }), \"\\n        \", _jsx(_components.span, {\n          className: \"token literal-property property\",\n          children: \"fallback\"\n        }), _jsx(_components.span, {\n          className: \"token operator\",\n          children: \":\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token string\",\n          children: \"'blocking'\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \",\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), \"\\n\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), \"\\n\\n\", _jsx(_components.span, {\n          className: \"token keyword module\",\n          children: \"export\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token function-variable function\",\n          children: \"getStaticProps\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"async\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsxs(_components.span, {\n          className: \"token parameter\",\n          children: [_jsx(_components.span, {\n            className: \"token punctuation\",\n            children: \"{\"\n          }), \" params \", _jsx(_components.span, {\n            className: \"token punctuation\",\n            children: \"}\"\n          })]\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token arrow operator\",\n          children: \"=>\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \" slug \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" params\\n\\n    \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" post \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token keyword control-flow\",\n          children: \"await\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token function\",\n          children: \"fetch\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsxs(_components.span, {\n          className: \"token template-string\",\n          children: [_jsx(_components.span, {\n            className: \"token template-punctuation string\",\n            children: \"`\"\n          }), _jsxs(_components.span, {\n            className: \"token interpolation\",\n            children: [_jsx(_components.span, {\n              className: \"token interpolation-punctuation punctuation\",\n              children: \"${\"\n            }), \"url\", _jsx(_components.span, {\n              className: \"token interpolation-punctuation punctuation\",\n              children: \"}\"\n            })]\n          }), _jsx(_components.span, {\n            className: \"token string\",\n            children: \"/api/posts/\"\n          }), _jsxs(_components.span, {\n            className: \"token interpolation\",\n            children: [_jsx(_components.span, {\n              className: \"token interpolation-punctuation punctuation\",\n              children: \"${\"\n            }), \"slug\", _jsx(_components.span, {\n              className: \"token interpolation-punctuation punctuation\",\n              children: \"}\"\n            })]\n          }), _jsx(_components.span, {\n            className: \"token template-punctuation string\",\n            children: \"`\"\n          })]\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n        \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token method function property-access\",\n          children: \"then\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token parameter\",\n          children: \"res\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token arrow operator\",\n          children: \"=>\"\n        }), \" res\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token method function property-access\",\n          children: \"json\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n        \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token keyword control-flow\",\n          children: \"catch\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token arrow operator\",\n          children: \"=>\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword null nil\",\n          children: \"null\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n\\n    \", _jsx(_components.span, {\n          className: \"token keyword control-flow\",\n          children: \"if\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"!\"\n        }), \"post\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \"\\n        \", _jsx(_components.span, {\n          className: \"token keyword control-flow\",\n          children: \"return\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \"\\n            \", _jsx(_components.span, {\n          className: \"token literal-property property\",\n          children: \"notFound\"\n        }), _jsx(_components.span, {\n          className: \"token operator\",\n          children: \":\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token boolean\",\n          children: \"true\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \",\"\n        }), \"\\n        \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), \"\\n\\n    \", _jsx(_components.span, {\n          className: \"token keyword control-flow\",\n          children: \"return\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \"\\n        \", _jsx(_components.span, {\n          className: \"token literal-property property\",\n          children: \"props\"\n        }), _jsx(_components.span, {\n          className: \"token operator\",\n          children: \":\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \"\\n            post\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \",\"\n        }), \"\\n        \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \",\"\n        }), \"\\n        \", _jsx(_components.span, {\n          className: \"token literal-property property\",\n          children: \"revalidate\"\n        }), _jsx(_components.span, {\n          className: \"token operator\",\n          children: \":\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token number\",\n          children: \"60\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \",\"\n        }), \"\\n    \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), \"\\n\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), \"\\n\"]\n      })\n    }), \"\\n\", _jsx(_components.p, {\n      children: \"You should see your build time cut down exponentially depending on how much content you have!\"\n    }), \"\\n\", _jsx(_components.h2, {\n      children: \"Bonus: Serialize your markdown (or mdx) on build\"\n    }), \"\\n\", _jsx(_components.p, {\n      children: \"Ideally with these changes you'll want to keep your serverless function execution time as short as possible (especially if you're on a Vercel Hobby plan). So there's a couple more corners you can cut.\"\n    }), \"\\n\", _jsxs(_components.p, {\n      children: [\"If you're using markdown or mdx you can actually serialize your markdown into a usable string outside of your \", _jsx(_components.code, {\n        children: \"getStaticProps\"\n      }), \". When generating your caches, rather than adding your markdown to your cache you can convert it directly to HTML or JSX so you won't have to convert it later while generating your page!\"]\n    }), \"\\n\", _jsx(_components.pre, {\n      className: \"language-javascript\",\n      children: _jsxs(_components.code, {\n        className: \"language-javascript\",\n        children: [_jsx(_components.span, {\n          className: \"token comment\",\n          children: \"// use this wherever you transform your markdown into JSON\"\n        }), \"\\n\\n\", _jsx(_components.span, {\n          className: \"token keyword module\",\n          children: \"import\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token imports\",\n          children: \"matter\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword module\",\n          children: \"from\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token string\",\n          children: \"'gray-matter'\"\n        }), \"\\n\", _jsx(_components.span, {\n          className: \"token keyword module\",\n          children: \"import\"\n        }), \" \", _jsxs(_components.span, {\n          className: \"token imports\",\n          children: [_jsx(_components.span, {\n            className: \"token punctuation\",\n            children: \"{\"\n          }), \" serialize \", _jsx(_components.span, {\n            className: \"token punctuation\",\n            children: \"}\"\n          })]\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword module\",\n          children: \"from\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token string\",\n          children: \"'next-mdx-remote/serialize'\"\n        }), \"\\n\", _jsx(_components.span, {\n          className: \"token keyword module\",\n          children: \"import\"\n        }), \" \", _jsxs(_components.span, {\n          className: \"token imports\",\n          children: [_jsx(_components.span, {\n            className: \"token punctuation\",\n            children: \"{\"\n          }), \" remark \", _jsx(_components.span, {\n            className: \"token punctuation\",\n            children: \"}\"\n          })]\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword module\",\n          children: \"from\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token string\",\n          children: \"'remark'\"\n        }), \"\\n\", _jsx(_components.span, {\n          className: \"token keyword module\",\n          children: \"import\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token imports\",\n          children: \"html\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword module\",\n          children: \"from\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token string\",\n          children: \"'remark-html'\"\n        }), \"\\n\\n\", _jsx(_components.span, {\n          className: \"token doc-comment comment\",\n          children: \"/**\\n * Convert a markdown file to JSON\\n */\"\n        }), \"\\n\", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token function-variable function\",\n          children: \"serializeMarkdown\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"async\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token parameter\",\n          children: \"markdownFile\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token arrow operator\",\n          children: \"=>\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \"\\n  \", _jsx(_components.span, {\n          className: \"token comment\",\n          children: \"// we extract the front-matter info from our markdown\"\n        }), \"\\n  \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" matterResult \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token function\",\n          children: \"matter\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), \"markdownFile\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n  \\n  \", _jsx(_components.span, {\n          className: \"token comment\",\n          children: \"// convert the markdown body into HTML\"\n        }), \"\\n  \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" html \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token function\",\n          children: \"remark\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token method function property-access\",\n          children: \"use\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), \"html\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token method function property-access\",\n          children: \"processSync\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), \"matterResult\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token property-access\",\n          children: \"content\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n  \\n  \", _jsx(_components.span, {\n          className: \"token comment\",\n          children: \"// or generate a JSX string from your MDX!\"\n        }), \"\\n  \", _jsx(_components.span, {\n          className: \"token keyword\",\n          children: \"const\"\n        }), \" mdx \", _jsx(_components.span, {\n          className: \"token operator\",\n          children: \"=\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token keyword control-flow\",\n          children: \"await\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token function\",\n          children: \"serialize\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"(\"\n        }), \"matterResult\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \".\"\n        }), _jsx(_components.span, {\n          className: \"token property-access\",\n          children: \"content\"\n        }), _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \")\"\n        }), \"\\n\\n  \", _jsx(_components.span, {\n          className: \"token keyword control-flow\",\n          children: \"return\"\n        }), \" \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"{\"\n        }), \"\\n      html\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \",\"\n        }), \"\\n      mdx\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \",\"\n        }), \"\\n      \", _jsx(_components.span, {\n          className: \"token spread operator\",\n          children: \"...\"\n        }), \"matterResult\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \",\"\n        }), \"\\n  \", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), \"\\n\", _jsx(_components.span, {\n          className: \"token punctuation\",\n          children: \"}\"\n        }), \"\\n\"]\n      })\n    }), \"\\n\", _jsx(_components.p, {\n      children: \"With these small changes Ironeko's build time dropped to around 40 seconds. This has improved my quality of life considerably, so you should definitely give it a try if you're falling out of love with static generation.\"\n    })]\n  });\n}\nfunction MDXContent(props = {}) {\n  const {wrapper: MDXLayout} = Object.assign({}, _provideComponents(), props.components);\n  return MDXLayout ? _jsx(MDXLayout, Object.assign({}, props, {\n    children: _jsx(_createMdxContent, props)\n  })) : _createMdxContent(props);\n}\nreturn {\n  default: MDXContent\n};\nfunction _missingMdxReference(id, component) {\n  throw new Error(\"Expected \" + (component ? \"component\" : \"object\") + \" `\" + id + \"` to be defined: you likely forgot to import, pass, or provide it.\");\n}\n","frontmatter":{},"scope":{}}}