Use MDX to automatically generate pages for each tab used in Astro

With the release of Astro 2.0 , the Content Collections API became available.
This makes it very easy to query Markdown/MDX in a type-safe way (and more, be sure to read the blog post I linked above).
For my blog it was really easy to set up, I just had to move my blog from to /pages/blogand /content/blogadd a /content/config.tsfile.
This /contentfolder is a reserved folder for the repository.
In /content/config.tsthe file, you define the schema for the collection you want to create.
Currently I only have 1 collection which is my blog.
So I created my schema as follows:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">z</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">defineCollection</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">astro:content</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span>

<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">blog</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">defineCollection</span><span style="color:var(--syntax-text-color)">({</span>
  <span style="color:var(--syntax-name-color)">schema</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">z</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">object</span><span style="color:var(--syntax-text-color)">({</span>
    <span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">z</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">(),</span>
    <span style="color:var(--syntax-name-color)">layout</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">z</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">(),</span>
    <span style="color:var(--syntax-name-color)">tags</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">z</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">array</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">z</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">()),</span>
    <span style="color:var(--syntax-name-color)">date</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">z</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">(),</span>
    <span style="color:var(--syntax-name-color)">image</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">z</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-declaration-color)">string</span><span style="color:var(--syntax-text-color)">().</span><span style="color:var(--syntax-name-color)">optional</span><span style="color:var(--syntax-text-color)">(),</span>
  <span style="color:var(--syntax-text-color)">}),</span>
<span style="color:var(--syntax-text-color)">});</span>

<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">collections</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-name-color)">blog</span><span style="color:var(--syntax-text-color)">,</span>
<span style="color:var(--syntax-text-color)">};</span>
</code></span></span>

As you can see, tagsis a required attribute for all my blogs, luckily I have tagged every blog post from the beginning.
In my MDX, the tags are defined at the top of the file as follows:

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code>---
tags: ['javascript', 'edge', 'vercel'];
---
</code></span></span>

.astroNow that I have the Blogs collection defined in my config, I can start using the data from my files.
I want to create a separate page for each unique tag used in the blog.
To make this possible, I just added a file /pages/blog/tags/[...slug].astro(it's a dynamic route ).
In this file, I want to fetch all blogs from my collection, find unique tags, and generate a URL for each tag.
The getStaticPaths()function will return the URL (hence the line) that I want to pre-render during build export const prerender = true;.

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-error-color)">---</span>
<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">prerender</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">true</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">slug</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">Astro</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">params</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">import</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">getCollection</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-declaration-color)">from</span> <span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">astro:content</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">;</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">blogs</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">await</span> <span style="color:var(--syntax-name-color)">getCollection</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">blog</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">tags</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">blogs</span>
  <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">map</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">blog</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">blog</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">data</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">tags</span><span style="color:var(--syntax-text-color)">)</span>
  <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">flat</span><span style="color:var(--syntax-text-color)">()</span>
  <span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">reduce</span><span style="color:var(--syntax-error-color)"><</span><span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">key</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">string</span><span style="color:var(--syntax-text-color)">]:</span> <span style="color:var(--syntax-name-color)">number</span> <span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-error-color)">></span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">result</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">c</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
    <span style="color:var(--syntax-declaration-color)">var</span> <span style="color:var(--syntax-name-color)">count</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">result</span><span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">c</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">||</span> <span style="color:var(--syntax-literal-color)">0</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-name-color)">result</span><span style="color:var(--syntax-text-color)">[</span><span style="color:var(--syntax-name-color)">c</span><span style="color:var(--syntax-text-color)">]</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-name-color)">count</span> <span style="color:var(--syntax-error-color)">+</span> <span style="color:var(--syntax-literal-color)">1</span><span style="color:var(--syntax-text-color)">;</span>
    <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">result</span><span style="color:var(--syntax-text-color)">;</span>
  <span style="color:var(--syntax-text-color)">},</span> <span style="color:var(--syntax-text-color)">{});</span>
<span style="color:var(--syntax-declaration-color)">export</span> <span style="color:var(--syntax-declaration-color)">async</span> <span style="color:var(--syntax-declaration-color)">function</span> <span style="color:var(--syntax-name-color)">getStaticPaths</span><span style="color:var(--syntax-text-color)">()</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">blogs</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">await</span> <span style="color:var(--syntax-name-color)">getCollection</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">blog</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">);</span>
  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">[...</span><span style="color:var(--syntax-declaration-color)">new</span> <span style="color:var(--syntax-text-color)">Set</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">blogs</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">map</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">blog</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">blog</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">data</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">tags</span><span style="color:var(--syntax-text-color)">).</span><span style="color:var(--syntax-name-color)">flat</span><span style="color:var(--syntax-text-color)">())].</span><span style="color:var(--syntax-name-color)">map</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">tag</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">({</span>
    <span style="color:var(--syntax-name-color)">params</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">slug</span><span style="color:var(--syntax-text-color)">:</span> <span style="color:var(--syntax-name-color)">tag</span> <span style="color:var(--syntax-text-color)">},</span>
  <span style="color:var(--syntax-text-color)">}));</span>
<span style="color:var(--syntax-text-color)">}</span>
<span style="color:var(--syntax-declaration-color)">if</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-error-color)">!</span><span style="color:var(--syntax-name-color)">slug</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">Astro</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">redirect</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">/404</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">}</span>
<span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-name-color)">allBlogPostsWithTag</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">await</span> <span style="color:var(--syntax-name-color)">getCollection</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">blog</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">blog</span> <span style="color:var(--syntax-error-color)">=></span>
  <span style="color:var(--syntax-name-color)">blog</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">data</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">tags</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">some</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">tag</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-name-color)">tag</span> <span style="color:var(--syntax-error-color)">===</span> <span style="color:var(--syntax-name-color)">slug</span><span style="color:var(--syntax-text-color)">)</span>
<span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-declaration-color)">if</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">allBlogPostsWithTag</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">length</span> <span style="color:var(--syntax-error-color)">===</span> <span style="color:var(--syntax-literal-color)">0</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-text-color)">{</span>
  <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-name-color)">Astro</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">redirect</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-string-color)">/404</span><span style="color:var(--syntax-string-color)">'</span><span style="color:var(--syntax-text-color)">);</span>
<span style="color:var(--syntax-text-color)">}</span>
<span style="color:var(--syntax-error-color)">---</span>
</code></span></span>

I used a .reduce()function to count the number of blogs available per tab, so I could display it at the top of the tab.
The API provided by Content Collections are functions getCollection()that allow me to get all the blogs in my collection blogs. As you can see, it is also possible to pass a filter function to this function, I used to get only the blogs that contained the tag on line 22 for which the current page was generated. The actual rendering is simple, I can now
use allBlogPostsWithTagvariables and render blog posts.
Since slugit matches the generated tags for this page, I can find the code in my title/description/..

<span style="color:var(--syntax-text-color)"><span style="color:var(--syntax-text-color)"><code><span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-name-color)">Layout</span>
  <span style="color:var(--syntax-name-color)">title</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-string-color)">`The Thomas Ledoux blog | </span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">slug</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-string-color)">}</span>
  <span style="color:var(--syntax-name-color)">description</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-string-color)">`All blogs about </span><span style="color:var(--syntax-text-color)">${</span><span style="color:var(--syntax-name-color)">slug</span><span style="color:var(--syntax-text-color)">}</span><span style="color:var(--syntax-string-color)">`</span><span style="color:var(--syntax-string-color)">}</span>
<span style="color:var(--syntax-text-color)">></span>
  <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">section</span><span style="color:var(--syntax-text-color)">></span>
    <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">h1</span> <span style="color:var(--syntax-name-color)">class</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"text-center text-2xl font-bold mb-6"</span><span style="color:var(--syntax-text-color)">></span>
      All blogs about <span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">slug</span><span style="color:var(--syntax-string-color)">}</span>
    <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">h1</span><span style="color:var(--syntax-text-color)">></span>
    <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-name-color)">Tags</span> <span style="color:var(--syntax-name-color)">tags</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">tags</span><span style="color:var(--syntax-string-color)">}</span> <span style="color:var(--syntax-name-color)">slug</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">slug</span><span style="color:var(--syntax-string-color)">}</span> <span style="color:var(--syntax-text-color)">/></span>
    <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-error-color)">div</span>
      <span style="color:var(--syntax-name-color)">class</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">"grid sm:grid-cols-2 lg:grid-cols-3 gap-6 items-center auto-rows-min mt-4"</span>
    <span style="color:var(--syntax-text-color)">></span>
      <span style="color:var(--syntax-string-color)">{</span>
        <span style="color:var(--syntax-name-color)">allBlogPostsWithTag</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">map</span><span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-declaration-color)">async</span> <span style="color:var(--syntax-text-color)">(</span><span style="color:var(--syntax-name-color)">post</span><span style="color:var(--syntax-text-color)">,</span> <span style="color:var(--syntax-name-color)">i</span><span style="color:var(--syntax-text-color)">)</span> <span style="color:var(--syntax-error-color)">=></span> <span style="color:var(--syntax-text-color)">{</span>
          <span style="color:var(--syntax-declaration-color)">const</span> <span style="color:var(--syntax-text-color)">{</span> <span style="color:var(--syntax-name-color)">remarkPluginFrontmatter</span> <span style="color:var(--syntax-text-color)">}</span> <span style="color:var(--syntax-error-color)">=</span> <span style="color:var(--syntax-declaration-color)">await</span> <span style="color:var(--syntax-name-color)">post</span><span style="color:var(--syntax-text-color)">.</span><span style="color:var(--syntax-name-color)">render</span><span style="color:var(--syntax-text-color)">();</span>

          <span style="color:var(--syntax-declaration-color)">return</span> <span style="color:var(--syntax-text-color)">(</span>
            <span style="color:var(--syntax-text-color)"><</span><span style="color:var(--syntax-name-color)">PostPreview</span>
              <span style="color:var(--syntax-name-color)">minutesRead</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">remarkPluginFrontmatter</span><span style="color:var(--syntax-text-color)">?.</span><span style="color:var(--syntax-name-color)">minutesRead</span><span style="color:var(--syntax-string-color)">}</span>
              <span style="color:var(--syntax-name-color)">post</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">post</span><span style="color:var(--syntax-string-color)">}</span>
              <span style="color:var(--syntax-name-color)">index</span><span style="color:var(--syntax-text-color)">=</span><span style="color:var(--syntax-string-color)">{</span><span style="color:var(--syntax-name-color)">i</span><span style="color:var(--syntax-string-color)">}</span>
            <span style="color:var(--syntax-text-color)">/></span>
          <span style="color:var(--syntax-text-color)">);</span>
        <span style="color:var(--syntax-text-color)">})</span>
      <span style="color:var(--syntax-string-color)">}</span>
    <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">div</span><span style="color:var(--syntax-text-color)">></span>
  <span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-error-color)">section</span><span style="color:var(--syntax-text-color)">></span>
<span style="color:var(--syntax-text-color)"></</span><span style="color:var(--syntax-name-color)">Layout</span><span style="color:var(--syntax-text-color)">></span>
</code></span></span>

The result of this markup page will look like this:

I must say I really like writing Markdown/MDX with Astro, especially when they make it so easy! Source code can

be found on Github. An example of a tab page can be found here  .

 

Guess you like

Origin blog.csdn.net/jascl/article/details/131304350