What is Astro? An Introduction To The Popular Static Site Generator - (r)

Jun 14, 2023
Get familiar with Astro.js static site generator and how it works

Share the news on

And that's where Astro comes in as one of the most cool kids on the JavaScript framework block.

The framework was developed by Fred K. Schott and an assortment of contributors, Astro has quickly become a favorite in the community of developers. It's a framework that's all-inclusive which functions a bit similar to a static page generator.

In this post we'll explain the reasons the majority of developers love Astro and are picking the framework over alternative solutions. We'll also walk you through how to build an online blog based on markdown using the framework.

What is Astro?

The Astro logo in black, showing "astro" in lowercase letters preceded by a stylized capital "A" with a small flame beneath it.
Astro

Despite its tiny footprint, Astro comes with powerful tools that drastically increase your site's flexibility, saving you hours in managing your theme and content. Additionally, it offers users the possibility of working with their preferred frameworks combination with Astro which is a great option for experienced coders who already have many favorites.

Here are just a few examples of ways Astro stands out from the crowd:

  • Island architecture: Astro extracts your user interface (UI) into smaller and isolated parts known as "Astro Islands" which can be utilized in any web page. Unused JavaScript replaces it with light HTML.
  • zero JavaScript (by default): While you are able to utilize all JavaScript that you would like to build your websites, Astro will attempt to use no JavaScript to production by transcription of your code. This is a great option if your focus is on speed of your site.

Furthermore, Astro is edge-ready, that means that it is ready to deploy at any point, at any time, without difficulty.

Are you ready to know more? We'll explore the way Astro works.

Astro's Structure

Before we venture any further, it's important to understand how Astro is set up so you're able to utilize it properly. Let's take a look at Astro's core file structure:

+-- dist/
 +-- src/
 | +-- components/
 | +-- layouts/
 | +-- pages/
 | +-- index.astro
 +-- public/
 +-- package.json

As you can see, the basic structure is easy to understand. But, there are a few key points you should remember:

  • Most of our project lives within the the src folder. The components, layouts, and pages in subfolders. You may add additional folders that make your work simpler to use.
  • This open folder is for any files in the outside world of the build process, such as images, fonts, or even a robots.txt file.
  • This folder called the dist folder will hold all the content you want to publish to your production server.

In the next step, let's dig deeper into Astro's major components parts, layouts and pages.

Components

The following is an example of how a simple component looks like -- in this instance the classified tag called a div tag that contains an H2:


 
 Hello, !
 

This is how we can incorporate that component into our website:

 import Component from ../components/.astro
--
 Then, import the component from../components/.astro 
 

As demonstrated above it is first necessary to import the element. It is only then that it will be included on the webpage.

The next step is to include some properties in the component. We'll start by adding a title property:

---
 const  title = 'Hello'  = Astro.props
 ---
 
 
 title
 

Here's the way our property could be incorporated:

 import component from ../components/.astro"
   
 This displays "Hello"  -->
  
  

Simple, right?

You've likely already realized, the real power of Astro's components is because of their universal and adaptable nature. They enable you to change the look and feel of your entire site by editing only a few lines of code. This could save you time to be wasted on tedious and laborious text replacements.

Layouts

Let's discuss layouts. In addition to their familiar purpose of thematics, layouts within Astro are also reusable elements, however they're used as code wrappers.

Look at this example:

---
 // src/layouts/Base.astro
 const  pageTitle = 'Hello world'  = Astro.props
 ---
 
 
 
 
 
 pageTitle
 
 
 
 
 
 
 

Take note of the tag Here is the tag. The component within Astro acts as a placeholder for actual HTML tags and other content.

We'll see how it works.

The below code will show our tag changing to our new code. All of this is wrapped around the Base.astro layout:

---
 import Base from '../layouts/Base.astro';
 ---
 
 
 
 Some example text.
 
 

You can see that our tags were substituted by the HTML it represents that is


 Some example text.
 

You can see that layouts, similar to components, allow you to reuse chunks of code across your website, easing the task of updating your overall design and content.

Pages

Pages are a specific type of component responsible for the routing of data, loading and templating.

Astro uses file-based routing to generate pages, rather than dynamic routing. Not only does the use of files consume less bandwidth, but it also prevents you from needing to import your component manually.

Here's an example of clearly defined ways:

src/pages/index.astro => yourdomain.com
 src/pages/test.astro => domain.com/test
 src/pages/test/subpage => domain.com/test/subpage

If we follow these paths, our resultant homepage will be displayed in the following manner:


 
 
 
 
 Hello World
 
 
 Hello, 
 
 

But we already know how to make layouts work, therefore let's transform this into something that's globally accessible:

---
 import Base from '../layouts/Base.astro';
 ---
 
 
 Hello, 
 

There - that's much cleaner.

We'll discuss routing in Astro further in detail later in this article, but for now, let's move on to things that are fun, like website construction and personalization.

Customizing and Extending Astro

Learn how you can customize your Astro website! We're going to use Markdown collections, routing, image handling and connection to React to create and customize our site.

Markdown Collections

With version 2.0, Astro introduced an improved method to manage Markdown content, compared to before. Thanks to collections, we can be sure that all our frontmatter data is included and will have the proper kind of connection.

Lately, in version 2.5 the developers included the ability to also manage JSON and YAML files in collections.

Ready to get your hands dirty?

First, put all your Markdown articles in the src/content/collection_name folder. The goal is to build blogs in this particular project. Therefore, for our example our folder it's the src/content/blog.

Now it's time to define all the required frontmatter fields in our src/content/config.ts file. The blog we're creating will require the following fields:

  • title (string)
  • tags (array)
  • publicationDate (time)
  • image (string, optional)

What it appears to be when assembled:

import  z, defineCollection  from 'astro:content';
 
 const blogCollection = defineCollection( 
 schema: z.object(
 title: z.string(),
 tags: z.array(z.string()),
 image: z.string().optional(),
 publishDate: z.date(),
 ),
 );
 
 export const collections = 
 'blog': blogCollection,
 ;

And this is what our article-about-astro.md Markdown file contains:

---
 title: Article about Astro
 tags: [tag1, tag3]
 publishDate: 2023-03-01
 ---
 ## Tamen risit
 
 Lorem *markdownum flumina*, laceraret quodcumque Pachyne, **alter** enim
 cadavera choro.

True, there's nothing special about our Markdown document. But there's some hidden magic there that's manifested in the event that we misspell a word.

For instance when we typed publishDate, we accidentally wrote publishData. If there is an error like this, Astro will throw an error message:

blog - article-about-astro.md frontmatter does not match collection schema. "publishDate" is required.

Amazing, right? This nifty feature can assist us to identify errors related to frontmatter in a matter of seconds.

The final thing to create is a web page that displays our information. Let's create a file at src/page/blog/[slug].astro with the following code:

---
 import Base from '../../layouts/Base.astro';
 import  getCollection  from 'astro:content';
 export async function getStaticPaths() 
 const blogEntries = await getCollection('blog');
 return blogEntries.map(entry => (
 params:  slug: entry.slug , props:  entry ,
 ));
 
 const  entry  = Astro.props;
 const  Content  = await entry.render();
 ---
 
 entry.data.title 
 
 

With the help of GetStaticPaths, Astro will create every static page for each post in the blog collection.

The only thing we're missing currently is a list of all our content:

---
 import Base from '../../layouts/Base.astro';
 
 import  getCollection  from 'astro:content';
 const blogEntries = await getCollection('blog');
 ---
 
 
 blogEntries.map(item =>  item.data.title
)
 
 

It is evident that making use of collections makes this process very simple.

Let's now create a database type collection. First, we must open the src/content/config.ts file again and add a new data collection:

import  z, defineCollection, referenece  from 'astro:content';
 
 const blogCollection = defineCollection( 
 type: 'content',
 schema: z.object(
 title: z.string(),
 tags: z.array(z.string()),
 image: z.string().optional(),
 publishDate: z.date(),
 author: reference('authors')
 ),
 );
 
 const authorsCollection = defineCollection( 
 type: 'data',
 schema: z.object(
 fullName: z.string(),
 country: z.string()
 ),
 );
 
 
 export const collections = 
 'blog': blogCollection,
 'authors': authorsCollection,
 ;

In addition to creating a brand new collection, we also included the writer reference in the blogCollection.

It is time to make a new author. We must create a file called maciek-palmowski.json in the content/authors.json:


 "fullName": "Maciek Palmowski",
 "country": "Poland"
 

The final step is to get this information for the form of our Post. In order to do this, we'll need to use obtainEntry:

---
 import Base from '../../layouts/Base.astro';
 import  getCollection, getEntry  from 'astro:content';
 export async function getStaticPaths() 
 const blogEntries = await getCollection('blog');
 return blogEntries.map(entry => (
 params:  slug: entry.slug , props:  entry ,
 ));
 
 const  entry  = Astro.props;
 const author = await getEntry(entry.data.author);
 const  Content  = await entry.render();
 ---
 
 entry.data.title
 Author: author.data.fullName
 
 

Routing

Astro is a web-based application that has two routes. We've covered the first static (file-based) routing - in our earlier discussion of pages.

Now we're going to shift our focus to dynamic routing.

By using dynamic route parameters it is possible to tell the Astro page file to perform the process of creating multiple pages that have the same layout. This is helpful when there are a large number of one specific type of page (think the author's bio and user profiles, as well as documentation article, etc.).

In this second example we'll be working on creating bio pages for the authors we'll be working with.

In Astro's static output mode, the pages are generated at build time. That means you need to determine the authors that get a corresponding file. When you switch to dynamic mode, on the contrary, the pages are generated upon request for every route that matches.

If you'd like to assign the name of a variable to a filename, put brackets around the variable:

pages/blog/[slug].astro -> blog/test, blog/about-me 

Let's get deeper into this by using the code in our blog/src/src/src/slug/src file:

---
 import Base from '../../layouts/Base.astro';
 import  getCollection  from 'astro:content';
 export async function getStaticPaths() 
 const blogEntries = await getCollection('blog');
 return blogEntries.map(entry => (
 params:  slug: entry.slug , props:  entry ,
 ));
 
 const  entry  = Astro.props;
 const  Content  = await entry.render();
 ---
 
 entry.data.title
 
 

The getStaticPaths route is the one responsible for creating all the static pages. It returns two objects:

  • params : Useful to fill in brackets of our URLs
  • props : All the values we're passing to the page

And with that, your page generation is taken care of.

Image Handling

Luckily, Astro has us covered here, too. Thanks to Astro's @astrojs/image package, we can present all of the above in just a couple of seconds.

Once installing the application After installation, we are granted access to two elements: Image and Picture.

Image component is used to create an image. Image component is used to produce an optimised

label. This is an example of how:

---
 import  Image  from '@astrojs/image/components';
 import heroImage from '../assets/hero.png';
 ---
 
 
 
 

Similar to it is the case that Image component produces an optimized part:

---
 import  Picture  from '@astrojs/image/components';
 import hero from '../assets/hero.png';
 ---
 

SSG against SSR

By the default settings, Astro is run as a static website generator. This means that all the contents are converted into static HTML pages.

While this is a perfect strategy from multiple angles (especially the speed aspect) however, there are times when we prefer a more dynamic approach. If you want a separate personal profile page for each of your users such as if you have thousands of articles on your site, re-rendering every time is way too slow.

Luckily, Astro also can work in a completely server-side-rendered structure as well as in an alternate mode between both.

For side-wide SSR to be enabled it is necessary to include the following code in astro.config.mjs:

import  defineConfig  from 'astro/config';
 export the default defineConfig(output: server');

This is the most common approach.

This hybrid strategy is that by default every page is generated dynamically aside from pages with the export const prerender = true included.

In Astro 2.5 it also offers an option to choose static rendering by default and choose dynamic routes on your own.

Because of these technologies tools, we are able to make, for instance, websites that are fully statically generated featuring dynamic user login and profile pages. Neat, right?

More information on this subject on the official documentation.

Incorporating other JavaScript Frameworks

Another amazing characteristic of Astro allows you to bring the framework you prefer and use it in concert with Astro. You can mix Astro along with React, Preact, Svelte, Vue, Solid, or Alpine (for all integrations you can refer to Astro's "Add Integrations" documentation).

npx astro add react

Now that React is fully integrated and is now the React component. In our case, it will be the counter component at src/components/ReactCounter.tsx:

import useState from'react';
 
 /*A counter created using React's */export functions Counter(children) 
 const [count setCount] = useState(0);const add = () = setCount((i) = i + 1) Const subtract = () = setCount((i) + i - 1) (i) =>return (
 setCount = () => return ( > -
count
count+
count +
count +children
>);
 

Then, but not least, we need to place the counter on our page with the following code:

---
 import * as react from '../components/ReactCounter';
 ---
 
 
 

And voila: Your React component has been fully integrated into your website.

How To Deploy Astro Using

Begin by establishing a GitHub repository to store your site's file files. If you're not yet ready to make use of your own data then you could copy this Astro starter site template that our team developed.

A portion of the GitHub repo for 's Astro starter site, showing an image of the white Astro
GitHub repo of Astro Template for a starter website by

When your repo is complete, log in to My My, then choose Applications on the left and then choose Application in the red Add Service dropdown.

he My dashboard opened to the "Applications" section, which shows a purple "Add service" dropdown with two options: "Application" and "Database".
Include an application to My

The final stage is providing the specifics of your build and installation.

Most of what you'll be given, like Name of process and Payment method are likely to have clear or straightforward solutions. Note that you may choose to leave the Start command field empty if you decide to do so; it will assign the npm command as the option.

After you've completed filling in your build's information Click to click the Confirm payment method button to initialize your build.

That's all there is to it! You now have an active, functioning static site built with Astro. Astro framework.

A dark page with the  logo in white in the center above the words "Welcome to Your New Astro Site", followed by two rows of cards with labels "Official Astro Website", "Astro Documentation", "Download Starter", and " GitHub".
Our live Astro homepage

Find your live URL and other details about your deployment under Deployments within your My Account.

The "Deployments" screen of My showing the details and history of our Astro site deployment.
A successful Astro deployment

Summary

Astro's clear structure, simple syntax, and global components make creating and running an application easy.  The lightweight design and the dual usage of static and dynamic routing significantly improve the responsiveness of your site and its capability of cooperating with and alongside other JavaScript frameworks makes it all the more appealing to experienced coders.

If you're looking to create a content-rich site that is quick to load, provides flexibility, and offers both dynamic and static creation, then Astro might be the best solution for you.

What are your thoughts on the Astro static site generator? Did you use it in a project of your own? Let us know in the comment section below.