Angular dev did a blog in Astro

Post cover

Hey! 👋

First of all: welcome to my blog 🎉

It’s a pleasure to share my knowledge, probably some jokes, tips & overall experience with you!


Your overall thoughts on Astro can be different - this posts presents my own opinion 😇

Why exactly this topic?

Yeah.. I know it’s the most common topic & it seems trivial, but I HAD TO!

One, really solid Angular player I really like and who (I assume 🤫) likes me a bit, suggested to go with exactly this topic for the first post.

Thank you, your idea was just great! Huge shout out to Mihai Paraschivescu 💛

How it started? 🛫

I must admit I was really impressed of Astro when I started contributing to (btw. really great) initiative - Angular Snippets by Santosh Yadav

A few things I paid attention to:

  • Lightweight
  • Simplicity
  • Imo great docs
  • A lot of integrations

So I thought, yeah… let’s do it

Of course the first step was to install it, boom:

pnpm create astro@latest

Then I was asked about a template: yes, the blog one please...

I looked around 👀

Because as an Angular Dev I was really interested in:

  • How routing works
  • How to compose components
  • How to pass props to components
  • Other things…


The same game as with the Nuxt - cool

Maybe we’re getting old… 👴

The fresh approaches everywhere… 🍓

It means routes are automatically generated based on folders’ structure

For me it was really beneficial, why?

✅ I love to keep a structure meaningful

✅ This project must be simple

✅ No ...RoutingModule, const routes = [...] etc.

Example ⌛️ (time, heh)

Structure of routes generation

  • It scans pages folder to build the structure
  • There’s no nesting, so the first index.astro is just /
  • blog folder means now we have /blog
  • index.astro inside the blog folder represents a structure of /blog
  • [...slug] represents a concrete post, so now we have /blog/my-concrete-post

Components’ composition

Pretty cool! We can just…

Components' composition

…use it like in Angular

How to pass props

Let’s assume our HeaderLink takes position from the parent Header

<HeaderLink href="/" position={'top'}>Home</HeaderLink>

Then in our HeaderLink we just:

const { position } = Astro.props;

Integrations ⚙️

This is the part I really appreciate 🤝

How do you think - what else do I need for the blog?

Some styling 🔊: yes, welcome Tailwind!

Some content 🔊: yes, welcome MDX!

Started with simple astro-cli commands:

pnpm astro add mdx

pnpm astro add tailwind

And ended with an Astro’s warm welcome, with everything configured

export default defineConfig({
	site: "",
	integrations: [mdx(), sitemap(), tailwind()],

I was also curious how the MDX fetching works. First thing - src/content is reserved for collections, second thing - these collections are accessible via astro:content. Let’s say we have a PostLayout component being a styled wrapper, then we have a [...slug].astro component loaded basing on nested structure + a slug of a post. The component uses getCollection() to get the whole collection, then it’s being filtered to find the exact post by a slug props.

And finally:

const post = Astro.props;
const { Content } = await post.render();
<PostLayout {}>
  <Content />

BTW the What you can expect header and the whole table are automatically generated by rehype-toc & rehype-autolink-headers. Tbh it required to be styled, nothing more 😛

Let’s build ⚒️

The biggest benefit of this project was that I wanted go ##YOLO 🤪

Fu** architecture, engineering, thinking about abstractions - it was supposed to be fun, so it was 😀

Landing on the first shot 🛬

By doing a landing I did some new Astro components, really nice & smooth

Browse all posts page 🔎

Here I just reused some components from the previous page - 😎

However, title of this page contains “Browse”, so I thought it’d be nice to have some search bar

Meme according to the problem

astro components === non-client code

💡 It means we’ve no access to window or document

Vue components to the rescue 🤝

Are u still here? So here we go again:

pnpm astro add vue

And we’re home, keeping in mind one quote from the greatest monk ever:

Vue components in Astro, no Astro components in Vue


Blog post page 🗾

For the first time it seemed like everything works

Meme according to the problem

Markdown doesn’t work properly for headers, lists, etc.

I still don’t know what’s wrong 🤪, but workaround was to use global styles assuming the only article is the blog post one


I also had a problem with non-working tailwind (vue)

This time I was just stupid, apologies

SEO 🧑‍💻

Yeah.. again - I was warmly welcomed by the built-in BaseHead component:

<!-- 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} />

<!-- Canonical URL -->
<link rel="canonical" href={canonicalURL} />

<!-- Primary Meta Tags -->
<meta name="title" content={title} />
<meta name="description" content={description} />

<!-- Open Graph / Facebook -->
<meta property="og:type" content="website" />
<meta property="og:url" content={Astro.url} />
<meta property="og:title" content={title} />

Then, as we already know the flexibility of Astro, it can just be used in other components

<!DOCTYPE html>
<html lang="en">
    <BaseHead title={SITE_TITLE} description={SITE_DESCRIPTION} />

Small adjustments and we’re home again!


Oh c'mon maaan, that's TOO EASY!

Meme according to the problem

I used Netlify, so:

  • Click to connect repo
  • Build command + dist
  • Click
  • Done

And in the meantime setting a domain with SSL

BTW. I don’t use SSR!

What’s more, astro-sitemap plugin takes care of creating a sitemap ‼ NICE

A11Y, Performance, Best practices

Let’s begin with the Lighthouse report 😀

At this point I just adjusted semantics, because of semi-#YOLO building


Unforunately, I haven’t found any good #accessibility tricks in the blog template, maybe I selected wrong one. Anyways - proper sectioning, aria-labels, alting… even skip to content did a trick!

Performance & Best practices

I had one problem with content compression - no problem, there’s always astro-compress easy to integrate as other tools. COOOOOL!

btw.. when you’ll see 272 console issues - that’s the problem of embedded tweets & twitter itself

Wrapping up 🔥

I really enjoyed working on this project

For me Astro was the best choice:

  • Wider perspective / get out of (Angular) comfort zone
  • Simplicity
  • Easy integrations
  • A lot of built-in components/approaches
  • Hugely customizable
  • Good docs
  • And the most important: it was a fun to work with it

Keeping in mind simplicity, no complex logic, no advanced data manipulation, no need to make it hugely scalable - that’s why I didn’t choose Angular (which I love btw)

- - Yours truly