Introduction
I had previously written my website using NextJS. However, the lack of proper MDX support (At the time of writing, NextJS 13.4.10 had experimental support for MDX) was not ideal.
/** @type {import('next').NextConfig} */ const nextConfig = { experimental: { mdxRs: true, }, };
const withMDX = require("@next/mdx")(); module.exports = withMDX(nextConfig);
I had heard great things about Astro, and the docs were a lot more oriented towards hosting / managing content, so this was a great opportunity for me to learn a new framework.
Getting Started
The first step is setting up an Astro project - with npm create astro@latest
. Reading about the project structure was also helpful.
The basics
- content: Contains all the blogs or whatever docs to host on the website.
- pages: Contains all the routes. Similar to the pages folder in NextJS.
- layouts: The base structure for the blog / home page. For now I just have a
Layout.astro
, but having a customBlog.astro
file can give a unique and consistent look for the blog pages.
Customizing
The next step was figuring out the blog should look like. I went with a brief description + some of my projects + a blog section to start with. To keep things simple, I just have a /
page for my website + pages for the blog entries.
Writing blogs
Astro is really good at handling MDX, so writing blogs is as simple a creating a (markdown) entry in the content/blog
folder. Its is recommended to a config.ts
. This is so that Astro can understand the content - i.e content collections.
This way, different content types like blogs, newsletters, projects etc., can have a different structure. For example, this is my blog
content structure
// zod! import { z, defineCollection } from "astro:content";
// define what properties a blog should have const blog = defineCollection({ type: "content", schema: z.object({ title: z.string(), date: z.string(), description: z.string(), isDraft: z.boolean().optional().default(false), }), });
// add more collections and export! export const collections = { blog, };
Defining the structure of a blog helps to do a some cool stuff:
- if
isDraft
is set totrue
, the blogs can be hidden until they’re done - order blogs based on the
date
This can be done by extracting the props in the BlogRow.astro
page.
const { post: { data: { title, date, isDraft }, slug, }, } = Astro.props;
For example, when rendering the list of blogs
- Create a component that shows the blog title + date. This is
BlogRow.astro
in my case. - Extract the props like above, and use them to filter or alter the way the blog is displayed.
In the main index.astro
, each blog is rendered like it was any react component. The props are the ones defined in the Blog Schema (hence its importance).
const blogs = await getCollection("blog")
<div> {blogs.map((post) => <BlogRow {post} />)} </div>
Deploying
Anything more is overkill for just starting off. I bought my domain off Google Domains (RIP), but will switch to Cloudflare soon.
Closing Thoughts
I really liked my first foray into the Astro ecosystem
- its stable, and there is a developed ecosystem around markdown support
- its API’s are intuitive and easy to use
I will be using Astro from here on for static sites.
Thanks for reading! Want to read more like this? Read CLI-mbing to sucess