👾 Getting started with Astro Framework
Published: 2023-09-26 14:24:59

**Author: <a  target="_blank" href="https://refine.dev/blog/author/chidume_nnamdi/">Chidume Nnamdi</a>**



## Introduction

Yet another framework, in the fast-paced world of web development, staying up-to-date with the latest tools and technologies is crucial. One such technology that has gained significant popularity in recent times is Astro.js. Designed to streamline and simplify the web development process, Astro.js offers an innovative approach to building modern websites and applications.

Astro.js, often referred to as a "static site generator," provides developers with a comprehensive framework for constructing static and dynamic web pages. By combining the best features of static site generation and server-side rendering, Astro.js offers a unique solution that optimizes performance, enhances developer productivity, and delivers exceptional user experiences.

> Astro is the all-in-one web framework designed for speed. Pull your content from anywhere and deploy it everywhere, all powered by your favorite UI components and libraries. - [Astro.js](https://astro.build/)

The benefits and advantages of using Astro.js are numerous. First, it allows developers to leverage the power of component-based development, enabling them to build reusable UI elements. This modular approach not only enhances code organization but also facilitates collaboration among team members, making it easier to maintain and scale projects.

One of the greatest achievements of Astro.js is its blinding speed. [In 2023, Astrojs was compared with other frameworks](https://astro.build/blog/2023-web-framework-performance-report/) in terms of performance. Astro.js, Nextjs, Nuxt, SvelteKit, WordPress, Remix, and Gatsby were compared against major core vitals assessments. In the FID, First Input Delay, measurement Astrojs came second behind SvelteKit. Astrojs took lea in Cumulative Layout Shift, Largest Contentful Paint (LCP), and Interaction to Next Paint (INP) measurements.

Another significant advantage of Astro.js is its ability to seamlessly integrate with various frontend frameworks and libraries. Whether you prefer React, Vue.js, Svelte, or any other popular JavaScript framework, Astro.js provides a flexible and agnostic environment that empowers developers to work with their preferred tools. This compatibility ensures that developers can leverage their existing knowledge and expertise while harnessing the benefits of Astro.js.

One of the standout features of Astro.js is its ability to deliver blazing-fast websites. By employing static site generation and intelligent caching, Astro.js optimizes performance by pre-rendering pages and serving them directly from a Content Delivery Network (CDN). This approach eliminates the need for server-side rendering on every request, resulting in lightning-fast loading times and improved SEO rankings.

Astro.js also excels at reducing the complexity associated with managing multiple data sources and APIs. With its unified data fetching approach, developers can seamlessly fetch data from various sources and render it alongside static content. This simplifies the development process and eliminates the need for separate data fetching and rendering logic, resulting in cleaner code and improved developer productivity.

Now that we have finished discussing the advantages and benefits of Astro.js, let's determine the intended readership for this article. This all-encompassing guide caters specifically to web developers aiming to augment their skill set and embrace contemporary development methodologies. Whether you are an experienced developer aiming to incorporate a more streamlined workflow or a novice enthusiastic to plunge into the realm of web development, this article will furnish you with a robust groundwork to initiate your Astro.js journey.

In the following sections, we will delve deeper into the core concepts of Astro.js, explore its key features, and guide you through the process of setting up your first Astro.js project. By the end of this article, you will have the knowledge and confidence to leverage Astro.js to build performant, scalable, and visually stunning websites and applications. So, let's embark on this exciting journey into the world of Astro.js and unlock its true potential in modern web development.

## Installation and Setup

In this section, we will learn how to set up the Astrojs project on our machine, but first, we have to make sure that some tools and binaries are already installed in our system.

- **Nodejs**: We need the Nodejs binaries installed in our system. Go over to [https://nodejs.org/en/download](https://nodejs.org/en/download) and install the binaries meant for your machine.
- **npm or yarn**: These are Node Package Managers, they help in maintaining and managing the dependencies, and the Nodejs environment of our project. `npm` comes bundled with the Nodejs binaries, so once you install Nodejs you don't need a separate installation for npm. [Yarn](https://classic.yarnpkg.com/lang/en/docs/install/) can be installed by running `npm i yarn -g`.

Now, we have all the binaries installed. To test if everything is working fine, run the following commands in your terminal.

```bash
node -v
npm -v
yarn -v
```

If you get the version numbers of the binaries, then you are good to go.

In the next section, we will learn how to create a new Astrojs project.

## Creating Your First Astro Project

To create a new Astrojs project, run the following command in your terminal.

```bash
npx create-astro my-astro-project

# create a new project with yarn
yarn create astro

# create a new project with npm
npm create astro@latest
```

This will create a new Astrojs project in the `my-astro-project` directory. But first, you will be prompted to choose the directory where your new project will be created in.

```bash
 astro   v2.5.7 Launch sequence initiated.

   dir   Where should we create your new project?
         ./astro-prj
```

Next, you will be prompted to choose a template for your project.

```
  tmpl   How would you like to start your new project?
         ○ Include sample files
         ○ Use blog template
         ● Empty
```

For this project, I chose the `Empty` project.

After some background work, it will prompt you to install dependencies.

```
  deps   Install dependencies? (recommended)
         ● Yes  ○ No
```

Select `Yes` to install the dependencies. The next prompt will be whether you want to use TypeScript in the project:

```
  ts   Do you plan to write TypeScript?
         ● Yes  ○ No
```

Next, will be whether to initialize a git repository in the project.

```
  git   Initialize a git repository?
         ● Yes  ○ No
```

At the end, you will be presented with this:

```

  next   Liftoff confirmed. Explore your project!

         Enter your project directory using cd ./astro-prj
         Run npm run dev to start the dev server. CTRL+C to stop.
         Add frameworks like react or tailwind using astro add.

         Stuck? Join us at https://astro.build/chat

╭─────╮  Houston:
│ ◠ ◡ ◠  Good luck out there, astronaut! 🚀
```

And an Astrojs project will be created in the `astro-prj` directory.

Once the project is created, navigate to the project directory and run the following command to start the development server.

```bash
cd astro-prj
npm run dev

(base) ➜  astro-prj git:(master) npm run dev

> astro-prj@0.0.1 dev
> astro dev

  🚀  astro  v2.5.7 started in 68ms

  ┃ Local    http://127.0.0.1:3000/
  ┃ Network  use --host to expose

```

The server will be started at ` http://127.0.0.1:3000/`. Open the URL in your browser to see the Astrojs project.

Now, we have successfully created our first Astrojs project. We will now learn about the project structure.

**Project Structure**

The project structure of an Astrojs project is as follows:

```bash
├── README.md
├── astro.config.mjs
├── package-lock.json
├── package.json
├── public
│   ├── favicon.svg
│   ├── index.css
│   └── index.js
├── src
│   ├── components
│   │   └── App.astro
│   ├── layouts
│   │   └── default.astro
│   ├── pages
│   │   ├── 404.astro
│   │   └── index.astro
│   └── styles
│       └── global.css
└── yarn.lock
```

This is the structure of a basic Astrojs project. Let's go over the files and directories in the project.

- The `astro.config.mjs` file is the configuration file for the Astrojs project.

- The `public` directory contains the static assets of the project.

- The `src` directory contains the source code of the project.

- The `components` directory contains the components of the project.

- The `layouts` directory contains the layouts of the project.

- The `pages` directory contains the pages of the project.

- The `styles` directory contains the styles of the project.

In the next section, we will learn about Astrojs layouts and pages.

---

<div>
<a href="https://github.com/refinedev/refine">
   <img  src="https://refine.ams3.cdn.digitaloceanspaces.com/blog-banners/retool-alternative.png" alt="refine repo" /> 
</a>
</div>
----


## Defining Layouts and Pages

Pages in Astrojs are similar to the pages in Nextjs. They are responsible for the routing of the Astrojs project. Every file in the `pages` directory is a page in the project. For example, the `index.astro` file in the `pages` directory is the home page of the project.

```bash
├── pages
│   ├── 404.astro
│   └── index.astro
```

The `404.astro` file is the 404 page of the project.

```bash
├── pages
│   ├── about.astro
│   ├── contact.astro
│   ├── blog
│   │   ├── [slug].astro
│   │   └── index.astro
│   └── index.astro
```

All the files in the above directory structure are pages of the project. Each of them makes up the routing of the project. Each file is loaded when its mapped route URL is visited in the browser. So each file in the `src/pages/` directory becomes an endpoint on your site based on its file path.

The `about.astro` and `contact.astro` files are the about and contact pages of the project respectively. The `blog` directory contains the blog pages of the project. The `index.astro` file in the `blog` directory is the blog home page. The `[slug].astro` file is the blog post page.

See that Astrojs supports dynamic routing. We have `blog` folder and inside the blog folder are three files: `index.astro` and `[slug].astro`. Now, the `blog` folder becomes a sub-path, and the `index.astro` maps to `/blog/` URL. The `[slug].astro` maps to `/blog/:slug` URL. The `:slug` is a dynamic parameter. So, if we have a blog post with the slug `hello-world`, then the URL will be `/blog/hello-world`.

So:

```
blog/ will load blog/index.astro file

/blog/hello-world will load blog/[slug].astro file
```

This process is called `file-based routing`. It is a simple and intuitive way to define routes in Astrojs.

**Layouts**

Layouts in Astrojs are like HTML templates used to provide a reusable UI structure. The `default.astro` file in the `layouts` directory is the default layout of the project.

```bash
├── layouts
│   └── default.astro
```

The `default.astro` file is used as the layout for all the pages of the project. The `default.astro` file is as follows:

```html
---
import { Head } from 'https://astrojs.org'
---

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />

    <link rel="icon" href="/favicon.svg" type="image/svg+xml" />
    <link rel="stylesheet" href="/index.css" />
    <script type="module" src="/index.js"></script>
  </head>

  <body>
    <slot />
  </body>
</html>
```

The `slot` element is where the external content placed between the layout component will be injected. This is similar to the `ng-content` in Angular and `{children}` in Reactjs.

Let's say we have a layout `MyLayout.astro`:

```html
---
import BaseHead from '../components/BaseHead.astro';
import Footer from '../components/Footer.astro';
const { title } = Astro.props
---

<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <BaseHead title="{title}" />
  </head>
  <body>
    <nav>
      <a href="#">Home</a>
      <a href="#">Posts</a>
      <a href="#">Contact</a>
    </nav>
    <h1>{title}</h1>
    <article>
      <slot />
      <!-- your content is injected here -->
    </article>
    <footer />
  </body>
</html>
```

Let's see how we can render it:

```html
---
import MyLayout from '../layouts/MyLayout.astro';
---

<MyLayout title="MyLayout">
  <p>My layout!</p>
</MyLayout>
```

The `<p>My layout!</p>` will be injected into the `<slot />` element in the `MyLayout.astro` file. The `title` prop will be passed to the `MyLayout.astro` file.

We will learn more about props in the next section.




## Building Components with Astro

Components are the building blocks of all component-oriented frameworks. Astrojs is a component-oriented framework. It is built around components.

Components are single units of UI. They are reusable and composable. This makes them easy to maintain and test. The complete website built using Astro is made up of components. So Astrojs is a tree of components.

To create a component in Astrojs we will simply create a file with its name ending with `.astro`. For example, `Component.astro` is a component in Astrojs. We have created a component.

A basic shell of a component looks like this:

```tsx
---
// Component Script (JavaScript)
---
<!-- Component Template (HTML + JS Expressions) -->
```

The `Component Script` section is where the JavaScript code is written. It is where to define the component logic. The component template is written in HTML. It is used to define the component UI.

Let's create a component called `MyComponent.astro`:

```tsx
<input type="text" placeholder="Type your text here..." />

<button>Send</button>
```

This is a simple component. It is a form component. It has an input field and a button. It is a reusable component. We can use it anywhere in our project.

Let's see how we can use it in our project:

```tsx
---
import MyComponent from '../components/MyComponent.astro';
---

<MyComponent />
```

Let's say we want to add a click event to the button in `MyComponent`. We know that the event handler will be a function, and this function is JavaScript. So first, we will add a script tag to the component. This is done by writing double dashes `--` at the top of the component file. Then we will write the JavaScript code in the script tag.

```tsx
---
function handleClick() {
  console.log('Button clicked!');
}
---
<input type="text" placeholder="Type your text here..." />

<button onclick="{handleClick}">Send</button>
```

We have added a click event handler to the button. The `handleClick` function will be called when the button is clicked. The `handleClick` function will log `Button clicked!` to the console.

**Passing Props to Components**

Props are one of the most important features in any component-oriented framework. Props are used to pass data from one component to another. This makes the components reusable and composable.

Let's see how we can pass props to an Astrojs component. We want to pass a button text to the `MyComponent` component. We will do this by rendering the component like this:

```tsx
---
import MyComponent from '../components/MyComponent.astro';
---

<MyComponent buttonText="Send" />
```

The `buttonText="Send"` is how props are passed to components. The `buttonText` is the name of the prop. The `Send` is the value of the prop. The prop name and value are separated by an equal sign `=`. The prop name and value are wrapped in double quotes `"`. Any JavaScript data can be passed via props.

Let's see how the `MyComponent` component will receive the prop:

```tsx
---
const { buttonText } = Astro.props;
---
<input type="text" placeholder="Type your text here..." />

<button>{buttonText}</button>
```

So the `buttonText` prop is received in the `MyComponent` component. The prop is destructured from the `Astro.props` object. The prop is then used in the component template.

The `Astro` object is available in all components and Astrojs puts all the props sent to that particular component in the component's `Astro.props` object. The Astro object instance is unique to each component.

## Working with Static and Dynamic Content

**Passing content to components**

There are times when we want to render elements between the tags of a component:

```tsx
<MyComponent>
  <p>My component!</p>
</MyComponent>
```

With the code in our `MyComponent` component, the `<p>My component!</p>` will not be rendered. This is because the component template does not have a place to render the content. We will add a `slot` element to the component template:

```tsx
---
const { buttonText } = Astro.props;
---
<input type="text" placeholder="Type your text here..." />

<button>{buttonText}</button>

<slot />
```

Astrojs will render the element `<p>My component!</p>` in place of the `slot` element.

Astrojs gave us the option of naming slots so we can render content in a specific slot. Let's say we want to render content at the start of the template and a footer at the end of the template. We will name the slots `header` and `footer`:

```tsx
---
const { buttonText } = Astro.props;
---
<slot name="header">
<input type="text" placeholder="Type your text here..." />

<button>{buttonText}</button>

<slot name="footer" />
```

Now, we can render content in the header and footer slots:

```tsx
<MyComponent>
  <p slot="header">My component!</p>
  <p slot="footer">My component!</p>
</MyComponent>
```

## Managing Data in Astro

Managing data is a crucial aspect of web development, and Astro.js provides robust options for efficiently fetching and utilizing data within your projects. In this section, we will explore the various data management capabilities offered by Astro.js, including fetching data from external sources or APIs and leveraging that data within Astro templates and components.

**Fetching Data from External Sources or APIs**

Astro.js offers us the flexibility for retrieving data from external sources or APIs. We can utilize the full power of JavaScript to perform data fetching operations and seamlessly integrate the retrieved data into your Astro projects.

**HTTP Requests**
We can make HTTP requests using popular JavaScript libraries such as `fetch` or `axios` in Astro.js. These libraries provide convenient methods for sending GET, POST, PUT, DELETE, and other types of requests to external APIs. By leveraging these libraries, we can retrieve data from various sources, including RESTful APIs, GraphQL endpoints, or even custom backend servers.

**Data Fetching Libraries**
Astro.js also integrates well with data-fetching libraries like `swr` or `react-query`. These libraries provide additional features such as caching, automatic revalidation, and error handling, which can greatly simplify the process of fetching and managing data in our Astro projects.

**Serverless Functions**
Another approach to fetching data in Astro.js involves using serverless functions. These functions run on the server side and allow us to fetch data from external sources or perform any necessary server-side processing. Astro.js seamlessly supports serverless functions, enabling us to retrieve data dynamically and pass it to our Astro components during the build process.

```tsx
---
import { getPosts } from '../lib/posts';
const posts = getPosts();
---

{posts.map((post) => (
  <div>
    <h2>{post.title}</h2>
    <p>{post.body}</p>
  </div>
))}
```

Once we have fetched the required data, Astro.js empowers us to seamlessly integrate it into your templates and components, enabling dynamic rendering and data-driven UIs.

With the data management capabilities provided by Astro.js, we can effortlessly fetch and utilize data from external sources or APIs, empowering you to create dynamic and data-driven websites or applications. Whether you need to display blog posts, populate product information, or showcase real-time data, Astro.js offers a versatile toolkit for managing data within your projects.

## Conclusion

We covered a lot and the basics of Astro.js in this article. We started by installing Astro.js and creating a new project. We then looked at the project structure and how to run the project. We then looked at the Astro.js template syntax and how to create components. We also looked at how to pass props to components and how to render static and dynamic content in components. We also looked at how to fetch data from external sources or APIs.