Iniubong Obonguko Frontend developer, Vue ninja, code enthusiast. Learning every day.

Using Astro and Netlify to build and deploy a web app

5 min read 1566

Using Astro And Netlify To Build And Deploy A Web App

What is Astro?

Astro is a powerful Static Site Generator that lets you create highly performant websites while shipping zero JavaScript.

Astro ships zero JavaScript in your final build by default, but for cases where you need the interactivity that JavaScript provides, Astro can automatically hydrate interactive components when they become visible on the page.

With Astro, you can use UI components from any JavaScript framework (React, Svelte, Vue). During build time, these components will be rendered as static HTML. Check out this article to learn more about Astro.

What is Netlify?

Netlify is a web hosting platform that simplifies the process of hosting and deploying your static websites.

Netlify has many features, including continuous integration and deployment, functions that allow us to perform backend operations without a server, and many more. Netlify is also commonly used to build Jamstack applications because of its robustness and simplicity.

In this tutorial, you’ll learn how to build a web application using Astro and deploy it to Netlify.

Jump ahead:


  • A Netlify account
  • A recent Node.js version
  • Command line/Terminal
  • Code editor
  • Working knowledge of JavaScript

Getting Started with Astro

Create a project using the Astro CLI, starting by running the following command in your terminal:

npm create [email protected]

Once the command has run, a script installation will take place.

The following prompt will come up on the terminal.

Getting Started With Astro

Either press Enter to proceed and a folder will be created in your current directory with the name my-astro-site, or you can rename the folder by typing your desired folder beginning with ./, followed by the name, such as ./desired-name.

Next, you’ll see a prompt to choose a template to get started with. For the sake of this tutorial, select the Just the basics template and press ENTER to proceed.

Choosing An Astro Template

Next, you’ll be prompted to choose whether to install npm dependencies or not. Press ENTER to continue, because “Yes” is the recommended answer.

Then, you’ll be asked whether you want to initialize your project as a Git repository. I recommend doing so, because you’ll need this later to deploy to Netlify.

Finally, select your level of TypeScript strictness, or opt out of using TypeScript entirely. I chose the relaxed option for this, but it’s totally up to you.

Selecting TypeScript Strictness

Now that the setup is complete, type cd into my-astro-site directory and run the command:

npm run dev

This will open up a server at http://localhost/3000/.

Here’s what it should look like:

Astro Site Server

Building your Astro web app

The application you’ll create while following this tutorial is a country directory application. You’ll make an HTTP request to an endpoint to fetch and render all countries, each with their own detailed page, and through this you’ll learn dynamic routing with Astro.

Let’s get started.

First, open up your newly created project folder in your code editor of choice.

Navigate to the Card.astro file in the /src/components folder to modify it to suit what you’re building.

Then, replace the code in the Card.astro file with the code below:

export interface Props {
  name: string;
  capital: string;
  population: number;
  cca3: string;
  flag: string;
const { name, capital, population, flag, cca3 } = Astro.props;
<li class="country">
  <a href={`country/${cca3}`}>
    <img src={flag} alt={name} class="countryflag" />
        new Intl.NumberFormat("en-US").format(population)
  .country {
    list-style-type: none;
    height: 350px;
    width: 30ch;
    margin: 0 auto;
    border-radius: 10px;
    box-shadow: 1.5px 1.5px 11px hsla(208.4, 23.5%, 31.8%, 0.39),
      -1.5px -1.5px 11px rgba(0, 0, 0, 0);
  .country h3,
  p {
    margin-left: 10px;
  p {
    font-size: 16px;
    font-weight: 500;
  .countryflag {
    aspect-ratio: 2/1;
    width: 100%;
    height: auto;
  a {
    text-decoration: none;
    color: black;

At the top of the component file, you’ll notice the Props interface. This helps define the properties of the data the component expects to receive.

Then, on line 9, the props are destructured for use within the component.

It’s probably worth mentioning that Astro components are demarcated into three: the JavaScript section is demarcated using three hyphens, the HTML section is demarcated by the use of HTML element tags, and the style section is demarcated by the use of style tags.

Next, go to the index.astro file located in the pages folder and replace it with the code below:

// index.astro
import Layout from "../layouts/Layout.astro";
import Card from "../components/Card.astro";
const allCountries = await fetch("").then(
  (res) => res.json()
<Layout title="Welcome to Astro.">
    <h1>Welcome to <span class="text-gradient">Astro</span></h1>
    <ul role="list" class="countries">
      { any) => {
          return (
  :root {
    --astro-gradient: linear-gradient(0deg, #4f39fa, #da62c4);
  .countries {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    grid-gap: 3rem;
    grid-auto-rows: minmax(100px, auto);
    margin: 70px auto;
  h1 {
    margin: 2rem 0;
  main {
    margin: auto;
    padding: 1em;
    max-width: 100ch;
  .text-gradient {
    font-weight: 900;
    background-image: var(--astro-gradient);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-size: 100% 200%;
    background-position-y: 100%;
    border-radius: 0.4rem;
    animation: pulse 4s ease-in-out infinite;

Here, an HTTP request is being made to the endpoint to fetch a list of all the countries. Then, data for each country is being passed as props to the Card.astro component. There’s a bit of styling added to make the app look nice.

More great articles from LogRocket:

Here’s what the app should look like now:

Country Directory App

Dynamic routing

Routing in Astro is done with the HTML a (anchor) element because it doesn’t come shipped with a custom Link component.

From the Cards.astro component, there’s the a element with its “href” attribute pointing to /country/cca3. For this to work, create a country folder in the pages directory.

Once you’ve created the folder, create a file with the name [slug].astro inside of it.

N.B., Astro uses bracket notation to define dynamic routes.

Country Folder In Astro Pages Directory

Next, open up the [slug].astro file, and paste in the following code:


import Layout from "../../layouts/Layout.astro";
export async function getStaticPaths() {
  const characters = await fetch("").then(
    (res) => res.json()
  return any) => ({
    params: {
      slug: el.cca3,
const { slug } = Astro.params;
const data = await fetch(`${slug}`).then(
  (res) => res.json()
<Layout title={data[0]?.name}>
  <section class="page-content">
    <div class="container">
      <img src={data[0].flags.svg} alt="" />
        <li>Official Name: {data[0]?.name.official}</li>
        <li>Independent: {data[0]?.independent ? `Yes` : `No`}</li>
        <li>Continents: {data[0]?.continents}</li>
        <li>Sub Region: {data[0]?.subregion}</li>
        <li>Timezones: {data[0]?.timezones}</li>
          Population: {
            new Intl.NumberFormat("en-US").format(data[0]?.population)
  .page-content {
    display: flex;
    flex-direction: column;
    padding-top: 100px;
    align-items: center;
    justify-content: center;
  .container {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
  img {
    aspect-ratio: 2/1;
    width: 50%;

For dynamic routing to work in Astro, all possible routes need to be pre-generated. The way to do this is with the getStaticPaths function.

In the code above, the getStaticPaths function is made asynchronous as an HTTP request is made to the endpoint to fetch all countries. Then, the unique three-letter cca3 identifier from each country is used as the params.

The “slug” property is then destructured from Astro.params and used to fetch the details of a particular country when the user navigates to that route. The data is then accessible in the template part of the component.

Here’s what your app should look like so far:

Astro App

Hosting with Netlify

In order to host your Astro application on Netlify and benefit from continuous deployment, I recommend deploying your application to a remote Git repository such as GitHub, GitLab, or Bitbucket. For this project, I’ll be using GitHub.

Once you’ve deployed your app to a Git repository, go to Netlify, click on Add new site and choose Import an existing project. You’ll be redirected to a three-step configuration process.

Hosting On Netlify

  1. 1. Connect to your Git provider.Connecting To Your Git Provider
  2. Import and select your project’s repository. The name of mine is astro-netlify-demo.
    Importing Your Project's Repository
  3. Select the project build setting. There’s no need to configure anything extra here, because it’s all standard. Click on Deploy site and voilà!
    Selecting Project Build Setting

Now all you have to do is wait for Netlify to finish deploying your project, and you can access your hosted URL in the dashboard.


This tutorial covered how to set up an Astro project with Astro components, dynamic routing with Astro, and deploying your web app to Netlify.

I hope you enjoyed! Let me know if you have any questions or suggestions.

: Full visibility into your web and mobile apps

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page and mobile apps.

Iniubong Obonguko Frontend developer, Vue ninja, code enthusiast. Learning every day.

Leave a Reply