29 lines
144 KiB
HTML
29 lines
144 KiB
HTML
<!DOCTYPE html><html lang="en-us" class="__variable_dd5b2f scroll-smooth"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" href="/_next/static/media/36966cca54120369-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="stylesheet" href="/_next/static/css/51ff4ab09cd9a322.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/css/ec75326fdf363785.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/css/7abc17aba6a0edf4.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-af24fb31267d6e11.js"/><script src="/_next/static/chunks/4bd1b696-5100ffb4d6775e5e.js" async=""></script><script src="/_next/static/chunks/684-c6a4ac930a941d3c.js" async=""></script><script src="/_next/static/chunks/main-app-8e08feffda26a933.js" async=""></script><script src="/_next/static/chunks/c16f53c3-5b47b7f1ae12d8f6.js" async=""></script><script src="/_next/static/chunks/874-7cca39d2e0ddd8b8.js" async=""></script><script src="/_next/static/chunks/430-f83175351bcd3192.js" async=""></script><script src="/_next/static/chunks/app/layout-6cdc32e6ffe9019a.js" async=""></script><script src="/_next/static/chunks/63-ef4ffe428c84fbc3.js" async=""></script><script src="/_next/static/chunks/app/blog/%5B...slug%5D/page-55fdf120c49a8b1e.js" async=""></script><link rel="preload" href="https://analytics.umami.is/script.js" as="script"/><meta name="next-size-adjust" content=""/><link rel="apple-touch-icon" sizes="76x76" href="/static/favicons/apple-touch-icon.png"/><link rel="icon" type="image/png" sizes="32x32" href="/static/favicons/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="16x16" href="/static/favicons/favicon-16x16.png"/><link rel="manifest" href="/static/favicons/site.webmanifest"/><link rel="mask-icon" href="/static/favicons/safari-pinned-tab.svg" color="#5bbad5"/><meta name="msapplication-TileColor" content="#000000"/><meta name="theme-color" media="(prefers-color-scheme: light)" content="#fff"/><meta name="theme-color" media="(prefers-color-scheme: dark)" content="#000"/><link rel="alternate" type="application/rss+xml" href="/feed.xml"/><title>Release of Tailwind Nextjs Starter Blog v2.0 | Next.js Starter Blog</title><meta name="description" content="Release of Tailwind Nextjs Starter Blog template v2.0, refactored with Nextjs App directory and React Server Components setup.Discover the new features and how to migrate from V1."/><meta name="robots" content="index, follow"/><meta name="googlebot" content="index, follow, max-video-preview:-1, max-image-preview:large, max-snippet:-1"/><link rel="canonical" href="https://tailwind-nextjs-starter-blog.vercel.app/blog/release-of-tailwind-nextjs-starter-blog-v2.0"/><link rel="alternate" type="application/rss+xml" href="https://tailwind-nextjs-starter-blog.vercel.app/feed.xml"/><meta property="og:title" content="Release of Tailwind Nextjs Starter Blog v2.0"/><meta property="og:description" content="Release of Tailwind Nextjs Starter Blog template v2.0, refactored with Nextjs App directory and React Server Components setup.Discover the new features and how to migrate from V1."/><meta property="og:url" content="https://tailwind-nextjs-starter-blog.vercel.app/blog/release-of-tailwind-nextjs-starter-blog-v2.0"/><meta property="og:site_name" content="Next.js Starter Blog"/><meta property="og:locale" content="en_US"/><meta property="og:image" content="https://tailwind-nextjs-starter-blog.vercel.app/static/images/twitter-card.png"/><meta property="og:type" content="article"/><meta property="article:published_time" content="2023-08-05T00:00:00.000Z"/><meta property="article:modified_time" content="2023-08-05T00:00:00.000Z"/><meta property="article:author" content="Tails Azimuth"/><meta name="twitter:card" content="summary_large_image"/><meta name="twitter:title" content="Release of Tailwind Nextjs Starter Blog v2.0"/><meta name="twitter:description" content="Release of Tailwind Nextjs Starter Blog template v2.0, refactored with Nextjs App directory and React Server Components setup.Discover the new features and how to migrate from V1."/><meta name="twitter:image" content="https://tailwind-nextjs-starter-blog.vercel.app/static/images/twitter-card.png"/><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body class="bg-white pl-[calc(100vw-100%)] text-black antialiased dark:bg-gray-950 dark:text-white"><script>((e,t,r,n,o,i,a,l)=>{let u=document.documentElement,s=["light","dark"];function c(t){var r;(Array.isArray(e)?e:[e]).forEach(e=>{let r="class"===e,n=r&&i?o.map(e=>i[e]||e):o;r?(u.classList.remove(...n),u.classList.add(i&&i[t]?i[t]:t)):u.setAttribute(e,t)}),r=t,l&&s.includes(r)&&(u.style.colorScheme=r)}if(n)c(n);else try{let e=localStorage.getItem(t)||r,n=a&&"system"===e?window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":e;c(n)}catch(e){}})("class","theme","system",null,["light","dark"],null,true,true)</script><section class="mx-auto max-w-3xl px-4 sm:px-6 xl:max-w-5xl xl:px-0"><header class="flex items-center w-full bg-white dark:bg-gray-950 justify-between py-10"><a class="break-words" aria-label="TailwindBlog" href="/"><div class="flex items-center justify-between"><div class="mr-3"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="53.87" height="43.61" viewBox="344.564 330.278 111.737 91.218"><defs><linearGradient id="logo_svg__b" x1="420.97" x2="420.97" y1="331.28" y2="418.5" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#06b6d4;stop-opacity:1"></stop><stop offset="100%" style="stop-color:#67e8f9;stop-opacity:1"></stop></linearGradient><linearGradient id="logo_svg__d" x1="377.89" x2="377.89" y1="331.28" y2="418.5" gradientUnits="userSpaceOnUse"><stop offset="0%" style="stop-color:#06b6d4;stop-opacity:1"></stop><stop offset="100%" style="stop-color:#67e8f9;stop-opacity:1"></stop></linearGradient><path id="logo_svg__a" d="M453.3 331.28v28.57l-64.66 58.65v-30.08z"></path><path id="logo_svg__c" d="M410.23 331.28v28.57l-64.67 58.65v-30.08z"></path></defs><use xlink:href="#logo_svg__a" fill="url(#logo_svg__b)"></use><use xlink:href="#logo_svg__c" fill="url(#logo_svg__d)"></use></svg></div><div class="hidden h-6 text-2xl font-semibold sm:block">TailwindBlog</div></div></a><div class="flex items-center space-x-4 leading-5 sm:-mr-6 sm:space-x-6"><div class="no-scrollbar hidden max-w-40 items-center gap-x-4 overflow-x-auto sm:flex md:max-w-72 lg:max-w-96"><a class="hover:text-primary-500 dark:hover:text-primary-400 m-1 font-medium text-gray-900 dark:text-gray-100" href="/blog">Blog</a><a class="hover:text-primary-500 dark:hover:text-primary-400 m-1 font-medium text-gray-900 dark:text-gray-100" href="/tags">Tags</a><a class="hover:text-primary-500 dark:hover:text-primary-400 m-1 font-medium text-gray-900 dark:text-gray-100" href="/projects">Projects</a><a class="hover:text-primary-500 dark:hover:text-primary-400 m-1 font-medium text-gray-900 dark:text-gray-100" href="/about">About</a></div><button aria-label="Search"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="hover:text-primary-500 dark:hover:text-primary-400 h-6 w-6 text-gray-900 dark:text-gray-100"><path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z"></path></svg></button><div class="flex items-center"><div class="relative inline-block text-left" data-headlessui-state=""><div class="hover:text-primary-500 dark:hover:text-primary-400 flex items-center justify-center"><button aria-label="Theme switcher" id="headlessui-menu-button-«Rtpkqlb»" type="button" aria-haspopup="menu" aria-expanded="false" data-headlessui-state=""><svg class="h-6 w-6"></svg></button></div></div></div><button aria-label="Toggle Menu" class="sm:hidden"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="hover:text-primary-500 dark:hover:text-primary-400 h-8 w-8 text-gray-900 dark:text-gray-100"><path fill-rule="evenodd" d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 10a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zM3 15a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z" clip-rule="evenodd"></path></svg></button><span hidden="" style="position:fixed;top:1px;left:1px;width:1px;height:0;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border-width:0;display:none"></span></div></header><main class="mb-auto"><script type="application/ld+json">{"@context":"https://schema.org","@type":"BlogPosting","headline":"Release of Tailwind Nextjs Starter Blog v2.0","datePublished":"2023-08-05T00:00:00.000Z","dateModified":"2023-08-05T00:00:00.000Z","description":"Release of Tailwind Nextjs Starter Blog template v2.0, refactored with Nextjs App directory and React Server Components setup.Discover the new features and how to migrate from V1.","image":"/static/images/twitter-card.png","url":"https://tailwind-nextjs-starter-blog.vercel.app/blog/release-of-tailwind-nextjs-starter-blog-v2.0","author":[{"@type":"Person","name":"Tails Azimuth"}]}</script><section class="mx-auto max-w-3xl px-4 sm:px-6 xl:max-w-5xl xl:px-0"><div class="fixed right-8 bottom-8 hidden flex-col gap-3 md:hidden"><button aria-label="Scroll To Comment" class="rounded-full bg-gray-200 p-2 text-gray-500 transition-all hover:bg-gray-300 dark:bg-gray-700 dark:text-gray-400 dark:hover:bg-gray-600"><svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M18 10c0 3.866-3.582 7-8 7a8.841 8.841 0 01-4.083-.98L2 17l1.338-3.123C2.493 12.767 2 11.434 2 10c0-3.866 3.582-7 8-7s8 3.134 8 7zM7 9H5v2h2V9zm8 0h-2v2h2V9zM9 9h2v2H9V9z" clip-rule="evenodd"></path></svg></button><button aria-label="Scroll To Top" class="rounded-full bg-gray-200 p-2 text-gray-500 transition-all hover:bg-gray-300 dark:bg-gray-700 dark:text-gray-400 dark:hover:bg-gray-600"><svg class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M3.293 9.707a1 1 0 010-1.414l6-6a1 1 0 011.414 0l6 6a1 1 0 01-1.414 1.414L11 5.414V17a1 1 0 11-2 0V5.414L4.707 9.707a1 1 0 01-1.414 0z" clip-rule="evenodd"></path></svg></button></div><article><div class="xl:divide-y xl:divide-gray-200 xl:dark:divide-gray-700"><header class="pt-6 xl:pb-6"><div class="space-y-1 text-center"><dl class="space-y-10"><div><dt class="sr-only">Published on</dt><dd class="text-base leading-6 font-medium text-gray-500 dark:text-gray-400"><time dateTime="2023-08-05T00:00:00.000Z">Saturday, August 5, 2023</time></dd></div></dl><div><h1 class="text-3xl leading-9 font-extrabold tracking-tight text-gray-900 sm:text-4xl sm:leading-10 md:text-5xl md:leading-14 dark:text-gray-100">Release of Tailwind Nextjs Starter Blog v2.0</h1></div></div></header><div class="grid-rows-[auto_1fr] divide-y divide-gray-200 pb-8 xl:grid xl:grid-cols-4 xl:gap-x-6 xl:divide-y-0 dark:divide-gray-700"><dl class="pt-6 pb-10 xl:border-b xl:border-gray-200 xl:pt-11 xl:dark:border-gray-700"><dt class="sr-only">Authors</dt><dd><ul class="flex flex-wrap justify-center gap-4 sm:space-x-12 xl:block xl:space-y-8 xl:space-x-0"><li class="flex items-center space-x-2"><img alt="avatar" loading="lazy" width="38" height="38" decoding="async" data-nimg="1" class="h-10 w-10 rounded-full" style="color:transparent" srcSet="/_next/image?url=%2Fstatic%2Fimages%2Favatar.png&w=48&q=75 1x, /_next/image?url=%2Fstatic%2Fimages%2Favatar.png&w=96&q=75 2x" src="/_next/image?url=%2Fstatic%2Fimages%2Favatar.png&w=96&q=75"/><dl class="text-sm leading-5 font-medium whitespace-nowrap"><dt class="sr-only">Name</dt><dd class="text-gray-900 dark:text-gray-100">Tails Azimuth</dd><dt class="sr-only">Twitter</dt><dd><a class="text-primary-500 hover:text-primary-600 dark:hover:text-primary-400" target="_blank" rel="noopener noreferrer" href="https://twitter.com/Twitter">@Twitter</a></dd></dl></li></ul></dd></dl><div class="divide-y divide-gray-200 xl:col-span-3 xl:row-span-2 xl:pb-0 dark:divide-gray-700"><div class="prose dark:prose-invert max-w-none pt-10 pb-8"><h2 class="content-header" id="introduction"><a class="break-words" href="#introduction" aria-hidden="true" tabindex="-1"><span class="content-header-link"><svg class="h-5 linkicon w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"></path><path d="M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"></path></svg></span></a>Introduction</h2><p>Welcome to the release of Tailwind Nextjs Starter Blog template v2.0. This release is a major refactor of the codebase to support Nextjs App directory and React Server Components. Read on to discover the new features and how to migrate from V1.</p><ul class=""><li class=""><a href="#v1-to-v2">V1 to V2</a></li><li class=""><a href="#nextjs-app-directory-and-react-server-components">Next.js App Directory and React Server Components</a></li><li class=""><a href="#typescript-first">Typescript First</a></li><li class=""><a href="#contentlayer">Contentlayer</a></li><li class=""><a href="#pliny">Pliny</a></li><li class=""><a href="#new-search-component">New Search Component</a><ul class=""><li class=""><a href="#algolia">Algolia</a></li><li class=""><a href="#kbar">Kbar</a></li></ul></li><li class=""><a href="#styling-and-layout-updates">Styling and Layout Updates</a><ul class=""><li class=""><a href="#theming">Theming</a></li><li class=""><a href="#new-layouts">New Layouts</a></li></ul></li><li class=""><a href="#migration-recommendations">Migration Recommendations</a></li><li class=""><a href="#conclusion">Conclusion</a></li><li class=""><a href="#support">Support</a></li><li class=""><a href="#licence">Licence</a></li></ul><h2 class="content-header" id="v1-to-v2"><a class="break-words" href="#v1-to-v2" aria-hidden="true" tabindex="-1"><span class="content-header-link"><svg class="h-5 linkicon w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"></path><path d="M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"></path></svg></span></a>V1 to V2</h2><div><img alt="Github Traffic" loading="lazy" width="920" height="420" decoding="async" data-nimg="1" style="color:transparent" srcSet="/_next/image?url=%2Fstatic%2Fimages%2Fgithub-traffic.png&w=1080&q=75 1x, /_next/image?url=%2Fstatic%2Fimages%2Fgithub-traffic.png&w=1920&q=75 2x" src="/_next/image?url=%2Fstatic%2Fimages%2Fgithub-traffic.png&w=1920&q=75"/></div><p>The template was first released in January 2021 and has since been used by thousands of users. It is featured on <a class="break-words" target="_blank" rel="noopener noreferrer" href="https://vercel.com/templates/next.js/tailwind-css-starter-blog">Next.js Templates</a>, <a class="break-words" target="_blank" rel="noopener noreferrer" href="https://www.tailwindawesome.com/resources/tailwind-nextjs-starter-blog">Tailwind Awesome</a> among other listing sites. It attracts 200+ unique visitors daily notching 1500-2000 page views, with 1.3k forks and many other clones.</p><p>Many thanks to the community of users and contributors for making this template a success! I created a small video montage of the blogs (while cleaning up the list in the readme) to showcase the diversity of the blogs created using the template and to celebrate the milestone:</p><video controls=""><source src="https://github-production-user-asset-6210df.s3.amazonaws.com/28362229/258559849-2124c81f-b99d-4431-839c-347e01a2616c.webm" type="video/webm"/></video><p>Version 2 builds on the success of the previous version and introduces many new features and improvements. The codebase has been refactored to support Next.js App directory and React Server Components. Markdown / MDX is now processed using Contentlayer, a type-safe content SDK that validates and transforms your content into type-safe JSON data. It integrates with Pliny, a new library that provides out of the box Next.js components to enhance your static site with analytics, comments and newsletter subscription. A new command palette (⌘-k) search component is also added to the template.</p><p>Let's dive into the new features and improvements in V2.</p><h2 class="content-header" id="nextjs-app-directory-and-react-server-components"><a class="break-words" href="#nextjs-app-directory-and-react-server-components" aria-hidden="true" tabindex="-1"><span class="content-header-link"><svg class="h-5 linkicon w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"></path><path d="M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"></path></svg></span></a>Next.js App Directory and React Server Components</h2><p>Now that <a class="break-words" target="_blank" rel="noopener noreferrer" href="https://nextjs.org/docs/app">Next.js App router</a> is finally stable and is mostly feature compatible with Page Router, the codebase has been migrated to new setup. This allows for a hybrid rendering approach, with the use of React Server Components generated on the server side for faster page loads and smaller bundle sizes, while retaining the ability to sprinkle in client side React components for interactivity.<sup><a class="break-words" href="#user-content-fn-1" aria-describedby="footnote-label" data-footnote-ref="true" id="user-content-fnref-1">1</a></sup></p><p>With addition powers comes a <a class="break-words" target="_blank" rel="noopener noreferrer" href="https://nextjs.org/docs/getting-started/react-essentials">new paradigm</a> to learn. I have migrated the codebase to make use of the new features as much as possible. This includes changes in the folder structure, splitting components into server vs client components, leveraging server side data fetching and using the recommended <a class="break-words" target="_blank" rel="noopener noreferrer" href="https://nextjs.org/docs/app/building-your-application/optimizing/metadata">Metadata</a> API for SEO discoverability.</p><p>While this simplifies the codebase to some extent, it makes migration from the old codebase more difficult. If you are looking to migrate, I recommend starting from a fresh template and copying over your customizations and existing content. See the <a class="break-words" href="#migration-recommendations">migration recommendations</a> section for more details.</p><h2 class="content-header" id="typescript-first"><a class="break-words" href="#typescript-first" aria-hidden="true" tabindex="-1"><span class="content-header-link"><svg class="h-5 linkicon w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"></path><path d="M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"></path></svg></span></a>Typescript First</h2><p>The codebase has been migrated to Typescript. While the previous version of the template was available in both Javascript and Typescript, I decided to reduce the maintenance burden and focus on Typescript. This also allows for better type checking and code completion in IDEs.</p><p>Typescript is also a perfect match with our new type-safe markdown processor - Contentlayer.</p><h2 class="content-header" id="contentlayer"><a class="break-words" href="#contentlayer" aria-hidden="true" tabindex="-1"><span class="content-header-link"><svg class="h-5 linkicon w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"></path><path d="M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"></path></svg></span></a>Contentlayer</h2><p><a class="break-words" target="_blank" rel="noopener noreferrer" href="https://www.contentlayer.dev/">Contentlayer</a> is a content SDK that validates and transforms your content into type-safe JSON data that you can easily import into your application. It makes working with local markdown or MDX files a breeze. This replaces <code>MDX-bundler</code> and our own markdown processing workflow.</p><p>First, a content source is defined, specifying the name of the document type, the source where it is located along with the frontmatter fields and any additional computed fields that should be generated as part of the process.</p><div class="remark-code-title">contentlayer.config.ts</div><div class="relative"><pre><code class="code-highlight language-ts"><span class="code-line"><span class="token keyword">export</span> <span class="token keyword">const</span> Blog <span class="token operator">=</span> <span class="token function">defineDocumentType</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">(</span><span class="token punctuation">{</span>
|
|
</span><span class="code-line"> name<span class="token operator">:</span> <span class="token string">'Blog'</span><span class="token punctuation">,</span>
|
|
</span><span class="code-line"> filePathPattern<span class="token operator">:</span> <span class="token string">'blog/**/*.mdx'</span><span class="token punctuation">,</span>
|
|
</span><span class="code-line"> contentType<span class="token operator">:</span> <span class="token string">'mdx'</span><span class="token punctuation">,</span>
|
|
</span><span class="code-line"> fields<span class="token operator">:</span> <span class="token punctuation">{</span>
|
|
</span><span class="code-line"> title<span class="token operator">:</span> <span class="token punctuation">{</span> type<span class="token operator">:</span> <span class="token string">'string'</span><span class="token punctuation">,</span> required<span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
|
|
</span><span class="code-line"> date<span class="token operator">:</span> <span class="token punctuation">{</span> type<span class="token operator">:</span> <span class="token string">'date'</span><span class="token punctuation">,</span> required<span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
|
|
</span><span class="code-line"> tags<span class="token operator">:</span> <span class="token punctuation">{</span> type<span class="token operator">:</span> <span class="token string">'list'</span><span class="token punctuation">,</span> <span class="token keyword">of</span><span class="token operator">:</span> <span class="token punctuation">{</span> type<span class="token operator">:</span> <span class="token string">'string'</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token keyword">default</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
|
|
</span><span class="code-line"> <span class="token operator">...</span>
|
|
</span><span class="code-line"> <span class="token punctuation">}</span><span class="token punctuation">,</span>
|
|
</span><span class="code-line"> computedFields<span class="token operator">:</span> <span class="token punctuation">{</span>
|
|
</span><span class="code-line"> readingTime<span class="token operator">:</span> <span class="token punctuation">{</span> type<span class="token operator">:</span> <span class="token string">'json'</span><span class="token punctuation">,</span> <span class="token function function-variable">resolve</span><span class="token operator">:</span> <span class="token punctuation">(</span>doc<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function">readingTime</span><span class="token punctuation">(</span>doc<span class="token punctuation">.</span>body<span class="token punctuation">.</span>raw<span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
|
|
</span><span class="code-line"> slug<span class="token operator">:</span> <span class="token punctuation">{</span>
|
|
</span><span class="code-line"> type<span class="token operator">:</span> <span class="token string">'string'</span><span class="token punctuation">,</span>
|
|
</span><span class="code-line"> <span class="token function function-variable">resolve</span><span class="token operator">:</span> <span class="token punctuation">(</span>doc<span class="token punctuation">)</span> <span class="token operator">=></span> doc<span class="token punctuation">.</span>_raw<span class="token punctuation">.</span>flattenedPath<span class="token punctuation">.</span><span class="token function">replace</span><span class="token punctuation">(</span><span class="token regex"><span class="token regex-delimiter">/</span><span class="token language-regex regex-source"><span class="token function anchor">^</span><span class="token char-set class-name">.</span><span class="token number quantifier">+?</span><span class="token punctuation group">(</span><span class="token escape">\/</span><span class="token punctuation group">)</span></span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
|
|
</span><span class="code-line"> <span class="token punctuation">}</span>
|
|
</span><span class="code-line"> <span class="token operator">...</span>
|
|
</span><span class="code-line"> <span class="token punctuation">}</span><span class="token punctuation">,</span>
|
|
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
|
|
</span></code></pre></div><p>Contentlayer then processes the MDX files with our desired markdown remark or rehype plugins, validates the schema, generate type definitions and output json files that can be easily imported in our pages. Hot reloading comes out of the box, so edits to the markdown files will be reflected in the browser immediately!</p><h2 class="content-header" id="pliny"><a class="break-words" href="#pliny" aria-hidden="true" tabindex="-1"><span class="content-header-link"><svg class="h-5 linkicon w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"></path><path d="M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"></path></svg></span></a>Pliny</h2><p>A large reason for the popularity of the template was its customizability and integration with other services from analytics providers to commenting solutions. However, this means that a lot of boilerplate code has to be co-located within the template even if the user does not use the feature. Updates and bug fixes had to be copied manually to the user's codebase.</p><p>To solve this, I have abstracted the logic to a separate repository - <a class="break-words" target="_blank" rel="noopener noreferrer" href="https://github.com/timlrx/pliny">Pliny</a>. Pliny provides out of the box Next.js components to enhance static sites:</p><ul><li>Analytics<ul><li>Google Analytics</li><li>Plausible Analytics</li><li>Simple Analytics</li><li>Umami Analytics</li><li>Posthog</li></ul></li><li>Comments<ul><li>Disqus</li><li>Giscus</li><li>Utterances</li></ul></li><li>Newsletter (uses Next 13 API Routes)<ul><li>Buttondown</li><li>Convertkit</li><li>Email Octopus</li><li>Klaviyo</li><li>Mailchimp</li><li>Revue</li></ul></li><li>Command palette search with tailwind style sheet<ul><li>Algolia</li><li>Kbar (local search)</li></ul></li><li>UI utility components<ul><li>Bleed</li><li>Newsletter / Blog Newsletter</li><li>Pre / Code block</li><li>Table of Contents</li></ul></li></ul><p>Choose your preferred service by modifying <code>siteMetadata.js</code> and changing the appropriate fields. For example to change from Umami Analytics to Plausible, we can change the following fields:</p><div class="remark-code-title">siteMetadata.js</div><div class="relative"><pre><code class="code-highlight language-diff-js"><span class="code-line"><span class="token literal-property property">analytics</span><span class="token operator">:</span> <span class="token punctuation">{</span>
|
|
</span><span class="code-line deleted"><span class="token operator">-</span> umamiAnalytics<span class="token operator">:</span> <span class="token punctuation">{</span>
|
|
</span><span class="code-line deleted"><span class="token operator">-</span> <span class="token comment">// We use an env variable for this site to avoid other users cloning our analytics ID</span>
|
|
</span><span class="code-line deleted"><span class="token operator">-</span> umamiWebsiteId<span class="token operator">:</span> process<span class="token punctuation">.</span><span class="token property-access">env</span><span class="token punctuation">.</span><span class="token constant">NEXT_UMAMI_ID</span><span class="token punctuation">,</span> <span class="token comment">// e.g. 123e4567-e89b-12d3-a456-426614174000</span>
|
|
</span><span class="code-line deleted"><span class="token operator">-</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
|
|
</span><span class="code-line inserted"><span class="token operator">+</span> plausibleAnalytics<span class="token operator">:</span> <span class="token punctuation">{</span>
|
|
</span><span class="code-line inserted"><span class="token operator">+</span> plausibleDataDomain<span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">,</span> <span class="token comment">// e.g. tailwind-nextjs-starter-blog.vercel.app</span>
|
|
</span><span class="code-line inserted"><span class="token operator">+</span> <span class="token punctuation">}</span><span class="token punctuation">,</span>
|
|
</span><span class="code-line"><span class="token punctuation">}</span><span class="token punctuation">,</span>
|
|
</span></code></pre></div><p>Changes in the configuration file gets propagated to the components automatically. No modification to the template is required.</p><p>Under the hood, Pliny exports high level components such as <code><Analytics analyticsConfig={analyticsConfig}/></code> and <code><Comments commentsConfig={commentsConfig}/></code> which takes in a configuration object and renders the appropriate component. Since the layouts are defined on the server side, Next.js is able to use the configuration object to determine which component to render and send only the required component bundle to the client.</p><h2 class="content-header" id="new-search-component"><a class="break-words" href="#new-search-component" aria-hidden="true" tabindex="-1"><span class="content-header-link"><svg class="h-5 linkicon w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"></path><path d="M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"></path></svg></span></a>New Search Component</h2><p>What's a blog in 2023 without a command palette search bar?</p><p>One of the most highly requested features have been added 🎉! The search component supports 2 search providers - Algolia and Kbar local search.</p><h3 class="content-header" id="algolia"><a class="break-words" href="#algolia" aria-hidden="true" tabindex="-1"><span class="content-header-link"><svg class="h-5 linkicon w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"></path><path d="M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"></path></svg></span></a>Algolia</h3><p><a class="break-words" target="_blank" rel="noopener noreferrer" href="https://docsearch.algolia.com/">Algolia Docsearch</a> is popular free service used across many documentation websites. It automatically scrapes the website that has is submitted for indexing and makes the search result available via a beautiful dialog modal. The pliny component is greatly inspired by the Docusaurus implementation and comes with a stylesheet that is compatible with the Tailwind CSS theme.</p><h3 class="content-header" id="kbar"><a class="break-words" href="#kbar" aria-hidden="true" tabindex="-1"><span class="content-header-link"><svg class="h-5 linkicon w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"></path><path d="M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"></path></svg></span></a>Kbar</h3><p><a class="break-words" target="_blank" rel="noopener noreferrer" href="https://github.com/timc1/kbar">Kbar</a> is a fast, portable, and extensible cmd+k interface. The pliny implementation uses kbar to create a local search dialog box. The component loads a JSON file, default <code>search.json</code>, that was created in the contentlayer build process. Try pressing ⌘-k or ctrl-k to see the search bar in action!</p><h2 class="content-header" id="styling-and-layout-updates"><a class="break-words" href="#styling-and-layout-updates" aria-hidden="true" tabindex="-1"><span class="content-header-link"><svg class="h-5 linkicon w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"></path><path d="M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"></path></svg></span></a>Styling and Layout Updates</h2><h3 class="content-header" id="theming"><a class="break-words" href="#theming" aria-hidden="true" tabindex="-1"><span class="content-header-link"><svg class="h-5 linkicon w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"></path><path d="M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"></path></svg></span></a>Theming</h3><p><code>tailwind.config.js</code> has been updated to use tailwind typography defaults where possible and to use the built-in support for dark mode via the <code>prose-invert</code> class. This replaces the previous <code>prose-dark</code> class and configuration.</p><p>The primary theme color is updated from <code>teal</code> to <code>pink</code> and the primary gray theme from <code>neutral</code> to <code>gray</code>.</p><p>Inter is now replaced with Space Grotesk as the default font.</p><h3 class="content-header" id="new-layouts"><a class="break-words" href="#new-layouts" aria-hidden="true" tabindex="-1"><span class="content-header-link"><svg class="h-5 linkicon w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"></path><path d="M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"></path></svg></span></a>New Layouts</h3><p>Layout components available in the <code>layouts</code> directory, provide a simple way to customize the look and feel of the blog.<sup><a class="break-words" href="#user-content-fn-2" aria-describedby="footnote-label" data-footnote-ref="true" id="user-content-fnref-2">2</a></sup></p><p>The downside of building a popular template is that you start seeing multiple similar sites everywhere 😆. While users are encouraged to customized the layouts to their liking, having more layout options that are easily switchable promotes diversity and perhaps can be a good starting point for further customizations.</p><p>In v2, I added a new post layout - <code>PostBanner</code>. It features a large banner image and a centered content container. Check out "<a class="break-words" href="/blog/pictures-of-canada">Pictures of Canada</a>" blog post which has been updated to use the new layout.</p><p>The default blog listing layout has also been updated to include a side bar with blog tags. The search bar in the previous layout has been replace with the new command palette search. To switch back to the old layout, simply change the pages that use the <code>ListLayoutWithTags</code> component back to the original <code>ListLayout</code>.</p><h2 class="content-header" id="migration-recommendations"><a class="break-words" href="#migration-recommendations" aria-hidden="true" tabindex="-1"><span class="content-header-link"><svg class="h-5 linkicon w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"></path><path d="M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"></path></svg></span></a>Migration Recommendations</h2><p>Due to the large changes in directory structure, setup and tooling, I recommend starting from a fresh template and copying existing content, followed by incrementally migrating changes over to the new template.</p><p>Styling changes should be relatively minor and can be copied over from the old <code>tailwind.config.js</code> to the new one. If copying over, you might need to add back the <code>prose-dark</code> class to components that opt into tailwind typography styling. Do modify the font import in the root layout component to use the desired font of choice.</p><p>Changes to the MDX processing pipeline and schema can be easily ported to the new Contentlayer setup. If there are changes to the frontmatter fields, you can modify the document type in <code>contentlayer.config.ts</code> to include the new fields. Custom plugins can be added to the <code>remarkPlugins</code> and <code>rehypePlugins</code> properties in the <code>makeSource</code> export of <code>contentlayer.config.ts</code>.</p><p>Markdown layouts are no longer sourced automatically from the <code>layouts</code> directory. Instead, they have to be specified in the <code>layouts</code> object defined in <code>blog/[...slug]/page.tsx</code>.<sup><a class="break-words" href="#user-content-fn-3" aria-describedby="footnote-label" data-footnote-ref="true" id="user-content-fnref-3">3</a></sup></p><p>To port over larger components or pages, I recommend first specificing it as a client component by using the <code>"use client"</code> directive. Once it renders correctly, you can split the interactive components (parts that rely on <code>use</code> hooks) as a client component and keep the remaining code as a server component. Consult the comprehensive Next.js <a class="break-words" target="_blank" rel="noopener noreferrer" href="https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration#migrating-from-pages-to-app">migration guide</a> for more details.</p><h2 class="content-header" id="conclusion"><a class="break-words" href="#conclusion" aria-hidden="true" tabindex="-1"><span class="content-header-link"><svg class="h-5 linkicon w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"></path><path d="M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"></path></svg></span></a>Conclusion</h2><p>I hope you enjoy the new features and improvements in V2. If you have any feedback or suggestions, feel free to open an issue or reach out to me on <a class="break-words" target="_blank" rel="noopener noreferrer" href="https://twitter.com/timlrx">Twitter</a>.</p><h2 class="content-header" id="support"><a class="break-words" href="#support" aria-hidden="true" tabindex="-1"><span class="content-header-link"><svg class="h-5 linkicon w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"></path><path d="M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"></path></svg></span></a>Support</h2><p>Using the template? Support this effort by giving a star on GitHub, sharing your own blog and giving a shoutout on Twitter or be a project <a class="break-words" target="_blank" rel="noopener noreferrer" href="https://github.com/sponsors/timlrx">sponsor</a>.</p><h2 class="content-header" id="licence"><a class="break-words" href="#licence" aria-hidden="true" tabindex="-1"><span class="content-header-link"><svg class="h-5 linkicon w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"></path><path d="M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"></path></svg></span></a>Licence</h2><p><a class="break-words" target="_blank" rel="noopener noreferrer" href="https://github.com/timlrx/tailwind-nextjs-starter-blog/blob/main/LICENSE">MIT</a> © <a class="break-words" target="_blank" rel="noopener noreferrer" href="https://www.timrlx.com">Timothy Lin</a></p><section class="footnotes" data-footnotes="true"><h2 class="content-header" id="footnote-label"><a class="break-words" href="#footnote-label" aria-hidden="true" tabindex="-1"><span class="content-header-link"><svg class="h-5 linkicon w-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"></path><path d="M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"></path></svg></span></a>Footnotes</h2><ol><li id="user-content-fn-1"><p>The previous version injects Preact into the production build. However, this is no longer possible as it does not support React Server Components. While overall bundle size has increased to about 85kB, most of the content can be pre-rendered on the server side, resulting in a low first contentful paint and time to interactive. Using React throughtout also leads to more consistent behavior with external libraries and components. <a class="data-footnote-backref" href="#user-content-fnref-1" aria-label="Back to reference 1" data-footnote-backref="">↩</a></p></li><li id="user-content-fn-2"><p>This is different from Next.js App Directory layouts and are best thought of as reusable React containers. <a class="data-footnote-backref" href="#user-content-fnref-2" aria-label="Back to reference 2" data-footnote-backref="">↩</a></p></li><li id="user-content-fn-3"><p>This takes advantage of Server Components by making it simple to specify the layout of choice in the markdown file and match against the <code>layouts</code> object which is then used to render the appropriate layout component. <a class="data-footnote-backref" href="#user-content-fnref-3" aria-label="Back to reference 3" data-footnote-backref="">↩</a></p></li></ol></section></div><div class="pt-6 pb-6 text-sm text-gray-700 dark:text-gray-300"><a class="break-words" target="_blank" rel="nofollow" href="https://mobile.twitter.com/search?q=https%3A%2F%2Ftailwind-nextjs-starter-blog.vercel.app%2Fblog%2Frelease-of-tailwind-nextjs-starter-blog-v2.0">Discuss on Twitter</a> • <a class="break-words" target="_blank" rel="noopener noreferrer" href="https://github.com/timlrx/tailwind-nextjs-starter-blog/blob/main/data/blog/release-of-tailwind-nextjs-starter-blog-v2.0.mdx">View on GitHub</a></div><div class="pt-6 pb-6 text-center text-gray-700 dark:text-gray-300" id="comment"><button>Load Comments</button></div></div><footer><div class="divide-gray-200 text-sm leading-5 font-medium xl:col-start-1 xl:row-start-2 xl:divide-y dark:divide-gray-700"><div class="py-4 xl:py-8"><h2 class="text-xs tracking-wide text-gray-500 uppercase dark:text-gray-400">Tags</h2><div class="flex flex-wrap"><a class="text-primary-500 hover:text-primary-600 dark:hover:text-primary-400 mr-3 text-sm font-medium uppercase" href="/tags/next-js">next-js</a><a class="text-primary-500 hover:text-primary-600 dark:hover:text-primary-400 mr-3 text-sm font-medium uppercase" href="/tags/tailwind">tailwind</a><a class="text-primary-500 hover:text-primary-600 dark:hover:text-primary-400 mr-3 text-sm font-medium uppercase" href="/tags/guide">guide</a><a class="text-primary-500 hover:text-primary-600 dark:hover:text-primary-400 mr-3 text-sm font-medium uppercase" href="/tags/feature">feature</a></div></div><div class="flex justify-between py-4 xl:block xl:space-y-8 xl:py-8"><div><h2 class="text-xs tracking-wide text-gray-500 uppercase dark:text-gray-400">Previous Article</h2><div class="text-primary-500 hover:text-primary-600 dark:hover:text-primary-400"><a class="break-words" href="/blog/new-features-in-v1">New features in v1</a></div></div></div></div><div class="pt-4 xl:pt-8"><a class="text-primary-500 hover:text-primary-600 dark:hover:text-primary-400" aria-label="Back to the blog" href="/blog">← Back to the blog</a></div></footer></div></div></article></section></main><footer><div class="mt-16 flex flex-col items-center"><div class="mb-3 flex space-x-4"><a class="text-sm text-gray-500 transition hover:text-gray-600" target="_blank" rel="noopener noreferrer" href="mailto:address@yoursite.com"><span class="sr-only">mail</span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" class="hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6"><title>Mail</title><path d="M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z"></path><path d="M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z"></path></svg></a><a class="text-sm text-gray-500 transition hover:text-gray-600" target="_blank" rel="noopener noreferrer" href="https://github.com"><span class="sr-only">github</span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"></path></svg></a><a class="text-sm text-gray-500 transition hover:text-gray-600" target="_blank" rel="noopener noreferrer" href="https://facebook.com"><span class="sr-only">facebook</span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6"><title>Facebook</title><path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z"></path></svg></a><a class="text-sm text-gray-500 transition hover:text-gray-600" target="_blank" rel="noopener noreferrer" href="https://youtube.com"><span class="sr-only">youtube</span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6"><title>Youtube</title><path d="M23.499 6.203a3.008 3.008 0 00-2.089-2.089c-1.87-.501-9.4-.501-9.4-.501s-7.509-.01-9.399.501a3.008 3.008 0 00-2.088 2.09A31.258 31.26 0 000 12.01a31.258 31.26 0 00.523 5.785 3.008 3.008 0 002.088 2.089c1.869.502 9.4.502 9.4.502s7.508 0 9.399-.502a3.008 3.008 0 002.089-2.09 31.258 31.26 0 00.5-5.784 31.258 31.26 0 00-.5-5.808zm-13.891 9.4V8.407l6.266 3.604z"></path></svg></a><a class="text-sm text-gray-500 transition hover:text-gray-600" target="_blank" rel="noopener noreferrer" href="https://www.linkedin.com"><span class="sr-only">linkedin</span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6"><title>Linkedin</title><path d="M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z"></path></svg></a><a class="text-sm text-gray-500 transition hover:text-gray-600" target="_blank" rel="noopener noreferrer" href="https://bsky.app/"><span class="sr-only">bluesky</span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6"><title>Bluesky</title><path d="M12 10.8c-1.087-2.114-4.046-6.053-6.798-7.995C2.566.944 1.561 1.266.902 1.565C.139 1.908 0 3.08 0 3.768c0 .69.378 5.65.624 6.479c.815 2.736 3.713 3.66 6.383 3.364q.204-.03.415-.056q-.207.033-.415.056c-3.912.58-7.387 2.005-2.83 7.078c5.013 5.19 6.87-1.113 7.823-4.308c.953 3.195 2.05 9.271 7.733 4.308c4.267-4.308 1.172-6.498-2.74-7.078a9 9 0 0 1-.415-.056q.21.026.415.056c2.67.297 5.568-.628 6.383-3.364c.246-.828.624-5.79.624-6.478c0-.69-.139-1.861-.902-2.206c-.659-.298-1.664-.62-4.3 1.24C16.046 4.748 13.087 8.687 12 10.8"></path></svg></a><a class="text-sm text-gray-500 transition hover:text-gray-600" target="_blank" rel="noopener noreferrer" href="https://twitter.com/x"><span class="sr-only">x</span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6"><title>X</title><path d="M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z"></path></svg></a><a class="text-sm text-gray-500 transition hover:text-gray-600" target="_blank" rel="noopener noreferrer" href="https://www.instagram.com"><span class="sr-only">instagram</span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6"><title>Instagram</title><path d="M12 0C8.74 0 8.333.015 7.053.072 5.775.132 4.905.333 4.14.63c-.789.306-1.459.717-2.126 1.384S.935 3.35.63 4.14C.333 4.905.131 5.775.072 7.053.012 8.333 0 8.74 0 12s.015 3.667.072 4.947c.06 1.277.261 2.148.558 2.913.306.788.717 1.459 1.384 2.126.667.666 1.336 1.079 2.126 1.384.766.296 1.636.499 2.913.558C8.333 23.988 8.74 24 12 24s3.667-.015 4.947-.072c1.277-.06 2.148-.262 2.913-.558.788-.306 1.459-.718 2.126-1.384.666-.667 1.079-1.335 1.384-2.126.296-.765.499-1.636.558-2.913.06-1.28.072-1.687.072-4.947s-.015-3.667-.072-4.947c-.06-1.277-.262-2.149-.558-2.913-.306-.789-.718-1.459-1.384-2.126C21.319 1.347 20.651.935 19.86.63c-.765-.297-1.636-.499-2.913-.558C15.667.012 15.26 0 12 0zm0 2.16c3.203 0 3.585.016 4.85.071 1.17.055 1.805.249 2.227.415.562.217.96.477 1.382.896.419.42.679.819.896 1.381.164.422.36 1.057.413 2.227.057 1.266.07 1.646.07 4.85s-.015 3.585-.074 4.85c-.061 1.17-.256 1.805-.421 2.227-.224.562-.479.96-.899 1.382-.419.419-.824.679-1.38.896-.42.164-1.065.36-2.235.413-1.274.057-1.649.07-4.859.07-3.211 0-3.586-.015-4.859-.074-1.171-.061-1.816-.256-2.236-.421-.569-.224-.96-.479-1.379-.899-.421-.419-.69-.824-.9-1.38-.165-.42-.359-1.065-.42-2.235-.045-1.26-.061-1.649-.061-4.844 0-3.196.016-3.586.061-4.861.061-1.17.255-1.814.42-2.234.21-.57.479-.96.9-1.381.419-.419.81-.689 1.379-.898.42-.166 1.051-.361 2.221-.421 1.275-.045 1.65-.06 4.859-.06l.045.03zm0 3.678c-3.405 0-6.162 2.76-6.162 6.162 0 3.405 2.76 6.162 6.162 6.162 3.405 0 6.162-2.76 6.162-6.162 0-3.405-2.76-6.162-6.162-6.162zM12 16c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4zm7.846-10.405c0 .795-.646 1.44-1.44 1.44-.795 0-1.44-.646-1.44-1.44 0-.794.646-1.439 1.44-1.439.793-.001 1.44.645 1.44 1.439z"></path></svg></a><a class="text-sm text-gray-500 transition hover:text-gray-600" target="_blank" rel="noopener noreferrer" href="https://www.threads.net"><span class="sr-only">threads</span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6"><title>Threads</title><path d="M12.186 24h-.007c-3.581-.024-6.334-1.205-8.184-3.509C2.35 18.44 1.5 15.586 1.472 12.01v-.017c.03-3.579.879-6.43 2.525-8.482C5.845 1.205 8.6.024 12.18 0h.014c2.746.02 5.043.725 6.826 2.098 1.677 1.29 2.858 3.13 3.509 5.467l-2.04.569c-1.104-3.96-3.898-5.984-8.304-6.015-2.91.022-5.11.936-6.54 2.717C4.307 6.504 3.616 8.914 3.589 12c.027 3.086.718 5.496 2.057 7.164 1.43 1.783 3.631 2.698 6.54 2.717 2.623-.02 4.358-.631 5.8-2.045 1.647-1.613 1.618-3.593 1.09-4.798-.31-.71-.873-1.3-1.634-1.75-.192 1.352-.622 2.446-1.284 3.272-.886 1.102-2.14 1.704-3.73 1.79-1.202.065-2.361-.218-3.259-.801-1.063-.689-1.685-1.74-1.752-2.964-.065-1.19.408-2.285 1.33-3.082.88-.76 2.119-1.207 3.583-1.291a13.853 13.853 0 0 1 3.02.142c-.126-.742-.375-1.332-.75-1.757-.513-.586-1.308-.883-2.359-.89h-.029c-.844 0-1.992.232-2.721 1.32L7.734 7.847c.98-1.454 2.568-2.256 4.478-2.256h.044c3.194.02 5.097 1.975 5.287 5.388.108.046.216.094.321.142 1.49.7 2.58 1.761 3.154 3.07.797 1.82.871 4.79-1.548 7.158-1.85 1.81-4.094 2.628-7.277 2.65Zm1.003-11.69c-.242 0-.487.007-.739.021-1.836.103-2.98.946-2.916 2.143.067 1.256 1.452 1.839 2.784 1.767 1.224-.065 2.818-.543 3.086-3.71a10.5 10.5 0 0 0-2.215-.221z"></path></svg></a><a class="text-sm text-gray-500 transition hover:text-gray-600" target="_blank" rel="noopener noreferrer" href="https://medium.com"><span class="sr-only">medium</span><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6"><title>Medium</title><path d="M13.54 12a6.8 6.8 0 01-6.77 6.82A6.8 6.8 0 010 12a6.8 6.8 0 016.77-6.82A6.8 6.8 0 0113.54 12zM20.96 12c0 3.54-1.51 6.42-3.38 6.42-1.87 0-3.39-2.88-3.39-6.42s1.52-6.42 3.39-6.42 3.38 2.88 3.38 6.42M24 12c0 3.17-.53 5.75-1.19 5.75-.66 0-1.19-2.58-1.19-5.75s.53-5.75 1.19-5.75C23.47 6.25 24 8.83 24 12z"></path></svg></a></div><div class="mb-2 flex space-x-2 text-sm text-gray-500 dark:text-gray-400"><div>Tails Azimuth</div><div> • </div><div>© 2026</div><div> • </div><a class="break-words" href="/">Next.js Starter Blog</a></div><div class="mb-8 text-sm text-gray-500 dark:text-gray-400"><a class="break-words" target="_blank" rel="noopener noreferrer" href="https://github.com/timlrx/tailwind-nextjs-starter-blog">Tailwind Nextjs Theme</a></div></div></footer></section><script src="/_next/static/chunks/webpack-af24fb31267d6e11.js" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[1478,[\"545\",\"static/chunks/c16f53c3-5b47b7f1ae12d8f6.js\",\"874\",\"static/chunks/874-7cca39d2e0ddd8b8.js\",\"430\",\"static/chunks/430-f83175351bcd3192.js\",\"177\",\"static/chunks/app/layout-6cdc32e6ffe9019a.js\"],\"ThemeProviders\"]\n3:I[9243,[\"545\",\"static/chunks/c16f53c3-5b47b7f1ae12d8f6.js\",\"874\",\"static/chunks/874-7cca39d2e0ddd8b8.js\",\"430\",\"static/chunks/430-f83175351bcd3192.js\",\"177\",\"static/chunks/app/layout-6cdc32e6ffe9019a.js\"],\"\"]\n4:I[7392,[\"545\",\"static/chunks/c16f53c3-5b47b7f1ae12d8f6.js\",\"874\",\"static/chunks/874-7cca39d2e0ddd8b8.js\",\"430\",\"static/chunks/430-f83175351bcd3192.js\",\"177\",\"static/chunks/app/layout-6cdc32e6ffe9019a.js\"],\"KBarSearchProvider\"]\n5:I[6874,[\"874\",\"static/chunks/874-7cca39d2e0ddd8b8.js\",\"63\",\"static/chunks/63-ef4ffe428c84fbc3.js\",\"909\",\"static/chunks/app/blog/%5B...slug%5D/page-55fdf120c49a8b1e.js\"],\"\"]\n6:I[4159,[\"545\",\"static/chunks/c16f53c3-5b47b7f1ae12d8f6.js\",\"874\",\"static/chunks/874-7cca39d2e0ddd8b8.js\",\"430\",\"static/chunks/430-f83175351bcd3192.js\",\"177\",\"static/chunks/app/layout-6cdc32e6ffe9019a.js\"],\"KBarButton\"]\n7:I[1762,[\"545\",\"static/chunks/c16f53c3-5b47b7f1ae12d8f6.js\",\"874\",\"static/chunks/874-7cca39d2e0ddd8b8.js\",\"430\",\"static/chunks/430-f83175351bcd3192.js\",\"177\",\"static/chunks/app/layout-6cdc32e6ffe9019a.js\"],\"default\"]\n8:I[7298,[\"545\",\"static/chunks/c16f53c3-5b47b7f1ae12d8f6.js\",\"874\",\"static/chunks/874-7cca39d2e0ddd8b8.js\",\"430\",\"static/chunks/430-f83175351bcd3192.js\",\"177\",\"static/chunks/app/layout-6cdc32e6ffe9019a.js\"],\"default\"]\n9:I[7555,[],\"\"]\na:I[1295,[],\"\"]\ne:I[9665,[],\"OutletBoundary\"]\n11:I[9665,[],\"ViewportBoundary\"]\n13:I[9665,[],\"MetadataBoundary\"]\n15:I[6614,[],\"\"]\n:HL[\"/_next/static/media/36966cca54120369-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/css/51ff4ab09cd9a322.css\",\"style\"]\n:HL[\"/_next/static/css/ec75326fdf363785.css\",\"style\"]\n:HL[\"/_next/static/css/7abc17aba6a0edf4.css\",\"style\"]\nb:T69f,M12 0C8.74 0 8.333.015 7.053.072 5.775.132 4.905.333 4.14.63c-.789.306-1.459.717-2.126 1.384S.935 3.35.63 4.14C.333 "])</script><script>self.__next_f.push([1,"4.905.131 5.775.072 7.053.012 8.333 0 8.74 0 12s.015 3.667.072 4.947c.06 1.277.261 2.148.558 2.913.306.788.717 1.459 1.384 2.126.667.666 1.336 1.079 2.126 1.384.766.296 1.636.499 2.913.558C8.333 23.988 8.74 24 12 24s3.667-.015 4.947-.072c1.277-.06 2.148-.262 2.913-.558.788-.306 1.459-.718 2.126-1.384.666-.667 1.079-1.335 1.384-2.126.296-.765.499-1.636.558-2.913.06-1.28.072-1.687.072-4.947s-.015-3.667-.072-4.947c-.06-1.277-.262-2.149-.558-2.913-.306-.789-.718-1.459-1.384-2.126C21.319 1.347 20.651.935 19.86.63c-.765-.297-1.636-.499-2.913-.558C15.667.012 15.26 0 12 0zm0 2.16c3.203 0 3.585.016 4.85.071 1.17.055 1.805.249 2.227.415.562.217.96.477 1.382.896.419.42.679.819.896 1.381.164.422.36 1.057.413 2.227.057 1.266.07 1.646.07 4.85s-.015 3.585-.074 4.85c-.061 1.17-.256 1.805-.421 2.227-.224.562-.479.96-.899 1.382-.419.419-.824.679-1.38.896-.42.164-1.065.36-2.235.413-1.274.057-1.649.07-4.859.07-3.211 0-3.586-.015-4.859-.074-1.171-.061-1.816-.256-2.236-.421-.569-.224-.96-.479-1.379-.899-.421-.419-.69-.824-.9-1.38-.165-.42-.359-1.065-.42-2.235-.045-1.26-.061-1.649-.061-4.844 0-3.196.016-3.586.061-4.861.061-1.17.255-1.814.42-2.234.21-.57.479-.96.9-1.381.419-.419.81-.689 1.379-.898.42-.166 1.051-.361 2.221-.421 1.275-.045 1.65-.06 4.859-.06l.045.03zm0 3.678c-3.405 0-6.162 2.76-6.162 6.162 0 3.405 2.76 6.162 6.162 6.162 3.405 0 6.162-2.76 6.162-6.162 0-3.405-2.76-6.162-6.162-6.162zM12 16c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4zm7.846-10.405c0 .795-.646 1.44-1.44 1.44-.795 0-1.44-.646-1.44-1.44 0-.794.646-1.439 1.44-1.439.793-.001 1.44.645 1.44 1.439zc:T498,M12.186 24h-.007c-3.581-.024-6.334-1.205-8.184-3.509C2.35 18.44 1.5 15.586 1.472 12.01v-.017c.03-3.579.879-6.43 2.525-8.482C5.845 1.205 8.6.024 12.18 0h.014c2.746.02 5.043.725 6.826 2.098 1.677 1.29 2.858 3.13 3.509 5.467l-2.04.569c-1.104-3.96-3.898-5.984-8.304-6.015-2.91.022-5.11.936-6.54 2.717C4.307 6.504 3.616 8.914 3.589 12c.027 3.086.718 5.496 2.057 7.164 1.43 1.783 3.631 2.698 6.54 2.717 2.623-.02 4.358-.631 5.8-2.045 1.647-1.613 1.618-3.593 1.09-4.798"])</script><script>self.__next_f.push([1,"-.31-.71-.873-1.3-1.634-1.75-.192 1.352-.622 2.446-1.284 3.272-.886 1.102-2.14 1.704-3.73 1.79-1.202.065-2.361-.218-3.259-.801-1.063-.689-1.685-1.74-1.752-2.964-.065-1.19.408-2.285 1.33-3.082.88-.76 2.119-1.207 3.583-1.291a13.853 13.853 0 0 1 3.02.142c-.126-.742-.375-1.332-.75-1.757-.513-.586-1.308-.883-2.359-.89h-.029c-.844 0-1.992.232-2.721 1.32L7.734 7.847c.98-1.454 2.568-2.256 4.478-2.256h.044c3.194.02 5.097 1.975 5.287 5.388.108.046.216.094.321.142 1.49.7 2.58 1.761 3.154 3.07.797 1.82.871 4.79-1.548 7.158-1.85 1.81-4.094 2.628-7.277 2.65Zm1.003-11.69c-.242 0-.487.007-.739.021-1.836.103-2.98.946-2.916 2.143.067 1.256 1.452 1.839 2.784 1.767 1.224-.065 2.818-.543 3.086-3.71a10.5 10.5 0 0 0-2.215-.221z"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"sCS18nH11lqaRF2xVLwHp\",\"p\":\"\",\"c\":[\"\",\"blog\",\"release-of-tailwind-nextjs-starter-blog-v2.0\"],\"i\":false,\"f\":[[[\"\",{\"children\":[\"blog\",{\"children\":[[\"slug\",\"release-of-tailwind-nextjs-starter-blog-v2.0\",\"c\"],{\"children\":[\"__PAGE__\",{}]}]}]},\"$undefined\",\"$undefined\",true],[\"\",[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/51ff4ab09cd9a322.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"link\",\"1\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/ec75326fdf363785.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en-us\",\"className\":\"__variable_dd5b2f scroll-smooth\",\"suppressHydrationWarning\":true,\"children\":[[\"$\",\"link\",null,{\"rel\":\"apple-touch-icon\",\"sizes\":\"76x76\",\"href\":\"/static/favicons/apple-touch-icon.png\"}],[\"$\",\"link\",null,{\"rel\":\"icon\",\"type\":\"image/png\",\"sizes\":\"32x32\",\"href\":\"/static/favicons/favicon-32x32.png\"}],[\"$\",\"link\",null,{\"rel\":\"icon\",\"type\":\"image/png\",\"sizes\":\"16x16\",\"href\":\"/static/favicons/favicon-16x16.png\"}],[\"$\",\"link\",null,{\"rel\":\"manifest\",\"href\":\"/static/favicons/site.webmanifest\"}],[\"$\",\"link\",null,{\"rel\":\"mask-icon\",\"href\":\"/static/favicons/safari-pinned-tab.svg\",\"color\":\"#5bbad5\"}],[\"$\",\"meta\",null,{\"name\":\"msapplication-TileColor\",\"content\":\"#000000\"}],[\"$\",\"meta\",null,{\"name\":\"theme-color\",\"media\":\"(prefers-color-scheme: light)\",\"content\":\"#fff\"}],[\"$\",\"meta\",null,{\"name\":\"theme-color\",\"media\":\"(prefers-color-scheme: dark)\",\"content\":\"#000\"}],[\"$\",\"link\",null,{\"rel\":\"alternate\",\"type\":\"application/rss+xml\",\"href\":\"/feed.xml\"}],[\"$\",\"body\",null,{\"className\":\"bg-white pl-[calc(100vw-100%)] text-black antialiased dark:bg-gray-950 dark:text-white\",\"children\":[\"$\",\"$L2\",null,{\"children\":[[\"$undefined\",\"$undefined\",\"$undefined\",[\"$\",\"$L3\",null,{\"async\":true,\"defer\":true,\"src\":\"https://analytics.umami.is/script.js\"}],\"$undefined\",\"$undefined\"],[\"$\",\"section\",null,{\"className\":\"mx-auto max-w-3xl px-4 sm:px-6 xl:max-w-5xl xl:px-0\",\"children\":[[\"$\",\"$L4\",null,{\"kbarConfig\":{\"searchDocumentsPath\":\"/search.json\"},\"children\":[[\"$\",\"header\",null,{\"className\":\"flex items-center w-full bg-white dark:bg-gray-950 justify-between py-10\",\"children\":[[\"$\",\"$L5\",null,{\"className\":\"break-words\",\"href\":\"/\",\"aria-label\":\"TailwindBlog\",\"children\":[\"$\",\"div\",null,{\"className\":\"flex items-center justify-between\",\"children\":[[\"$\",\"div\",null,{\"className\":\"mr-3\",\"children\":[\"$\",\"svg\",null,{\"xmlns\":\"http://www.w3.org/2000/svg\",\"xmlnsXlink\":\"http://www.w3.org/1999/xlink\",\"width\":53.87,\"height\":43.61,\"viewBox\":\"344.564 330.278 111.737 91.218\",\"children\":[[\"$\",\"defs\",null,{\"children\":[[\"$\",\"linearGradient\",null,{\"id\":\"logo_svg__b\",\"x1\":420.97,\"x2\":420.97,\"y1\":331.28,\"y2\":418.5,\"gradientUnits\":\"userSpaceOnUse\",\"children\":[[\"$\",\"stop\",null,{\"offset\":\"0%\",\"style\":{\"stopColor\":\"#06b6d4\",\"stopOpacity\":1}}],[\"$\",\"stop\",null,{\"offset\":\"100%\",\"style\":{\"stopColor\":\"#67e8f9\",\"stopOpacity\":1}}]]}],[\"$\",\"linearGradient\",null,{\"id\":\"logo_svg__d\",\"x1\":377.89,\"x2\":377.89,\"y1\":331.28,\"y2\":418.5,\"gradientUnits\":\"userSpaceOnUse\",\"children\":[[\"$\",\"stop\",null,{\"offset\":\"0%\",\"style\":{\"stopColor\":\"#06b6d4\",\"stopOpacity\":1}}],[\"$\",\"stop\",null,{\"offset\":\"100%\",\"style\":{\"stopColor\":\"#67e8f9\",\"stopOpacity\":1}}]]}],[\"$\",\"path\",null,{\"id\":\"logo_svg__a\",\"d\":\"M453.3 331.28v28.57l-64.66 58.65v-30.08z\"}],[\"$\",\"path\",null,{\"id\":\"logo_svg__c\",\"d\":\"M410.23 331.28v28.57l-64.67 58.65v-30.08z\"}]]}],[\"$\",\"use\",null,{\"xlinkHref\":\"#logo_svg__a\",\"fill\":\"url(#logo_svg__b)\"}],[\"$\",\"use\",null,{\"xlinkHref\":\"#logo_svg__c\",\"fill\":\"url(#logo_svg__d)\"}]]}]}],[\"$\",\"div\",null,{\"className\":\"hidden h-6 text-2xl font-semibold sm:block\",\"children\":\"TailwindBlog\"}]]}]}],[\"$\",\"div\",null,{\"className\":\"flex items-center space-x-4 leading-5 sm:-mr-6 sm:space-x-6\",\"children\":[[\"$\",\"div\",null,{\"className\":\"no-scrollbar hidden max-w-40 items-center gap-x-4 overflow-x-auto sm:flex md:max-w-72 lg:max-w-96\",\"children\":[[\"$\",\"$L5\",\"Blog\",{\"className\":\"hover:text-primary-500 dark:hover:text-primary-400 m-1 font-medium text-gray-900 dark:text-gray-100\",\"href\":\"/blog\",\"children\":\"Blog\"}],[\"$\",\"$L5\",\"Tags\",{\"className\":\"hover:text-primary-500 dark:hover:text-primary-400 m-1 font-medium text-gray-900 dark:text-gray-100\",\"href\":\"/tags\",\"children\":\"Tags\"}],[\"$\",\"$L5\",\"Projects\",{\"className\":\"hover:text-primary-500 dark:hover:text-primary-400 m-1 font-medium text-gray-900 dark:text-gray-100\",\"href\":\"/projects\",\"children\":\"Projects\"}],[\"$\",\"$L5\",\"About\",{\"className\":\"hover:text-primary-500 dark:hover:text-primary-400 m-1 font-medium text-gray-900 dark:text-gray-100\",\"href\":\"/about\",\"children\":\"About\"}]]}],[\"$\",\"$L6\",null,{\"aria-label\":\"Search\",\"children\":[\"$\",\"svg\",null,{\"xmlns\":\"http://www.w3.org/2000/svg\",\"fill\":\"none\",\"viewBox\":\"0 0 24 24\",\"strokeWidth\":1.5,\"stroke\":\"currentColor\",\"className\":\"hover:text-primary-500 dark:hover:text-primary-400 h-6 w-6 text-gray-900 dark:text-gray-100\",\"children\":[\"$\",\"path\",null,{\"strokeLinecap\":\"round\",\"strokeLinejoin\":\"round\",\"d\":\"M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z\"}]}]}],[\"$\",\"$L7\",null,{}],[\"$\",\"$L8\",null,{}]]}]]}],[\"$\",\"main\",null,{\"className\":\"mb-auto\",\"children\":[\"$\",\"$L9\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$La\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[\"$\",\"div\",null,{\"className\":\"flex flex-col items-start justify-start md:mt-24 md:flex-row md:items-center md:justify-center md:space-x-6\",\"children\":[[\"$\",\"div\",null,{\"className\":\"space-x-2 pt-6 pb-8 md:space-y-5\",\"children\":[\"$\",\"h1\",null,{\"className\":\"text-6xl leading-9 font-extrabold tracking-tight text-gray-900 md:border-r-2 md:px-6 md:text-8xl md:leading-14 dark:text-gray-100\",\"children\":\"404\"}]}],[\"$\",\"div\",null,{\"className\":\"max-w-md\",\"children\":[[\"$\",\"p\",null,{\"className\":\"mb-4 text-xl leading-normal font-bold md:text-2xl\",\"children\":\"Sorry we couldn't find this page.\"}],[\"$\",\"p\",null,{\"className\":\"mb-8\",\"children\":\"But dont worry, you can find plenty of other things on our homepage.\"}],[\"$\",\"$L5\",null,{\"className\":\"focus:shadow-outline-blue inline rounded-lg border border-transparent bg-blue-600 px-4 py-2 text-sm leading-5 font-medium text-white shadow-xs transition-colors duration-150 hover:bg-blue-700 focus:outline-hidden dark:hover:bg-blue-500\",\"href\":\"/\",\"children\":\"Back to homepage\"}]]}]]}],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]]}],[\"$\",\"footer\",null,{\"children\":[\"$\",\"div\",null,{\"className\":\"mt-16 flex flex-col items-center\",\"children\":[[\"$\",\"div\",null,{\"className\":\"mb-3 flex space-x-4\",\"children\":[[\"$\",\"a\",null,{\"className\":\"text-sm text-gray-500 transition hover:text-gray-600\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"mailto:address@yoursite.com\",\"children\":[[\"$\",\"span\",null,{\"className\":\"sr-only\",\"children\":\"mail\"}],[\"$\",\"svg\",null,{\"xmlns\":\"http://www.w3.org/2000/svg\",\"viewBox\":\"0 0 20 20\",\"className\":\"hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6\",\"children\":[[\"$\",\"title\",null,{\"children\":\"Mail\"}],[\"$\",\"path\",null,{\"d\":\"M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z\"}],[\"$\",\"path\",null,{\"d\":\"M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z\"}]]}]]}],[\"$\",\"a\",null,{\"className\":\"text-sm text-gray-500 transition hover:text-gray-600\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://github.com\",\"children\":[[\"$\",\"span\",null,{\"className\":\"sr-only\",\"children\":\"github\"}],[\"$\",\"svg\",null,{\"xmlns\":\"http://www.w3.org/2000/svg\",\"viewBox\":\"0 0 24 24\",\"className\":\"hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6\",\"children\":[[\"$\",\"title\",null,{\"children\":\"GitHub\"}],[\"$\",\"path\",null,{\"d\":\"M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\"}]]}]]}],[\"$\",\"a\",null,{\"className\":\"text-sm text-gray-500 transition hover:text-gray-600\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://facebook.com\",\"children\":[[\"$\",\"span\",null,{\"className\":\"sr-only\",\"children\":\"facebook\"}],[\"$\",\"svg\",null,{\"xmlns\":\"http://www.w3.org/2000/svg\",\"viewBox\":\"0 0 24 24\",\"className\":\"hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6\",\"children\":[[\"$\",\"title\",null,{\"children\":\"Facebook\"}],[\"$\",\"path\",null,{\"d\":\"M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z\"}]]}]]}],[\"$\",\"a\",null,{\"className\":\"text-sm text-gray-500 transition hover:text-gray-600\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://youtube.com\",\"children\":[[\"$\",\"span\",null,{\"className\":\"sr-only\",\"children\":\"youtube\"}],[\"$\",\"svg\",null,{\"xmlns\":\"http://www.w3.org/2000/svg\",\"viewBox\":\"0 0 24 24\",\"className\":\"hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6\",\"children\":[[\"$\",\"title\",null,{\"children\":\"Youtube\"}],[\"$\",\"path\",null,{\"d\":\"M23.499 6.203a3.008 3.008 0 00-2.089-2.089c-1.87-.501-9.4-.501-9.4-.501s-7.509-.01-9.399.501a3.008 3.008 0 00-2.088 2.09A31.258 31.26 0 000 12.01a31.258 31.26 0 00.523 5.785 3.008 3.008 0 002.088 2.089c1.869.502 9.4.502 9.4.502s7.508 0 9.399-.502a3.008 3.008 0 002.089-2.09 31.258 31.26 0 00.5-5.784 31.258 31.26 0 00-.5-5.808zm-13.891 9.4V8.407l6.266 3.604z\"}]]}]]}],[\"$\",\"a\",null,{\"className\":\"text-sm text-gray-500 transition hover:text-gray-600\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://www.linkedin.com\",\"children\":[[\"$\",\"span\",null,{\"className\":\"sr-only\",\"children\":\"linkedin\"}],[\"$\",\"svg\",null,{\"xmlns\":\"http://www.w3.org/2000/svg\",\"viewBox\":\"0 0 24 24\",\"className\":\"hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6\",\"children\":[[\"$\",\"title\",null,{\"children\":\"Linkedin\"}],[\"$\",\"path\",null,{\"d\":\"M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433a2.062 2.062 0 01-2.063-2.065 2.064 2.064 0 112.063 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z\"}]]}]]}],null,[\"$\",\"a\",null,{\"className\":\"text-sm text-gray-500 transition hover:text-gray-600\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://bsky.app/\",\"children\":[[\"$\",\"span\",null,{\"className\":\"sr-only\",\"children\":\"bluesky\"}],[\"$\",\"svg\",null,{\"xmlns\":\"http://www.w3.org/2000/svg\",\"viewBox\":\"0 0 24 24\",\"className\":\"hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6\",\"children\":[[\"$\",\"title\",null,{\"children\":\"Bluesky\"}],[\"$\",\"path\",null,{\"d\":\"M12 10.8c-1.087-2.114-4.046-6.053-6.798-7.995C2.566.944 1.561 1.266.902 1.565C.139 1.908 0 3.08 0 3.768c0 .69.378 5.65.624 6.479c.815 2.736 3.713 3.66 6.383 3.364q.204-.03.415-.056q-.207.033-.415.056c-3.912.58-7.387 2.005-2.83 7.078c5.013 5.19 6.87-1.113 7.823-4.308c.953 3.195 2.05 9.271 7.733 4.308c4.267-4.308 1.172-6.498-2.74-7.078a9 9 0 0 1-.415-.056q.21.026.415.056c2.67.297 5.568-.628 6.383-3.364c.246-.828.624-5.79.624-6.478c0-.69-.139-1.861-.902-2.206c-.659-.298-1.664-.62-4.3 1.24C16.046 4.748 13.087 8.687 12 10.8\"}]]}]]}],[\"$\",\"a\",null,{\"className\":\"text-sm text-gray-500 transition hover:text-gray-600\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://twitter.com/x\",\"children\":[[\"$\",\"span\",null,{\"className\":\"sr-only\",\"children\":\"x\"}],[\"$\",\"svg\",null,{\"xmlns\":\"http://www.w3.org/2000/svg\",\"viewBox\":\"0 0 24 24\",\"className\":\"hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6\",\"children\":[[\"$\",\"title\",null,{\"children\":\"X\"}],[\"$\",\"path\",null,{\"d\":\"M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z\"}]]}]]}],[\"$\",\"a\",null,{\"className\":\"text-sm text-gray-500 transition hover:text-gray-600\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://www.instagram.com\",\"children\":[[\"$\",\"span\",null,{\"className\":\"sr-only\",\"children\":\"instagram\"}],[\"$\",\"svg\",null,{\"xmlns\":\"http://www.w3.org/2000/svg\",\"viewBox\":\"0 0 24 24\",\"className\":\"hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6\",\"children\":[[\"$\",\"title\",null,{\"children\":\"Instagram\"}],[\"$\",\"path\",null,{\"d\":\"$b\"}]]}]]}],[\"$\",\"a\",null,{\"className\":\"text-sm text-gray-500 transition hover:text-gray-600\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://www.threads.net\",\"children\":[[\"$\",\"span\",null,{\"className\":\"sr-only\",\"children\":\"threads\"}],[\"$\",\"svg\",null,{\"xmlns\":\"http://www.w3.org/2000/svg\",\"viewBox\":\"0 0 24 24\",\"className\":\"hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6\",\"children\":[[\"$\",\"title\",null,{\"children\":\"Threads\"}],[\"$\",\"path\",null,{\"d\":\"$c\"}]]}]]}],[\"$\",\"a\",null,{\"className\":\"text-sm text-gray-500 transition hover:text-gray-600\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://medium.com\",\"children\":[[\"$\",\"span\",null,{\"className\":\"sr-only\",\"children\":\"medium\"}],[\"$\",\"svg\",null,{\"xmlns\":\"http://www.w3.org/2000/svg\",\"viewBox\":\"0 0 24 24\",\"className\":\"hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6\",\"children\":[[\"$\",\"title\",null,{\"children\":\"Medium\"}],[\"$\",\"path\",null,{\"d\":\"M13.54 12a6.8 6.8 0 01-6.77 6.82A6.8 6.8 0 010 12a6.8 6.8 0 016.77-6.82A6.8 6.8 0 0113.54 12zM20.96 12c0 3.54-1.51 6.42-3.38 6.42-1.87 0-3.39-2.88-3.39-6.42s1.52-6.42 3.39-6.42 3.38 2.88 3.38 6.42M24 12c0 3.17-.53 5.75-1.19 5.75-.66 0-1.19-2.58-1.19-5.75s.53-5.75 1.19-5.75C23.47 6.25 24 8.83 24 12z\"}]]}]]}]]}],[\"$\",\"div\",null,{\"className\":\"mb-2 flex space-x-2 text-sm text-gray-500 dark:text-gray-400\",\"children\":[[\"$\",\"div\",null,{\"children\":\"Tails Azimuth\"}],[\"$\",\"div\",null,{\"children\":\" • \"}],[\"$\",\"div\",null,{\"children\":\"© 2026\"}],[\"$\",\"div\",null,{\"children\":\" • \"}],[\"$\",\"$L5\",null,{\"className\":\"break-words\",\"href\":\"/\",\"children\":\"Next.js Starter Blog\"}]]}],[\"$\",\"div\",null,{\"className\":\"mb-8 text-sm text-gray-500 dark:text-gray-400\",\"children\":[\"$\",\"a\",null,{\"className\":\"break-words\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://github.com/timlrx/tailwind-nextjs-starter-blog\",\"children\":\"Tailwind Nextjs Theme\"}]}]]}]}]]}]]}]}]]}]]}],{\"children\":[\"blog\",[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L9\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$La\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"slug\",\"release-of-tailwind-nextjs-starter-blog-v2.0\",\"c\"],[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L9\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$La\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[\"__PAGE__\",[\"$\",\"$1\",\"c\",{\"children\":[\"$Ld\",\"$undefined\",[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/7abc17aba6a0edf4.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"$Le\",null,{\"children\":[\"$Lf\",\"$L10\",null]}]]}],{},null,false]},null,false]},null,false]},null,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$1\",\"DXyvx78kh8MUXF1c6G92o\",{\"children\":[[\"$\",\"$L11\",null,{\"children\":\"$L12\"}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],[\"$\",\"$L13\",null,{\"children\":\"$L14\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$15\",\"$undefined\"],\"s\":false,\"S\":true}\n"])</script><script>self.__next_f.push([1,"16:I[1839,[\"874\",\"static/chunks/874-7cca39d2e0ddd8b8.js\",\"63\",\"static/chunks/63-ef4ffe428c84fbc3.js\",\"909\",\"static/chunks/app/blog/%5B...slug%5D/page-55fdf120c49a8b1e.js\"],\"default\"]\n17:I[3063,[\"874\",\"static/chunks/874-7cca39d2e0ddd8b8.js\",\"63\",\"static/chunks/63-ef4ffe428c84fbc3.js\",\"909\",\"static/chunks/app/blog/%5B...slug%5D/page-55fdf120c49a8b1e.js\"],\"Image\"]\n18:I[2100,[\"874\",\"static/chunks/874-7cca39d2e0ddd8b8.js\",\"63\",\"static/chunks/63-ef4ffe428c84fbc3.js\",\"909\",\"static/chunks/app/blog/%5B...slug%5D/page-55fdf120c49a8b1e.js\"],\"default\"]\n19:I[1449,[\"874\",\"static/chunks/874-7cca39d2e0ddd8b8.js\",\"63\",\"static/chunks/63-ef4ffe428c84fbc3.js\",\"909\",\"static/chunks/app/blog/%5B...slug%5D/page-55fdf120c49a8b1e.js\"],\"default\"]\n"])</script><script>self.__next_f.push([1,"d:[[\"$\",\"script\",null,{\"type\":\"application/ld+json\",\"dangerouslySetInnerHTML\":{\"__html\":\"{\\\"@context\\\":\\\"https://schema.org\\\",\\\"@type\\\":\\\"BlogPosting\\\",\\\"headline\\\":\\\"Release of Tailwind Nextjs Starter Blog v2.0\\\",\\\"datePublished\\\":\\\"2023-08-05T00:00:00.000Z\\\",\\\"dateModified\\\":\\\"2023-08-05T00:00:00.000Z\\\",\\\"description\\\":\\\"Release of Tailwind Nextjs Starter Blog template v2.0, refactored with Nextjs App directory and React Server Components setup.Discover the new features and how to migrate from V1.\\\",\\\"image\\\":\\\"/static/images/twitter-card.png\\\",\\\"url\\\":\\\"https://tailwind-nextjs-starter-blog.vercel.app/blog/release-of-tailwind-nextjs-starter-blog-v2.0\\\",\\\"author\\\":[{\\\"@type\\\":\\\"Person\\\",\\\"name\\\":\\\"Tails Azimuth\\\"}]}\"}}],[\"$\",\"section\",null,{\"className\":\"mx-auto max-w-3xl px-4 sm:px-6 xl:max-w-5xl xl:px-0\",\"children\":[[\"$\",\"$L16\",null,{}],[\"$\",\"article\",null,{\"children\":[\"$\",\"div\",null,{\"className\":\"xl:divide-y xl:divide-gray-200 xl:dark:divide-gray-700\",\"children\":[[\"$\",\"header\",null,{\"className\":\"pt-6 xl:pb-6\",\"children\":[\"$\",\"div\",null,{\"className\":\"space-y-1 text-center\",\"children\":[[\"$\",\"dl\",null,{\"className\":\"space-y-10\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"dt\",null,{\"className\":\"sr-only\",\"children\":\"Published on\"}],[\"$\",\"dd\",null,{\"className\":\"text-base leading-6 font-medium text-gray-500 dark:text-gray-400\",\"children\":[\"$\",\"time\",null,{\"dateTime\":\"2023-08-05T00:00:00.000Z\",\"children\":\"Saturday, August 5, 2023\"}]}]]}]}],[\"$\",\"div\",null,{\"children\":[\"$\",\"h1\",null,{\"className\":\"text-3xl leading-9 font-extrabold tracking-tight text-gray-900 sm:text-4xl sm:leading-10 md:text-5xl md:leading-14 dark:text-gray-100\",\"children\":\"Release of Tailwind Nextjs Starter Blog v2.0\"}]}]]}]}],[\"$\",\"div\",null,{\"className\":\"grid-rows-[auto_1fr] divide-y divide-gray-200 pb-8 xl:grid xl:grid-cols-4 xl:gap-x-6 xl:divide-y-0 dark:divide-gray-700\",\"children\":[[\"$\",\"dl\",null,{\"className\":\"pt-6 pb-10 xl:border-b xl:border-gray-200 xl:pt-11 xl:dark:border-gray-700\",\"children\":[[\"$\",\"dt\",null,{\"className\":\"sr-only\",\"children\":\"Authors\"}],[\"$\",\"dd\",null,{\"children\":[\"$\",\"ul\",null,{\"className\":\"flex flex-wrap justify-center gap-4 sm:space-x-12 xl:block xl:space-y-8 xl:space-x-0\",\"children\":[[\"$\",\"li\",\"Tails Azimuth\",{\"className\":\"flex items-center space-x-2\",\"children\":[[\"$\",\"$L17\",null,{\"src\":\"/static/images/avatar.png\",\"width\":38,\"height\":38,\"alt\":\"avatar\",\"className\":\"h-10 w-10 rounded-full\"}],[\"$\",\"dl\",null,{\"className\":\"text-sm leading-5 font-medium whitespace-nowrap\",\"children\":[[\"$\",\"dt\",null,{\"className\":\"sr-only\",\"children\":\"Name\"}],[\"$\",\"dd\",null,{\"className\":\"text-gray-900 dark:text-gray-100\",\"children\":\"Tails Azimuth\"}],[\"$\",\"dt\",null,{\"className\":\"sr-only\",\"children\":\"Twitter\"}],[\"$\",\"dd\",null,{\"children\":[\"$\",\"a\",null,{\"className\":\"text-primary-500 hover:text-primary-600 dark:hover:text-primary-400\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://twitter.com/Twitter\",\"children\":\"@Twitter\"}]}]]}]]}]]}]}]]}],[\"$\",\"div\",null,{\"className\":\"divide-y divide-gray-200 xl:col-span-3 xl:row-span-2 xl:pb-0 dark:divide-gray-700\",\"children\":[[\"$\",\"div\",null,{\"className\":\"prose dark:prose-invert max-w-none pt-10 pb-8\",\"children\":[[\"$\",\"h2\",null,{\"className\":\"content-header\",\"id\":\"introduction\",\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#introduction\",\"aria-hidden\":\"true\",\"tabIndex\":\"-1\",\"children\":[\"$\",\"span\",null,{\"className\":\"content-header-link\",\"children\":[\"$\",\"svg\",null,{\"className\":\"h-5 linkicon w-5\",\"fill\":\"currentColor\",\"viewBox\":\"0 0 20 20\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"children\":[[\"$\",\"path\",null,{\"d\":\"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z\"}],[\"$\",\"path\",null,{\"d\":\"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z\"}]]}]}]}],\"Introduction\"]}],[\"$\",\"p\",null,{\"children\":\"Welcome to the release of Tailwind Nextjs Starter Blog template v2.0. This release is a major refactor of the codebase to support Nextjs App directory and React Server Components. Read on to discover the new features and how to migrate from V1.\"}],[\"$\",\"ul\",null,{\"className\":\"\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"\",\"children\":[[\"$\",\"a\",null,{\"href\":\"#v1-to-v2\",\"children\":\"V1 to V2\"}],null]}],[\"$\",\"li\",\"1\",{\"className\":\"\",\"children\":[[\"$\",\"a\",null,{\"href\":\"#nextjs-app-directory-and-react-server-components\",\"children\":\"Next.js App Directory and React Server Components\"}],null]}],[\"$\",\"li\",\"2\",{\"className\":\"\",\"children\":[[\"$\",\"a\",null,{\"href\":\"#typescript-first\",\"children\":\"Typescript First\"}],null]}],[\"$\",\"li\",\"3\",{\"className\":\"\",\"children\":[[\"$\",\"a\",null,{\"href\":\"#contentlayer\",\"children\":\"Contentlayer\"}],null]}],[\"$\",\"li\",\"4\",{\"className\":\"\",\"children\":[[\"$\",\"a\",null,{\"href\":\"#pliny\",\"children\":\"Pliny\"}],null]}],[\"$\",\"li\",\"5\",{\"className\":\"\",\"children\":[[\"$\",\"a\",null,{\"href\":\"#new-search-component\",\"children\":\"New Search Component\"}],[\"$\",\"ul\",null,{\"className\":\"\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"\",\"children\":[[\"$\",\"a\",null,{\"href\":\"#algolia\",\"children\":\"Algolia\"}],null]}],[\"$\",\"li\",\"1\",{\"className\":\"\",\"children\":[[\"$\",\"a\",null,{\"href\":\"#kbar\",\"children\":\"Kbar\"}],null]}]]}]]}],[\"$\",\"li\",\"6\",{\"className\":\"\",\"children\":[[\"$\",\"a\",null,{\"href\":\"#styling-and-layout-updates\",\"children\":\"Styling and Layout Updates\"}],[\"$\",\"ul\",null,{\"className\":\"\",\"children\":[[\"$\",\"li\",\"0\",{\"className\":\"\",\"children\":[[\"$\",\"a\",null,{\"href\":\"#theming\",\"children\":\"Theming\"}],null]}],[\"$\",\"li\",\"1\",{\"className\":\"\",\"children\":[[\"$\",\"a\",null,{\"href\":\"#new-layouts\",\"children\":\"New Layouts\"}],null]}]]}]]}],[\"$\",\"li\",\"7\",{\"className\":\"\",\"children\":[[\"$\",\"a\",null,{\"href\":\"#migration-recommendations\",\"children\":\"Migration Recommendations\"}],null]}],[\"$\",\"li\",\"8\",{\"className\":\"\",\"children\":[[\"$\",\"a\",null,{\"href\":\"#conclusion\",\"children\":\"Conclusion\"}],null]}],[\"$\",\"li\",\"9\",{\"className\":\"\",\"children\":[[\"$\",\"a\",null,{\"href\":\"#support\",\"children\":\"Support\"}],null]}],[\"$\",\"li\",\"10\",{\"className\":\"\",\"children\":[[\"$\",\"a\",null,{\"href\":\"#licence\",\"children\":\"Licence\"}],null]}]]}],[\"$\",\"h2\",null,{\"className\":\"content-header\",\"id\":\"v1-to-v2\",\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#v1-to-v2\",\"aria-hidden\":\"true\",\"tabIndex\":\"-1\",\"children\":[\"$\",\"span\",null,{\"className\":\"content-header-link\",\"children\":[\"$\",\"svg\",null,{\"className\":\"h-5 linkicon w-5\",\"fill\":\"currentColor\",\"viewBox\":\"0 0 20 20\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"children\":[[\"$\",\"path\",null,{\"d\":\"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z\"}],[\"$\",\"path\",null,{\"d\":\"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z\"}]]}]}]}],\"V1 to V2\"]}],[\"$\",\"div\",null,{\"children\":[\"$\",\"$L17\",null,{\"src\":\"/static/images/github-traffic.png\",\"alt\":\"Github Traffic\",\"width\":\"920\",\"height\":\"420\"}]}],[\"$\",\"p\",null,{\"children\":[\"The template was first released in January 2021 and has since been used by thousands of users. It is featured on \",[\"$\",\"a\",null,{\"className\":\"break-words\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://vercel.com/templates/next.js/tailwind-css-starter-blog\",\"children\":\"Next.js Templates\"}],\", \",[\"$\",\"a\",null,{\"className\":\"break-words\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://www.tailwindawesome.com/resources/tailwind-nextjs-starter-blog\",\"children\":\"Tailwind Awesome\"}],\" among other listing sites. It attracts 200+ unique visitors daily notching 1500-2000 page views, with 1.3k forks and many other clones.\"]}],[\"$\",\"p\",null,{\"children\":\"Many thanks to the community of users and contributors for making this template a success! I created a small video montage of the blogs (while cleaning up the list in the readme) to showcase the diversity of the blogs created using the template and to celebrate the milestone:\"}],[\"$\",\"video\",null,{\"controls\":true,\"children\":[\"$\",\"source\",null,{\"src\":\"https://github-production-user-asset-6210df.s3.amazonaws.com/28362229/258559849-2124c81f-b99d-4431-839c-347e01a2616c.webm\",\"type\":\"video/webm\"}]}],[\"$\",\"p\",null,{\"children\":\"Version 2 builds on the success of the previous version and introduces many new features and improvements. The codebase has been refactored to support Next.js App directory and React Server Components. Markdown / MDX is now processed using Contentlayer, a type-safe content SDK that validates and transforms your content into type-safe JSON data. It integrates with Pliny, a new library that provides out of the box Next.js components to enhance your static site with analytics, comments and newsletter subscription. A new command palette (⌘-k) search component is also added to the template.\"}],[\"$\",\"p\",null,{\"children\":\"Let's dive into the new features and improvements in V2.\"}],[\"$\",\"h2\",null,{\"className\":\"content-header\",\"id\":\"nextjs-app-directory-and-react-server-components\",\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#nextjs-app-directory-and-react-server-components\",\"aria-hidden\":\"true\",\"tabIndex\":\"-1\",\"children\":[\"$\",\"span\",null,{\"className\":\"content-header-link\",\"children\":[\"$\",\"svg\",null,{\"className\":\"h-5 linkicon w-5\",\"fill\":\"currentColor\",\"viewBox\":\"0 0 20 20\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"children\":[[\"$\",\"path\",null,{\"d\":\"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z\"}],[\"$\",\"path\",null,{\"d\":\"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z\"}]]}]}]}],\"Next.js App Directory and React Server Components\"]}],[\"$\",\"p\",null,{\"children\":[\"Now that \",[\"$\",\"a\",null,{\"className\":\"break-words\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://nextjs.org/docs/app\",\"children\":\"Next.js App router\"}],\" is finally stable and is mostly feature compatible with Page Router, the codebase has been migrated to new setup. This allows for a hybrid rendering approach, with the use of React Server Components generated on the server side for faster page loads and smaller bundle sizes, while retaining the ability to sprinkle in client side React components for interactivity.\",[\"$\",\"sup\",null,{\"children\":[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#user-content-fn-1\",\"aria-describedby\":\"footnote-label\",\"data-footnote-ref\":true,\"id\":\"user-content-fnref-1\",\"children\":\"1\"}]}]]}],[\"$\",\"p\",null,{\"children\":[\"With addition powers comes a \",[\"$\",\"a\",null,{\"className\":\"break-words\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://nextjs.org/docs/getting-started/react-essentials\",\"children\":\"new paradigm\"}],\" to learn. I have migrated the codebase to make use of the new features as much as possible. This includes changes in the folder structure, splitting components into server vs client components, leveraging server side data fetching and using the recommended \",[\"$\",\"a\",null,{\"className\":\"break-words\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://nextjs.org/docs/app/building-your-application/optimizing/metadata\",\"children\":\"Metadata\"}],\" API for SEO discoverability.\"]}],[\"$\",\"p\",null,{\"children\":[\"While this simplifies the codebase to some extent, it makes migration from the old codebase more difficult. If you are looking to migrate, I recommend starting from a fresh template and copying over your customizations and existing content. See the \",[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#migration-recommendations\",\"children\":\"migration recommendations\"}],\" section for more details.\"]}],[\"$\",\"h2\",null,{\"className\":\"content-header\",\"id\":\"typescript-first\",\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#typescript-first\",\"aria-hidden\":\"true\",\"tabIndex\":\"-1\",\"children\":[\"$\",\"span\",null,{\"className\":\"content-header-link\",\"children\":[\"$\",\"svg\",null,{\"className\":\"h-5 linkicon w-5\",\"fill\":\"currentColor\",\"viewBox\":\"0 0 20 20\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"children\":[[\"$\",\"path\",null,{\"d\":\"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z\"}],[\"$\",\"path\",null,{\"d\":\"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z\"}]]}]}]}],\"Typescript First\"]}],[\"$\",\"p\",null,{\"children\":\"The codebase has been migrated to Typescript. While the previous version of the template was available in both Javascript and Typescript, I decided to reduce the maintenance burden and focus on Typescript. This also allows for better type checking and code completion in IDEs.\"}],[\"$\",\"p\",null,{\"children\":\"Typescript is also a perfect match with our new type-safe markdown processor - Contentlayer.\"}],[\"$\",\"h2\",null,{\"className\":\"content-header\",\"id\":\"contentlayer\",\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#contentlayer\",\"aria-hidden\":\"true\",\"tabIndex\":\"-1\",\"children\":[\"$\",\"span\",null,{\"className\":\"content-header-link\",\"children\":[\"$\",\"svg\",null,{\"className\":\"h-5 linkicon w-5\",\"fill\":\"currentColor\",\"viewBox\":\"0 0 20 20\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"children\":[[\"$\",\"path\",null,{\"d\":\"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z\"}],[\"$\",\"path\",null,{\"d\":\"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z\"}]]}]}]}],\"Contentlayer\"]}],[\"$\",\"p\",null,{\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://www.contentlayer.dev/\",\"children\":\"Contentlayer\"}],\" is a content SDK that validates and transforms your content into type-safe JSON data that you can easily import into your application. It makes working with local markdown or MDX files a breeze. This replaces \",[\"$\",\"code\",null,{\"children\":\"MDX-bundler\"}],\" and our own markdown processing workflow.\"]}],[\"$\",\"p\",null,{\"children\":\"First, a content source is defined, specifying the name of the document type, the source where it is located along with the frontmatter fields and any additional computed fields that should be generated as part of the process.\"}],[\"$\",\"div\",null,{\"className\":\"remark-code-title\",\"children\":\"contentlayer.config.ts\"}],[\"$\",\"$L18\",null,{\"className\":\"language-ts\",\"children\":[\"$\",\"code\",null,{\"className\":\"code-highlight language-ts\",\"children\":[[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"export\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"const\"}],\" Blog \",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\"=\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token function\",\"children\":\"defineDocumentType\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"(\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"(\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\")\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\"=\u003e\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"(\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[\" name\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"'Blog'\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[\" filePathPattern\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"'blog/**/*.mdx'\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[\" contentType\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"'mdx'\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[\" fields\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[\" title\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\" type\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"'string'\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\" required\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token boolean\",\"children\":\"true\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[\" date\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\" type\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"'date'\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\" required\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token boolean\",\"children\":\"true\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[\" tags\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\" type\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"'list'\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"of\"}],[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\" type\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"'string'\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token keyword\",\"children\":\"default\"}],[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"[\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"]\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[\" \",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\"...\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[\" computedFields\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[\" readingTime\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\" type\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"'json'\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token function function-variable\",\"children\":\"resolve\"}],[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"(\"}],\"doc\",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\")\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\"=\u003e\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token function\",\"children\":\"readingTime\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"(\"}],\"doc\",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\".\"}],\"body\",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\".\"}],\"raw\",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\")\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[\" slug\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[\" type\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"'string'\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[\" \",[\"$\",\"span\",null,{\"className\":\"token function function-variable\",\"children\":\"resolve\"}],[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"(\"}],\"doc\",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\")\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\"=\u003e\"}],\" doc\",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\".\"}],\"_raw\",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\".\"}],\"flattenedPath\",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\".\"}],[\"$\",\"span\",null,{\"className\":\"token function\",\"children\":\"replace\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"(\"}],[\"$\",\"span\",null,{\"className\":\"token regex\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token regex-delimiter\",\"children\":\"/\"}],[\"$\",\"span\",null,{\"className\":\"token language-regex regex-source\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token function anchor\",\"children\":\"^\"}],[\"$\",\"span\",null,{\"className\":\"token char-set class-name\",\"children\":\".\"}],[\"$\",\"span\",null,{\"className\":\"token number quantifier\",\"children\":\"+?\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation group\",\"children\":\"(\"}],[\"$\",\"span\",null,{\"className\":\"token escape\",\"children\":\"\\\\/\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation group\",\"children\":\")\"}]]}],[\"$\",\"span\",null,{\"className\":\"token regex-delimiter\",\"children\":\"/\"}]]}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"''\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\")\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[\" \",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\"...\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\")\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\")\"}],\"\\n\"]}]]}]}],[\"$\",\"p\",null,{\"children\":\"Contentlayer then processes the MDX files with our desired markdown remark or rehype plugins, validates the schema, generate type definitions and output json files that can be easily imported in our pages. Hot reloading comes out of the box, so edits to the markdown files will be reflected in the browser immediately!\"}],[\"$\",\"h2\",null,{\"className\":\"content-header\",\"id\":\"pliny\",\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#pliny\",\"aria-hidden\":\"true\",\"tabIndex\":\"-1\",\"children\":[\"$\",\"span\",null,{\"className\":\"content-header-link\",\"children\":[\"$\",\"svg\",null,{\"className\":\"h-5 linkicon w-5\",\"fill\":\"currentColor\",\"viewBox\":\"0 0 20 20\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"children\":[[\"$\",\"path\",null,{\"d\":\"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z\"}],[\"$\",\"path\",null,{\"d\":\"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z\"}]]}]}]}],\"Pliny\"]}],[\"$\",\"p\",null,{\"children\":\"A large reason for the popularity of the template was its customizability and integration with other services from analytics providers to commenting solutions. However, this means that a lot of boilerplate code has to be co-located within the template even if the user does not use the feature. Updates and bug fixes had to be copied manually to the user's codebase.\"}],[\"$\",\"p\",null,{\"children\":[\"To solve this, I have abstracted the logic to a separate repository - \",[\"$\",\"a\",null,{\"className\":\"break-words\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://github.com/timlrx/pliny\",\"children\":\"Pliny\"}],\". Pliny provides out of the box Next.js components to enhance static sites:\"]}],[\"$\",\"ul\",null,{\"children\":[[\"$\",\"li\",null,{\"children\":[\"Analytics\",[\"$\",\"ul\",null,{\"children\":[[\"$\",\"li\",null,{\"children\":\"Google Analytics\"}],[\"$\",\"li\",null,{\"children\":\"Plausible Analytics\"}],[\"$\",\"li\",null,{\"children\":\"Simple Analytics\"}],[\"$\",\"li\",null,{\"children\":\"Umami Analytics\"}],[\"$\",\"li\",null,{\"children\":\"Posthog\"}]]}]]}],[\"$\",\"li\",null,{\"children\":[\"Comments\",[\"$\",\"ul\",null,{\"children\":[[\"$\",\"li\",null,{\"children\":\"Disqus\"}],[\"$\",\"li\",null,{\"children\":\"Giscus\"}],[\"$\",\"li\",null,{\"children\":\"Utterances\"}]]}]]}],[\"$\",\"li\",null,{\"children\":[\"Newsletter (uses Next 13 API Routes)\",[\"$\",\"ul\",null,{\"children\":[[\"$\",\"li\",null,{\"children\":\"Buttondown\"}],[\"$\",\"li\",null,{\"children\":\"Convertkit\"}],[\"$\",\"li\",null,{\"children\":\"Email Octopus\"}],[\"$\",\"li\",null,{\"children\":\"Klaviyo\"}],[\"$\",\"li\",null,{\"children\":\"Mailchimp\"}],[\"$\",\"li\",null,{\"children\":\"Revue\"}]]}]]}],[\"$\",\"li\",null,{\"children\":[\"Command palette search with tailwind style sheet\",[\"$\",\"ul\",null,{\"children\":[[\"$\",\"li\",null,{\"children\":\"Algolia\"}],[\"$\",\"li\",null,{\"children\":\"Kbar (local search)\"}]]}]]}],[\"$\",\"li\",null,{\"children\":[\"UI utility components\",[\"$\",\"ul\",null,{\"children\":[[\"$\",\"li\",null,{\"children\":\"Bleed\"}],[\"$\",\"li\",null,{\"children\":\"Newsletter / Blog Newsletter\"}],[\"$\",\"li\",null,{\"children\":\"Pre / Code block\"}],[\"$\",\"li\",null,{\"children\":\"Table of Contents\"}]]}]]}]]}],[\"$\",\"p\",null,{\"children\":[\"Choose your preferred service by modifying \",[\"$\",\"code\",null,{\"children\":\"siteMetadata.js\"}],\" and changing the appropriate fields. For example to change from Umami Analytics to Plausible, we can change the following fields:\"]}],[\"$\",\"div\",null,{\"className\":\"remark-code-title\",\"children\":\"siteMetadata.js\"}],[\"$\",\"$L18\",null,{\"className\":\"language-js\",\"children\":[\"$\",\"code\",null,{\"className\":\"code-highlight language-diff-js\",\"children\":[[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token literal-property property\",\"children\":\"analytics\"}],[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line deleted\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\"-\"}],\" umamiAnalytics\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line deleted\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\"-\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token comment\",\"children\":\"// We use an env variable for this site to avoid other users cloning our analytics ID\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line deleted\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\"-\"}],\" umamiWebsiteId\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" process\",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\".\"}],[\"$\",\"span\",null,{\"className\":\"token property-access\",\"children\":\"env\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\".\"}],[\"$\",\"span\",null,{\"className\":\"token constant\",\"children\":\"NEXT_UMAMI_ID\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token comment\",\"children\":\"// e.g. 123e4567-e89b-12d3-a456-426614174000\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line deleted\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\"-\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line inserted\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\"+\"}],\" plausibleAnalytics\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"{\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line inserted\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\"+\"}],\" plausibleDataDomain\",[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\":\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token string\",\"children\":\"''\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token comment\",\"children\":\"// e.g. tailwind-nextjs-starter-blog.vercel.app\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line inserted\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token operator\",\"children\":\"+\"}],\" \",[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n\"]}],[\"$\",\"span\",null,{\"className\":\"code-line\",\"children\":[[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\"}\"}],[\"$\",\"span\",null,{\"className\":\"token punctuation\",\"children\":\",\"}],\"\\n\"]}]]}]}],[\"$\",\"p\",null,{\"children\":\"Changes in the configuration file gets propagated to the components automatically. No modification to the template is required.\"}],[\"$\",\"p\",null,{\"children\":[\"Under the hood, Pliny exports high level components such as \",[\"$\",\"code\",null,{\"children\":\"\u003cAnalytics analyticsConfig={analyticsConfig}/\u003e\"}],\" and \",[\"$\",\"code\",null,{\"children\":\"\u003cComments commentsConfig={commentsConfig}/\u003e\"}],\" which takes in a configuration object and renders the appropriate component. Since the layouts are defined on the server side, Next.js is able to use the configuration object to determine which component to render and send only the required component bundle to the client.\"]}],[\"$\",\"h2\",null,{\"className\":\"content-header\",\"id\":\"new-search-component\",\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#new-search-component\",\"aria-hidden\":\"true\",\"tabIndex\":\"-1\",\"children\":[\"$\",\"span\",null,{\"className\":\"content-header-link\",\"children\":[\"$\",\"svg\",null,{\"className\":\"h-5 linkicon w-5\",\"fill\":\"currentColor\",\"viewBox\":\"0 0 20 20\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"children\":[[\"$\",\"path\",null,{\"d\":\"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z\"}],[\"$\",\"path\",null,{\"d\":\"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z\"}]]}]}]}],\"New Search Component\"]}],[\"$\",\"p\",null,{\"children\":\"What's a blog in 2023 without a command palette search bar?\"}],[\"$\",\"p\",null,{\"children\":\"One of the most highly requested features have been added 🎉! The search component supports 2 search providers - Algolia and Kbar local search.\"}],[\"$\",\"h3\",null,{\"className\":\"content-header\",\"id\":\"algolia\",\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#algolia\",\"aria-hidden\":\"true\",\"tabIndex\":\"-1\",\"children\":[\"$\",\"span\",null,{\"className\":\"content-header-link\",\"children\":[\"$\",\"svg\",null,{\"className\":\"h-5 linkicon w-5\",\"fill\":\"currentColor\",\"viewBox\":\"0 0 20 20\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"children\":[[\"$\",\"path\",null,{\"d\":\"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z\"}],[\"$\",\"path\",null,{\"d\":\"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z\"}]]}]}]}],\"Algolia\"]}],[\"$\",\"p\",null,{\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://docsearch.algolia.com/\",\"children\":\"Algolia Docsearch\"}],\" is popular free service used across many documentation websites. It automatically scrapes the website that has is submitted for indexing and makes the search result available via a beautiful dialog modal. The pliny component is greatly inspired by the Docusaurus implementation and comes with a stylesheet that is compatible with the Tailwind CSS theme.\"]}],[\"$\",\"h3\",null,{\"className\":\"content-header\",\"id\":\"kbar\",\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#kbar\",\"aria-hidden\":\"true\",\"tabIndex\":\"-1\",\"children\":[\"$\",\"span\",null,{\"className\":\"content-header-link\",\"children\":[\"$\",\"svg\",null,{\"className\":\"h-5 linkicon w-5\",\"fill\":\"currentColor\",\"viewBox\":\"0 0 20 20\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"children\":[[\"$\",\"path\",null,{\"d\":\"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z\"}],[\"$\",\"path\",null,{\"d\":\"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z\"}]]}]}]}],\"Kbar\"]}],[\"$\",\"p\",null,{\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://github.com/timc1/kbar\",\"children\":\"Kbar\"}],\" is a fast, portable, and extensible cmd+k interface. The pliny implementation uses kbar to create a local search dialog box. The component loads a JSON file, default \",[\"$\",\"code\",null,{\"children\":\"search.json\"}],\", that was created in the contentlayer build process. Try pressing ⌘-k or ctrl-k to see the search bar in action!\"]}],[\"$\",\"h2\",null,{\"className\":\"content-header\",\"id\":\"styling-and-layout-updates\",\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#styling-and-layout-updates\",\"aria-hidden\":\"true\",\"tabIndex\":\"-1\",\"children\":[\"$\",\"span\",null,{\"className\":\"content-header-link\",\"children\":[\"$\",\"svg\",null,{\"className\":\"h-5 linkicon w-5\",\"fill\":\"currentColor\",\"viewBox\":\"0 0 20 20\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"children\":[[\"$\",\"path\",null,{\"d\":\"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z\"}],[\"$\",\"path\",null,{\"d\":\"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z\"}]]}]}]}],\"Styling and Layout Updates\"]}],[\"$\",\"h3\",null,{\"className\":\"content-header\",\"id\":\"theming\",\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#theming\",\"aria-hidden\":\"true\",\"tabIndex\":\"-1\",\"children\":[\"$\",\"span\",null,{\"className\":\"content-header-link\",\"children\":[\"$\",\"svg\",null,{\"className\":\"h-5 linkicon w-5\",\"fill\":\"currentColor\",\"viewBox\":\"0 0 20 20\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"children\":[[\"$\",\"path\",null,{\"d\":\"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z\"}],[\"$\",\"path\",null,{\"d\":\"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z\"}]]}]}]}],\"Theming\"]}],[\"$\",\"p\",null,{\"children\":[[\"$\",\"code\",null,{\"children\":\"tailwind.config.js\"}],\" has been updated to use tailwind typography defaults where possible and to use the built-in support for dark mode via the \",[\"$\",\"code\",null,{\"children\":\"prose-invert\"}],\" class. This replaces the previous \",[\"$\",\"code\",null,{\"children\":\"prose-dark\"}],\" class and configuration.\"]}],[\"$\",\"p\",null,{\"children\":[\"The primary theme color is updated from \",[\"$\",\"code\",null,{\"children\":\"teal\"}],\" to \",[\"$\",\"code\",null,{\"children\":\"pink\"}],\" and the primary gray theme from \",[\"$\",\"code\",null,{\"children\":\"neutral\"}],\" to \",[\"$\",\"code\",null,{\"children\":\"gray\"}],\".\"]}],[\"$\",\"p\",null,{\"children\":\"Inter is now replaced with Space Grotesk as the default font.\"}],[\"$\",\"h3\",null,{\"className\":\"content-header\",\"id\":\"new-layouts\",\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#new-layouts\",\"aria-hidden\":\"true\",\"tabIndex\":\"-1\",\"children\":[\"$\",\"span\",null,{\"className\":\"content-header-link\",\"children\":[\"$\",\"svg\",null,{\"className\":\"h-5 linkicon w-5\",\"fill\":\"currentColor\",\"viewBox\":\"0 0 20 20\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"children\":[[\"$\",\"path\",null,{\"d\":\"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z\"}],[\"$\",\"path\",null,{\"d\":\"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z\"}]]}]}]}],\"New Layouts\"]}],[\"$\",\"p\",null,{\"children\":[\"Layout components available in the \",[\"$\",\"code\",null,{\"children\":\"layouts\"}],\" directory, provide a simple way to customize the look and feel of the blog.\",[\"$\",\"sup\",null,{\"children\":[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#user-content-fn-2\",\"aria-describedby\":\"footnote-label\",\"data-footnote-ref\":true,\"id\":\"user-content-fnref-2\",\"children\":\"2\"}]}]]}],[\"$\",\"p\",null,{\"children\":\"The downside of building a popular template is that you start seeing multiple similar sites everywhere 😆. While users are encouraged to customized the layouts to their liking, having more layout options that are easily switchable promotes diversity and perhaps can be a good starting point for further customizations.\"}],[\"$\",\"p\",null,{\"children\":[\"In v2, I added a new post layout - \",[\"$\",\"code\",null,{\"children\":\"PostBanner\"}],\". It features a large banner image and a centered content container. Check out \\\"\",[\"$\",\"$L5\",null,{\"className\":\"break-words\",\"href\":\"/blog/pictures-of-canada\",\"children\":\"Pictures of Canada\"}],\"\\\" blog post which has been updated to use the new layout.\"]}],[\"$\",\"p\",null,{\"children\":[\"The default blog listing layout has also been updated to include a side bar with blog tags. The search bar in the previous layout has been replace with the new command palette search. To switch back to the old layout, simply change the pages that use the \",[\"$\",\"code\",null,{\"children\":\"ListLayoutWithTags\"}],\" component back to the original \",[\"$\",\"code\",null,{\"children\":\"ListLayout\"}],\".\"]}],[\"$\",\"h2\",null,{\"className\":\"content-header\",\"id\":\"migration-recommendations\",\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#migration-recommendations\",\"aria-hidden\":\"true\",\"tabIndex\":\"-1\",\"children\":[\"$\",\"span\",null,{\"className\":\"content-header-link\",\"children\":[\"$\",\"svg\",null,{\"className\":\"h-5 linkicon w-5\",\"fill\":\"currentColor\",\"viewBox\":\"0 0 20 20\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"children\":[[\"$\",\"path\",null,{\"d\":\"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z\"}],[\"$\",\"path\",null,{\"d\":\"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z\"}]]}]}]}],\"Migration Recommendations\"]}],[\"$\",\"p\",null,{\"children\":\"Due to the large changes in directory structure, setup and tooling, I recommend starting from a fresh template and copying existing content, followed by incrementally migrating changes over to the new template.\"}],[\"$\",\"p\",null,{\"children\":[\"Styling changes should be relatively minor and can be copied over from the old \",[\"$\",\"code\",null,{\"children\":\"tailwind.config.js\"}],\" to the new one. If copying over, you might need to add back the \",[\"$\",\"code\",null,{\"children\":\"prose-dark\"}],\" class to components that opt into tailwind typography styling. Do modify the font import in the root layout component to use the desired font of choice.\"]}],[\"$\",\"p\",null,{\"children\":[\"Changes to the MDX processing pipeline and schema can be easily ported to the new Contentlayer setup. If there are changes to the frontmatter fields, you can modify the document type in \",[\"$\",\"code\",null,{\"children\":\"contentlayer.config.ts\"}],\" to include the new fields. Custom plugins can be added to the \",[\"$\",\"code\",null,{\"children\":\"remarkPlugins\"}],\" and \",[\"$\",\"code\",null,{\"children\":\"rehypePlugins\"}],\" properties in the \",[\"$\",\"code\",null,{\"children\":\"makeSource\"}],\" export of \",[\"$\",\"code\",null,{\"children\":\"contentlayer.config.ts\"}],\".\"]}],[\"$\",\"p\",null,{\"children\":[\"Markdown layouts are no longer sourced automatically from the \",[\"$\",\"code\",null,{\"children\":\"layouts\"}],\" directory. Instead, they have to be specified in the \",[\"$\",\"code\",null,{\"children\":\"layouts\"}],\" object defined in \",[\"$\",\"code\",null,{\"children\":\"blog/[...slug]/page.tsx\"}],\".\",[\"$\",\"sup\",null,{\"children\":[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#user-content-fn-3\",\"aria-describedby\":\"footnote-label\",\"data-footnote-ref\":true,\"id\":\"user-content-fnref-3\",\"children\":\"3\"}]}]]}],[\"$\",\"p\",null,{\"children\":[\"To port over larger components or pages, I recommend first specificing it as a client component by using the \",[\"$\",\"code\",null,{\"children\":\"\\\"use client\\\"\"}],\" directive. Once it renders correctly, you can split the interactive components (parts that rely on \",[\"$\",\"code\",null,{\"children\":\"use\"}],\" hooks) as a client component and keep the remaining code as a server component. Consult the comprehensive Next.js \",[\"$\",\"a\",null,{\"className\":\"break-words\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://nextjs.org/docs/app/building-your-application/upgrading/app-router-migration#migrating-from-pages-to-app\",\"children\":\"migration guide\"}],\" for more details.\"]}],[\"$\",\"h2\",null,{\"className\":\"content-header\",\"id\":\"conclusion\",\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#conclusion\",\"aria-hidden\":\"true\",\"tabIndex\":\"-1\",\"children\":[\"$\",\"span\",null,{\"className\":\"content-header-link\",\"children\":[\"$\",\"svg\",null,{\"className\":\"h-5 linkicon w-5\",\"fill\":\"currentColor\",\"viewBox\":\"0 0 20 20\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"children\":[[\"$\",\"path\",null,{\"d\":\"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z\"}],[\"$\",\"path\",null,{\"d\":\"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z\"}]]}]}]}],\"Conclusion\"]}],[\"$\",\"p\",null,{\"children\":[\"I hope you enjoy the new features and improvements in V2. If you have any feedback or suggestions, feel free to open an issue or reach out to me on \",[\"$\",\"a\",null,{\"className\":\"break-words\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://twitter.com/timlrx\",\"children\":\"Twitter\"}],\".\"]}],[\"$\",\"h2\",null,{\"className\":\"content-header\",\"id\":\"support\",\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#support\",\"aria-hidden\":\"true\",\"tabIndex\":\"-1\",\"children\":[\"$\",\"span\",null,{\"className\":\"content-header-link\",\"children\":[\"$\",\"svg\",null,{\"className\":\"h-5 linkicon w-5\",\"fill\":\"currentColor\",\"viewBox\":\"0 0 20 20\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"children\":[[\"$\",\"path\",null,{\"d\":\"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z\"}],[\"$\",\"path\",null,{\"d\":\"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z\"}]]}]}]}],\"Support\"]}],[\"$\",\"p\",null,{\"children\":[\"Using the template? Support this effort by giving a star on GitHub, sharing your own blog and giving a shoutout on Twitter or be a project \",[\"$\",\"a\",null,{\"className\":\"break-words\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://github.com/sponsors/timlrx\",\"children\":\"sponsor\"}],\".\"]}],[\"$\",\"h2\",null,{\"className\":\"content-header\",\"id\":\"licence\",\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#licence\",\"aria-hidden\":\"true\",\"tabIndex\":\"-1\",\"children\":[\"$\",\"span\",null,{\"className\":\"content-header-link\",\"children\":[\"$\",\"svg\",null,{\"className\":\"h-5 linkicon w-5\",\"fill\":\"currentColor\",\"viewBox\":\"0 0 20 20\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"children\":[[\"$\",\"path\",null,{\"d\":\"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z\"}],[\"$\",\"path\",null,{\"d\":\"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z\"}]]}]}]}],\"Licence\"]}],[\"$\",\"p\",null,{\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://github.com/timlrx/tailwind-nextjs-starter-blog/blob/main/LICENSE\",\"children\":\"MIT\"}],\" © \",[\"$\",\"a\",null,{\"className\":\"break-words\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://www.timrlx.com\",\"children\":\"Timothy Lin\"}]]}],[\"$\",\"section\",null,{\"className\":\"footnotes\",\"data-footnotes\":true,\"children\":[[\"$\",\"h2\",null,{\"className\":\"content-header\",\"id\":\"footnote-label\",\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"href\":\"#footnote-label\",\"aria-hidden\":\"true\",\"tabIndex\":\"-1\",\"children\":[\"$\",\"span\",null,{\"className\":\"content-header-link\",\"children\":[\"$\",\"svg\",null,{\"className\":\"h-5 linkicon w-5\",\"fill\":\"currentColor\",\"viewBox\":\"0 0 20 20\",\"xmlns\":\"http://www.w3.org/2000/svg\",\"children\":[[\"$\",\"path\",null,{\"d\":\"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z\"}],[\"$\",\"path\",null,{\"d\":\"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z\"}]]}]}]}],\"Footnotes\"]}],[\"$\",\"ol\",null,{\"children\":[[\"$\",\"li\",null,{\"id\":\"user-content-fn-1\",\"children\":[\"$\",\"p\",null,{\"children\":[\"The previous version injects Preact into the production build. However, this is no longer possible as it does not support React Server Components. While overall bundle size has increased to about 85kB, most of the content can be pre-rendered on the server side, resulting in a low first contentful paint and time to interactive. Using React throughtout also leads to more consistent behavior with external libraries and components. \",[\"$\",\"a\",null,{\"className\":\"data-footnote-backref\",\"href\":\"#user-content-fnref-1\",\"aria-label\":\"Back to reference 1\",\"data-footnote-backref\":\"\",\"children\":\"↩\"}]]}]}],[\"$\",\"li\",null,{\"id\":\"user-content-fn-2\",\"children\":[\"$\",\"p\",null,{\"children\":[\"This is different from Next.js App Directory layouts and are best thought of as reusable React containers. \",[\"$\",\"a\",null,{\"className\":\"data-footnote-backref\",\"href\":\"#user-content-fnref-2\",\"aria-label\":\"Back to reference 2\",\"data-footnote-backref\":\"\",\"children\":\"↩\"}]]}]}],[\"$\",\"li\",null,{\"id\":\"user-content-fn-3\",\"children\":[\"$\",\"p\",null,{\"children\":[\"This takes advantage of Server Components by making it simple to specify the layout of choice in the markdown file and match against the \",[\"$\",\"code\",null,{\"children\":\"layouts\"}],\" object which is then used to render the appropriate layout component. \",[\"$\",\"a\",null,{\"className\":\"data-footnote-backref\",\"href\":\"#user-content-fnref-3\",\"aria-label\":\"Back to reference 3\",\"data-footnote-backref\":\"\",\"children\":\"↩\"}]]}]}]]}]]}]]}],[\"$\",\"div\",null,{\"className\":\"pt-6 pb-6 text-sm text-gray-700 dark:text-gray-300\",\"children\":[[\"$\",\"a\",null,{\"className\":\"break-words\",\"target\":\"_blank\",\"rel\":\"nofollow\",\"href\":\"https://mobile.twitter.com/search?q=https%3A%2F%2Ftailwind-nextjs-starter-blog.vercel.app%2Fblog%2Frelease-of-tailwind-nextjs-starter-blog-v2.0\",\"children\":\"Discuss on Twitter\"}],\" • \",[\"$\",\"a\",null,{\"className\":\"break-words\",\"target\":\"_blank\",\"rel\":\"noopener noreferrer\",\"href\":\"https://github.com/timlrx/tailwind-nextjs-starter-blog/blob/main/data/blog/release-of-tailwind-nextjs-starter-blog-v2.0.mdx\",\"children\":\"View on GitHub\"}]]}],[\"$\",\"div\",null,{\"className\":\"pt-6 pb-6 text-center text-gray-700 dark:text-gray-300\",\"id\":\"comment\",\"children\":[\"$\",\"$L19\",null,{\"slug\":\"release-of-tailwind-nextjs-starter-blog-v2.0\"}]}]]}],[\"$\",\"footer\",null,{\"children\":[[\"$\",\"div\",null,{\"className\":\"divide-gray-200 text-sm leading-5 font-medium xl:col-start-1 xl:row-start-2 xl:divide-y dark:divide-gray-700\",\"children\":[[\"$\",\"div\",null,{\"className\":\"py-4 xl:py-8\",\"children\":[[\"$\",\"h2\",null,{\"className\":\"text-xs tracking-wide text-gray-500 uppercase dark:text-gray-400\",\"children\":\"Tags\"}],[\"$\",\"div\",null,{\"className\":\"flex flex-wrap\",\"children\":[[\"$\",\"$L5\",\"next-js\",{\"href\":\"/tags/next-js\",\"className\":\"text-primary-500 hover:text-primary-600 dark:hover:text-primary-400 mr-3 text-sm font-medium uppercase\",\"children\":\"next-js\"}],[\"$\",\"$L5\",\"tailwind\",{\"href\":\"/tags/tailwind\",\"className\":\"text-primary-500 hover:text-primary-600 dark:hover:text-primary-400 mr-3 text-sm font-medium uppercase\",\"children\":\"tailwind\"}],[\"$\",\"$L5\",\"guide\",{\"href\":\"/tags/guide\",\"className\":\"text-primary-500 hover:text-primary-600 dark:hover:text-primary-400 mr-3 text-sm font-medium uppercase\",\"children\":\"guide\"}],[\"$\",\"$L5\",\"feature\",{\"href\":\"/tags/feature\",\"className\":\"text-primary-500 hover:text-primary-600 dark:hover:text-primary-400 mr-3 text-sm font-medium uppercase\",\"children\":\"feature\"}]]}]]}],[\"$\",\"div\",null,{\"className\":\"flex justify-between py-4 xl:block xl:space-y-8 xl:py-8\",\"children\":[[\"$\",\"div\",null,{\"children\":[[\"$\",\"h2\",null,{\"className\":\"text-xs tracking-wide text-gray-500 uppercase dark:text-gray-400\",\"children\":\"Previous Article\"}],[\"$\",\"div\",null,{\"className\":\"text-primary-500 hover:text-primary-600 dark:hover:text-primary-400\",\"children\":[\"$\",\"$L5\",null,{\"className\":\"break-words\",\"href\":\"/blog/new-features-in-v1\",\"children\":\"New features in v1\"}]}]]}],\"$undefined\"]}]]}],[\"$\",\"div\",null,{\"className\":\"pt-4 xl:pt-8\",\"children\":[\"$\",\"$L5\",null,{\"className\":\"text-primary-500 hover:text-primary-600 dark:hover:text-primary-400\",\"href\":\"/blog\",\"aria-label\":\"Back to the blog\",\"children\":\"← Back to the blog\"}]}]]}]]}]]}]}]]}]]\n"])</script><script>self.__next_f.push([1,"12:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\nf:null\n"])</script><script>self.__next_f.push([1,"10:null\n"])</script><script>self.__next_f.push([1,"14:[[\"$\",\"title\",\"0\",{\"children\":\"Release of Tailwind Nextjs Starter Blog v2.0 | Next.js Starter Blog\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Release of Tailwind Nextjs Starter Blog template v2.0, refactored with Nextjs App directory and React Server Components setup.Discover the new features and how to migrate from V1.\"}],[\"$\",\"meta\",\"2\",{\"name\":\"robots\",\"content\":\"index, follow\"}],[\"$\",\"meta\",\"3\",{\"name\":\"googlebot\",\"content\":\"index, follow, max-video-preview:-1, max-image-preview:large, max-snippet:-1\"}],[\"$\",\"link\",\"4\",{\"rel\":\"canonical\",\"href\":\"https://tailwind-nextjs-starter-blog.vercel.app/blog/release-of-tailwind-nextjs-starter-blog-v2.0\"}],[\"$\",\"link\",\"5\",{\"rel\":\"alternate\",\"type\":\"application/rss+xml\",\"href\":\"https://tailwind-nextjs-starter-blog.vercel.app/feed.xml\"}],[\"$\",\"meta\",\"6\",{\"property\":\"og:title\",\"content\":\"Release of Tailwind Nextjs Starter Blog v2.0\"}],[\"$\",\"meta\",\"7\",{\"property\":\"og:description\",\"content\":\"Release of Tailwind Nextjs Starter Blog template v2.0, refactored with Nextjs App directory and React Server Components setup.Discover the new features and how to migrate from V1.\"}],[\"$\",\"meta\",\"8\",{\"property\":\"og:url\",\"content\":\"https://tailwind-nextjs-starter-blog.vercel.app/blog/release-of-tailwind-nextjs-starter-blog-v2.0\"}],[\"$\",\"meta\",\"9\",{\"property\":\"og:site_name\",\"content\":\"Next.js Starter Blog\"}],[\"$\",\"meta\",\"10\",{\"property\":\"og:locale\",\"content\":\"en_US\"}],[\"$\",\"meta\",\"11\",{\"property\":\"og:image\",\"content\":\"https://tailwind-nextjs-starter-blog.vercel.app/static/images/twitter-card.png\"}],[\"$\",\"meta\",\"12\",{\"property\":\"og:type\",\"content\":\"article\"}],[\"$\",\"meta\",\"13\",{\"property\":\"article:published_time\",\"content\":\"2023-08-05T00:00:00.000Z\"}],[\"$\",\"meta\",\"14\",{\"property\":\"article:modified_time\",\"content\":\"2023-08-05T00:00:00.000Z\"}],[\"$\",\"meta\",\"15\",{\"property\":\"article:author\",\"content\":\"Tails Azimuth\"}],[\"$\",\"meta\",\"16\",{\"name\":\"twitter:card\",\"content\":\"summary_large_image\"}],[\"$\",\"meta\",\"17\",{\"name\":\"twitter:title\",\"content\":\"Release of Tailwind Nextjs Starter Blog v2.0\"}],[\"$\",\"meta\",\"18\",{\"name\":\"twitter:description\",\"content\":\"Release of Tailwind Nextjs Starter Blog template v2.0, refactored with Nextjs App directory and React Server Components setup.Discover the new features and how to migrate from V1.\"}],[\"$\",\"meta\",\"19\",{\"name\":\"twitter:image\",\"content\":\"https://tailwind-nextjs-starter-blog.vercel.app/static/images/twitter-card.png\"}]]\n"])</script></body></html> |