Building Your First Island-based Project with Astro

Learning how to build a website using the island of interactivity pattern provided by Astro.

Fernando Doglio
Bits and Pieces
Published in
6 min readNov 1, 2022

--

Photo by Lucas Marconnet on Unsplash

The “Islands of Interactivity” pattern is being talked (or written) about quite a lot lately, and that’s because more frameworks are starting to embrace it.

Recently Fresh 1.0 was released, and they base their entire architecture around this pattern. I even wrote a piece about this in case you’d like to know more details about how islands work.

But today I want to talk about Astro instead. This framework allows you to build your web apps the way you want. Do you want to use React? Or perhaps use a little bit of Vue as well? Sure! Maybe integrate that Svelte component you saw somewhere? Sure, why not!

And on top of it all, it provides you with a way to implement the islands architecture, so your apps are only shipping the JavaScript you need, and no more.

Let’s see how that works!

Getting started with Astro

This is the easy part, getting an Astro-based project up and running is very simple, especially in this case where I’m going to build a static blog with a single interactive component (the actual island).

This command will trigger a nice wizard walkthrough that will guide you through the process. You’ll get asked a few questions, just make sure you specify you’re building a blog, this will scaffold everything you need to have the blog up and running immediately.

If you have any issues here, check out their documentation, it has all the details you need.

What are we building?

We’re building a blog, that’s for sure. But that’s done automatically for us with the create command.

That said, we’re going to add an indexer and a real-time search box to the blog. For that we’ll be using the islands pattern, that Astro provides, but also, I’m going to build a custom integration for the indexer.

The end result will look like this:

The focus is not going to be the actual search, but rather, the fact that we’re adding an interactive component on an otherwise static website.

Let’s start with the indexing of our content.

Creating your first Astro Integration

Astro Integrations are like plugins you can create for your website that will add behavior to one (or more) of the stages of the build process.

In our case, we need to index the generated content, so we’ll make sure to hook our integration right at the end of it. That way, we’re sure we’re indexing every single blog post.

For that, we’ll go to the astro.config.mjs file located at the root of our folder, and we’ll add a function called indexMySite that looks like this:

BTW, you’ll also need to install the parse-md package, so we can read the frontmatter of the Markdown files.

That said, this function returns an object that has a name property and a hooks property. They’re both required properties, but the first one can have anything you want, it’s just a name you give your integration. The second one though, is where you define exactly which hooks will you be using, in our case, we only care about astro:build:done because we want our code to run right after the building process is done.

There are several other hooks you can use as well, so make sure you check out their documentation.

For the hook key, we’ll define a function that takes an array of pages and routes . We’ll use the latter for this build, iterating over it, making sure we just take into account blog pages (I’m filtering out anything that doesn’t end with a .md extension) and then using parse-md to get the metadata of the file and add it into an array.

In the end, I’ll create the “index” of our search engine by saving the array into a JSON file inside the public directory of our blog. That way it’s easily accessible by our island component.

With the function ready, we just need to make sure Astro knows to use it, so inside the same file, go to the defineConfig function, and make sure to add the call to our new function inside the integrations array.

In my case, it looks like this:

Did you like what you read? Consider subscribe to my FREE newsletter where I share my 2 decades worth of wisdom in the IT industry with everyone. Join “The Rambling of an old developer” !

Adding the search component

Now it’s time to build the search, and since Astro allows for the integration of components from different frameworks, I’m going to use React for this one.

So first things first, I need to add support for React, so I’ll run npx astro add react

That command will install React for me and it’ll also add it as an integration to the astro.config.mjs file.

With that out of the way, I can build my own Search component inside the src/components folder. Notice how I’m not having to use a special folder for my interactive components (unlike Fresh, where I have a special islands folder).

The component in our case is very simple, all we have to do is load the index.json from the public folder, and perform a search inside it:

In this file I’ve defined two components, the Search component that I’m exporting. This component will take care of rendering the input box, and performing the search when the user starts typing.

The second component though, is the ResultsList component, and this one will render the list of results. I’m not exporting it, because I’m only using it from within the previous one.

Now, with our component ready, I can go to the Header.astro file, which contains the code for the header of our blog, and I can add my component:

Notice how on line 17 I’ve added my component.

There is a catch though. If you add your component as I did, Astro will treat it like any other component, and it’ll render it on the server, but it will not add the interactive code on the client side.

By default, all components in Astro are SSR. But we need this one to be hydrated on the client side. Essentially, we need to tell Astro that this is an island of interactivity.

How do we do that? Astro provides several client: directives that can be added. They tell Astro when to hydrate the component.

In our case, we need it working right after the page ends up loading, so we’ll go with client:load , like this:

Again, check on line 17, now that the directive is added, Astro will render it correctly and it will enable the JavaScript code inside it.

We’ve successfully rendered our first island inside Astro!

And that’s it, islands are a very simple concept that enables frameworks to only serve the absolutely required JavaScript to the client, keeping the rest on the server.

Defining a component as an island is as simple as passing a client: directive when adding it to the HTML. And finally, we also quickly covered how to extend the behavior of Astro by adding a custom integration.

Is this your first time using Astro? What did you think about it? Leave a comment and let’s talk about it!

Build apps with reusable components like Lego

Bit’s open-source tool help 250,000+ devs to build apps with components.

Turn any UI, feature, or page into a reusable component — and share it across your applications. It’s easier to collaborate and build faster.

Learn more

Split apps into components to make app development easier, and enjoy the best experience for the workflows you want:

Micro-Frontends

Design System

Code-Sharing and reuse

Monorepo

--

--

I write about technology, freelancing and more. Check out my FREE newsletter if you’re into Software Development: https://fernandodoglio.substack.com/