Astro recently announced support for MDX and Vite 3.0 in their release of Astro 1.0, two important integrations that put them at the top of their game for building static sites. Vite is an upgrade to their internal engine, providing fast builds and a better development experience, and MDX for extending Markdown capabilities that cater to interactive, text-based content.
In this article, you’ll learn how to build a blog using Astro and MDX. We’ll cover:
- What is Astro?
- What is Vite?
- What is MDX?
- Astro app setup
- Writing MDX code into our Astro app
- Creating a blog with MDX and Astro
Prerequisites
- Working knowledge of JavaScript and/or JavaScript frameworks
- Knowledge of Markdown syntax
What is Astro?
Astro is a powerful static site generator that lets you create highly performant websites using the JavaScript frameworks you know and love. Astro is static-first, with progressive enhancement, meaning that, by default, it ships zero JavaScript to the browser until required.
What is Vite?
Vite is a next-gen JavaScript build tool that simplifies how frontend web applications are built and developed. Other popular JavaScript build tools, such as Webpack and Rollup, solve the problem of asset bundling and serving code locally during development.
However, Vite approaches the problem differently by leveraging native browser ES modules to load JavaScript code instantly in the browser. This way, no matter the number of dependencies or code added to your project, you still get instant builds.
What is MDX?
MDX is a tool that lets you extend the capabilities of Markdown by leveraging the power of JSX. You can import and use interactive components such as charts, alerts, and more. You can even create reusable MDX components. MDX opens up new possibilities for creating written content.
Astro app setup
Create a project using the Astro CLI by first running the following command in your terminal:
npm create astro@latest
Follow the step-by-step terminal prompts to finish the setup according to your preferences.
Once that’s done, cd
into the project directory and run the command below to start an Astro dev server at http://localhost:3000
:
npm run dev
Open your browser and navigate to http://localhost:3000
. You should see the following on your screen:
Now, install MDX using the command below, depending on your package manager:
# Using NPM npx astro add mdx # Using Yarn yarn astro add mdx # Using PNPM pnpm astro add mdx
Accept all the prompts to complete the integration within your Astro application and restart your development server.
By default, Astro has support for Markdown files and can build routes/pages from Markdown files (.md
) in the src/pages
folder. But by adding the MDX integration, you can use .mdx
files in the folder to generate pages in your app.
Writing MDX code into our Astro app
MDX doesn’t have any special syntax because it is just a combination of Markdown and JSX. You can write JSX, Markdown, JavaScript expressions, and import and export statements.
To get a feel for what writing MDX code is like, create a file in your project’s src/pages
directory, give it whatever name you want, and end the file extension with .mdx
. Then paste in the following block of code:
export const continents = ['Africa', 'South America', 'Asia', 'Europe'] I think 2 + 2 is {2+2} # Math operations Test in MDX, Astro and Vite ### There are 7 continents in the world, below are a few of them listed: <ul> {continents.map((continent) => ( <li>{continent}</li> ))} </ul> ## HTMl-JSX-Markdown Mix <div> > Some *notable* things in a block quote! </div>
When you navigate to the name of your page, you should see the following output in your browser:
Creating a blog with MDX and Astro
In this tutorial, we’re building a blog using MDX and Astro.
While creating the blog, you’ll:
- Use MDX to create text-based content
- Create a layout for the
blog
andpost
pages - Add interactive components to MDX
- Use
frontmatter
in Astro to pass data to Astro layouts - Fetch all Markdown files locally using the
Astro.glob()
method for display
Creating the blog post layout
Navigate to the src/layouts
folder and create a new layout called PostLayout.astro
and paste in the following code:
--- import BaseHead from "../components/BaseHead.astro"; import Header from "../components/Header.astro"; import Footer from "../components/Footer.astro"; const { frontmatter: { title, description, pubDate, image, author }, } = Astro.props; --- <html lang="en"> <head> <BaseHead title={title} description={description} /> <style> .title { font-size: 2em; margin: 0.25em 0 0; } hr { border-top: 1px solid #ddd; margin: 1rem 0; } </style> </head> <body> <Header /> <main> <article> <div class="article-head"> <h1 class="title">{title}</h1> <em>Written by: {author}</em> </div> <div class="article-body"> {image && <img width={720} height={360} src={image} alt="" />} Published on: {pubDate && <time>{pubDate}</time>} <hr /> <slot /> </div> </article> </main> <div class="footer-container"> <Footer /> </div> <style> html { min-height: 100vh; height: 100%; } body { height: 100%; } time { display: inline-block; margin-top: 10px; } </style> </body> </html>
Let’s analyze the contents of the code block above.
First, there are a few component imports at the top of the file that don’t exist yet. We’ll get to create them soon:
- The
BaseHead
component is going to contain all the HTML<head></head>
properties for the layout - The
Header
component will contain the navigation links at the top of the page for going between routes - The
Footer
component will contain the footer for the layout - The
<slot/>
component on line 37 is used to inject the rest of the text content from the Markdown file into the layout
Astro provides Markdown and MDX pages with a frontmatter
property that can be used to define “metadata” that can describe the file.
In the PostLayout.astro
file, the frontmatter
prop passed by each Markdown/MDX file can be accessed to extract the metadata defined in the file. On line 8, the frontmatter
property provided by Astro.props
is then destructured to expose the variables for the template.
Now, let’s add the code for the missing imported components.
For each of the code blocks below, create the corresponding file in the components
folder and paste in the code from the corresponding code block:
For Header.astro
:
<header> <nav> <a href="/">Home</a> <a href="/blog">Blog</a> </nav> </header> <style> header { margin: 2em 4em 2em; } h2 { margin: 0.5em 0; } </style>
For Footer.astro
:
--- const today = new Date(); --- <footer> © {today.getFullYear()} YOUR NAME HERE. All rights reserved. </footer> <style> footer { padding: 25px; text-align: center; } </style>
And finally, for BaseHead.astro
:
--- // Import the global.css file here so that it is included on // all pages through the use of the <BaseHead /> component. import "../styles/global.css"; const { title, description } = Astro.props; --- <!-- Global Metadata --> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width,initial-scale=1" /> <link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <meta name="generator" content={Astro.generator} /> <!-- Primary Meta Tags --> <title>{title}</title> <meta name="title" content={title} /> <meta name="description" content={description} />
There’s also a missing import: ../styles/global.css
. Let’s quickly create the file and add styles to it.
In the src
folder, create a styles
folder with a file named global.css
and add the following code:
/* The CSS in this style tag is based off of Bear Blog's default CSS. https://github.com/HermanMartinus/bearblog/blob/297026a877bc2ab2b3bdfbd6b9f7961c350917dd/templates/styles/blog/default.css License MIT: https://github.com/HermanMartinus/bearblog/blob/master/LICENSE.md */ body { font-family: Verdana, sans-serif; margin: auto; padding: 20px; text-align: left; background-color: #fff; word-wrap: break-word; overflow-wrap: break-word; line-height: 1.5; color: #444; width: 100%; } .article-head { margin-left: 4em; margin-bottom: 50px; } .article-body { max-width: 65ch; margin: 0 auto; } h1, h2, h3, h4, h5, h6, strong, b { color: #222; } a { color: #222; } nav a { margin-right: 10px; } textarea { width: 100%; font-size: 16px; } input { font-size: 16px; } content { line-height: 1.6; } table { width: 100%; } img { max-width: 100%; height: auto; } code { padding: 2px 5px; background-color: #f2f2f2; } pre { padding: 1rem; } pre > code { all: unset; } blockquote { border: 1px solid #999; color: #222; padding: 2px 0px 2px 20px; margin: 0px; font-style: italic; }
Creating a Markdown blog post
To test the layout, create a .mdx
file and add some content. To do this, navigate to the pages
folder, create a post
folder, add the first blog post named first-post.mdx
, and then paste in the code below. Feel free to tweak it and change the property values:
--- layout: ../../layouts/PostLayout.astro title: "Astro, Vite and MDX test" description: "Lorem ipsum dolor sit amet" author: "Iniubong Obonguko" pubDate: "20 Aug, 2022" image: "https://images.unsplash.com/photo-1664380619395-a25d867b5fb9?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&q=80&w=1080" slug: "first-post" --- ## Story about Old days In the olden days, Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Vitae ultricies leo integer malesuada nunc vel risus commodo viverra. Adipiscing enim eu turpis egestas pretium. Euismod elementum nisi quis eleifend quam adipiscing. In hac habitasse platea dictumst vestibulum. Sagittis purus sit amet volutpat. Netus et malesuada fames ac turpis egestas. Eget magna fermentum iaculis eu non diam phasellus vestibulum lorem. Varius sit amet mattis vulputate enim. Habitasse platea dictumst quisque sagittis. Integer quis auctor elit sed vulputate mi. Dictumst quisque sagittis purus sit amet. ## Conclusion Morbi tristique senectus et netus. Id semper risus in hendrerit gravida rutrum quisque non tellus. Habitasse platea dictumst quisque sagittis purus sit amet. Tellus molestie nunc non blandit massa. Cursus vitae congue mauris rhoncus. Accumsan tortor posuere ac ut. Fringilla urna porttitor rhoncus dolor. Elit ullamcorper dignissim cras tincidunt lobortis. In cursus turpis massa tincidunt dui ut ornare lectus. Integer feugiat scelerisque varius morbi enim nunc. Bibendum neque egestas congue quisque egestas diam. Cras ornare arcu dui vivamus arcu felis bibendum. Dignissim suspendisse in est ante in nibh mauris. Sed tempus urna et pharetra pharetra massa massa ultricies mi.
The frontmatter
is all the metadata property and values defined between
the triple dashes (—).
At the top of the .mdx
file is where all the frontmatter
data is defined:
- The
layout
property defines the layout of choice, which was created earlier inPostLayout.astro
- All other properties in the
frontmatter
contain “metadata” that’ll be used by the layout to populate the page - The rest of the content below the
frontmatter
is treated as text content for the blog and is passed into the<slot/>
placeholder in the layout
On your browser, go to https://localhost:3000/post/first-post
and you should get a page similar to the one below:
Adding interactive components to our Astro blog
Now, we’ll see how we can add interactive JavaScript-enabled components to our blog post.
For this, we’ll use an Astro components library called accessible-astro-components
. To proceed, we first need to install the library. Do this by running the code below in your terminal under the projects
folder.
npm i accessible-astro-components
Next, in the first-post.mdx
file below the frontmatter
definitions, import the Accordion
and AccordionItem
components:
import { Accordion, AccordionItem } from "accessible-astro-components";
Now, you can use Accordion
anywhere in the file:
{/* first-post.mdx */} {/* Rest of content at top */} ... <Accordion> <AccordionItem header="First Item"> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Architecto quasi nobis optio? Qui in quo accusantium debitis sapiente obcaecati magnam incidunt sit. Molestiae exercitationem quibusdam quod veritatis laboriosam est tenetur. </p> <a href="#">Tab to me!</a> </AccordionItem> <AccordionItem header="Second Item"> <p> Lorem ipsum dolor sit amet consectetur adipisicing elit. Architecto quasi nobis optio? Qui in quo accusantium debitis sapiente obcaecati magnam incidunt sit. Molestiae exercitationem quibusdam quod veritatis laboriosam est tenetur. </p> </AccordionItem> </Accordion> ... {/* Rest of content at bottom */}
The result is:
You can also use components that are specifically made for other JavaScript frameworks, such as VueJS, React, and Svelte. You just need to set up the framework in your Astro app first and then import the desired component.
Refer to the official documentation here for how it’s done.
Create a page in our Astro blog
We need a blog page that will display all the blog posts in a grid.
But before we get to that, let’s first create a layout for the blog page under the /Layout
folder and name it BlogLayout.astro
. Then paste the following code into it:
--- import Header from "../components/Header.astro"; import BaseHead from "../components/BaseHead.astro"; const { title } = Astro.props; --- <!DOCTYPE html> <html lang="en"> <BaseHead title="Blog Page" description="A page to display all our blog posts" /> <body> <div class="layout"> <h1>{title}</h1> <Header /> <main> <slot /> </main> </div> <style> body { margin: 0; background-color: #fff; width: 100%; } .layout { max-width: 1280px; margin: 0 auto; } </style> </body> </html>
Next, go to the src/pages
folder and create a blog.astro
file and paste in the following code:
--- import BlogLayout from "../layouts/BlogLayout.astro"; import { Card } from "accessible-astro-components"; const posts = await Astro.glob("../pages/post/**/*.mdx"); --- <BlogLayout title="Blog"> <section> <div class="container"> <ul> { posts.map((post) => ( <li> <Card url={"/post/" + post.frontmatter.slug} img={post.frontmatter.image} title={post.frontmatter.title} footer={post.frontmatter.author} > {post.frontmatter.description} </Card> </li> )) } </ul> </div> </section> </BlogLayout> <style lang="scss"> ul { display: grid; grid-gap: 2rem; grid-template-columns: repeat(3, 1fr); list-style-type: none; } </style>
Let’s analyze what’s happening in the code block above:
- First,
BlogLayout
is being imported to be used as the layout for the page - The
Card
component from theaccessible-astro-components
package is imported - Astro has an
Astro
global context and has the.glob()
method, which can be used to load many local files into the static site setup. In this case, all the.mdx
files contained in the/pages/post
directory are being loaded and assigned to theposts
variable - A
.map
method then loops through the values in theposts
variable, renders a list, and assigns the necessary props to theCard
component - The
slug
property defined on thefrontmatter
property of the blog file is then used to build the URL for the card component
Add one or two or more blog posts in the pages/post
directory to populate the blog page.
Once done, the blog page should look like this:
Voila! The blog is now complete.
Conclusion
Creating interactive text-based content using Markdown syntax has never been easier. By following this tutorial, you’re on your way to creating a blog using Astro and MDX. Feel free to update the code from this tutorial with your own custom styling and extra features.
You can also learn more about all the cool features that Astro provides with their MDX integration from the official documentation site.
Namaste.
The post Build a blog with Astro, Vite, and MDX appeared first on LogRocket Blog.
from LogRocket Blog https://ift.tt/HtXxnDW
Gain $200 in a week
via Read more