Astro Server Islands explained: A complete step-by-step tutorial

Astro Server Islands.jpeg
By Bhuwan Mishra
Read time 8 min
Posted on 7 May 2025

The need for fast and scalable applications and websites has grown over the years. Traditional CMSs like WordPress and Drupal often struggle to meet those needs, especially without modern solutions like headless CMSs and the Astro server islands approach as websites and apps grow in complexity.

The rise of headless CMS, like BCMS, decouples content management from the front ends, allowing greater flexibility in integrating the content within a mobile application or website. By doing so, they provide greater flexibility, enabling developers to use any technology stack for the front end while managing content through a powerful backend system.

What Is Astro?

Astro is like the minimalist kid of web development, helping developers to craft beautiful, lightning-fast websites by cutting out unnecessary baggage.

If you love the idea of websites that load instantly, Astro is your new best friend. Instead of bombarding the browser with hefty JavaScript, it prioritizes static content and only adds interactivity when you want it. The result? Sites that are superfast and don’t waste bandwidth or time.

Astro Server Islands architecture: Fast, interactive, isolated

Server Islands is a smart technique offering the performance of static site generation while still allowing for rich, interactive components, only when and where they're needed. It’s Astro’s way of giving you speed without sacrificing functionality.

This paradigm optimizes web performance by splitting a page into "islands" of interactivity. Astro Islands is part of Astro’s broader focus on static site generation with minimal client-side JavaScript.

Unlike traditional frontend frameworks, Astro Island architecture hydrates only the interactive components. This way, Astro serves the page as static HTML first (superfast) and then "wakes up" only the interactive parts, minimizing JavaScript and keeping the page performance high.

Each dynamic component (the "island") is isolated from the rest of the page. So, if you have a comment section, only that small, isolated piece will run JavaScript in the browser. The rest of the page remains static, providing the best performance for the bulk of the content.

Every island component makes use of client:* directive. Here’s a quick glance at what each directive does and when to use it:

island component

Build faster, manage smarter: Why integrate BCMS with Astro

A headless CMS, like BCMS, delivers content across channels. No matter if it's a web application or a mobile application, developers can integrate content across platforms.

With BCMS managing your dynamic data, Astro ensures that your site is fast and responsive, providing an optimal balance of content flexibility and page speed.

BCMS ensures your content is always fresh and easily updatable, while Astro’s static-first approach minimizes the complexity of handling front-end code.

BCMS acts as a headless CMS, which means you can separate your content management from your website’s codebase. This gives content editors full control to update or add content without worrying about how it will be displayed. It makes updates faster and safer.

As your website grows, BCMS scales seamlessly with it. This is a perfect solution for businesses looking to scale their site with dynamic content, all while maintaining optimal load times.

By combining Astro’s optimized static content delivery with BCMS’s easy-to-use content management system, you get the best of both worlds: users get ultra-fast pages, and content creators get a smooth, intuitive interface for managing site updates. You’re not sacrificing speed for flexibility, or vice versa.

BCMS multilingual support makes it easy to deliver your content in different languages.

Prerequisites

To follow along with this tutorial, you’ll need:

  • Node.js: This guide recommends using Node.js LTS version 22.14.0. You can check your Node.js version using the command:

node -v
  • BCMS account: Ensure you’ve created a BCMS account. It’s free to create one.

  • The completed project is on GitHub. Feel free to clone it and test.

  • Previous knowledge of working with APIs and Astro would be helpful.

Create an Astro Project

The BCMS CLI provides a couple of astro-templates to start with. Here is the list of all Astro templates you can choose from. I’ll choose the simple-blog template to start with:

Step 1: Choose a starter template

npx @thebcms/cli create astro starter simple-blog

This command will ask you to log in to your BCMS account to configure the API and settings automatically.

astro project

Step 2: Set the project name

After a successful login, it will ask for a project name.

project name.
3 tut blog.png

Step 3: Install dependencies and run

As usual, you can install dependencies with npm install.

cd tut-blog && npm install && npm run dev

A quick tip: to save some time while installing dependencies, you can use bun as well. Bun is a new JavaScript runtime and can be used as a Node.js compatible package manager.

The project structure

Upon the successful project creation, you’ll get to see a similar project structure:

├── astro.config.mjs

├── bcms

│ └── types

├── bcms.config.cjs

├── package.json

├── package-lock.json

├── public

│ ├── favicon.svg

│ └── logo-dark.png

├── README.md

├── src

│ ├── bcms-client.ts

│ ├── components

│ ├── env.d.ts

│ ├── layouts

│ ├── pages

│ └── utils

├── tailwind.config.mjs

└── tsconfig.json

The bcms.config.cjs config file loads the BCMS project details from the .env file. The BCMS CLI handles the configuration automatically so that you can just focus on creating content for your website.

BCMS dashboard walkthrough

Let’s see! What entries and templates have been created in BCMS? You can consider Templates as post templates if you come from a traditional CMS background like WordPress. It simply tells what makes a post. And Entries, in the BCMS, are like individual blog posts.

Switch project

With a single BCMS account, you can manage different projects. Each project will have its own set of templates and entries.

Simply switch to the tutblog project from the dropdown as shown here. The project name might be different in your case if you’ve set up a different name upon creation.

Switch project

Add a new blog post

Add a new Blog Post

A content editor needs to interface only with the Entries component most of the time. To create a new entry, simply click on create new entry button.

create new entry

And add details of your new Astro blog post.

blog details

After adding a new blog post, make sure to restart the project with npm run dev.

You’ll get to see the newly created post on the homepage:

8 new post.png

Add dynamic components (The Astro Islands way)

For blogs, implementing interactive image galleries and slideshows is an effective way to enhance the user experience. Our simple-blog Astro starter template comes preconfigured with Vue integration. So, for this tutorial, we’ll go with pre-made Vue components for our project.

npm i vue3-carousel

Upon successful installation, your package.json file will get updated.

9 carousel.png

Step 2: Add a new field to Blog Templates in BCMS

I’ll add a new Media field to the existing Blog template, which will hold a list of images.

new field

After adding the field, restart the project with the command “npm run dev”. This will pull new changes from your BCMS project.

Also, head over to the Blog entries and modify at least one of the blogs to include some media for the Carousel field.

Carousel field

Step 3: Create an ImageCarousel Vue component

Simply, I’ll create a Vue component that will take a prop called collection to iterate over all the JSON media objects. So, open and edit the file src/components/image-carousel.vue with the contents:

(This example is taken from the Vue3-carousel Getting started section, but I have modified it to load images from the BCMS project.)

<script setup>
import { bcms } from "../bcms-client";
import "vue3-carousel/carousel.css";
import { Carousel, Slide, Pagination, Navigation } from "vue3-carousel";
const props = defineProps({
  collection: {
    type: Array,
    required: true,
  },
});
const config = {
  height: 600,
  itemsToShow: 1,
  gap: 5,
};
</script>
<template>
  <Carousel v-bind="config">
    <Slide v-for="media in collection" :key="media._id">
      <img
        :src="`${bcms.cmsOrigin}${bcms.media.toUri(media._id, media.name)}`"
        alt="media.name"
      />
    </Slide>
    <template #addons>
      <Navigation />
      <Pagination />
    </template>
  </Carousel>
</template>
<style>
.carousel {
  --vc-pgn-background-color: rgba(255, 255, 255, 0.7);
  --vc-pgn-active-color: rgba(255, 255, 255, 1);
  --vc-nav-background: rgba(255, 255, 255, 0.7);
  --vc-nav-border-radius: 100%;
}
img {
  border-radius: 8px;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
</style>

Step 4: Add ImageCarousel to Blog posts

Now, you need to add your newly created Vue component to the blog pages. So, open and edit file src/pages/blog/[...slug].astro. It should look like:

---
import { bcms } from '../../bcms-client';
import type { BlogEntry, BlogEntryMetaItem } from '../../../bcms/types/ts';
....
import { BCMSImage, BCMSContentManager } from '@thebcms/components-vue';
import ImageCarousel from '../../components/image-carousel.vue';

export async function getStaticPaths() {
    const blogs = (await bcms.entry.getAll('blog')) as BlogEntry[];
    return blogs.map((blog) => {
        const meta = blog.meta.en as BlogEntryMetaItem;
        return {
            params: {
                slug: meta.slug,
            },
        };
    });
}
....
                        
<div class="leading-none">
   {toReadableDate(data.meta.date)}
</div>

{data.meta.carousel ?
    <ImageCarousel collection={data.meta.carousel} client:load />
    :
    <BCMSImage
       client={bcmsConfig}
       media={data.meta.cover_image}
       client:load
    />
}
</header>
          .....

Let’s understand what I just did. I used conditional rendering to render ImageCarousel only if the Carousel field for corresponding blog entries is present. If it’s not present, render cover_image instead.

By adding the directive client:load to my component, I am instructing Astro to build the component at compile time but defer loading and running the JavaScript for it until the page is fully loaded in the browser.

Step 6: Preview and customize

Now, if you run the project, you’ll get to see an image carousel component on your blog page.

Feel free to customize the carousel by setting its height and the number of images to show in a frame.

Blog preview

Preparing the application for production

In the previous section, I've already created a dynamic component to integrate into my blog post. The command “npm run dev” is only intended for the development phase. While deploying your production application, you first need to run “npm run build”.

blog production

Upon successful completion of npm run build, you’ll get to see a new dist directory in the project directory. It’ll have a list of HTML pages to serve.

To see how your production application looks, run this command:

npm run preview

Now, a user navigating to your website doesn’t need to load 100KB of JavaScript first. The pages will be served to the user without any delay since there is no database involved and there’s no compilation to generate HTML pages. That’s a huge advantage over a traditional CMS.

A quick disclaimer: in production, you don’t even need to run “npm run preview”. It’s just there for you to see how your project builds. Instead, you can directly upload the dist directory to the document root of nginx or Apache server.

Understanding partial hydration in Astro Server Islands

Islands and their architecture will make you think of what’s most important for a user at first. If I had been using frameworks like React JS, Vue.js instead of Astro for my blog, I would have needed to load around 100KB, plus even before it could display even a simple heading. That’s where partial hydration shines!

Consider a scenario to integrate an option to collect feedback from readers. The feedback section only needs to be interactive when a user scrolls to that section, so it makes sense to hydrate it only when it enters the viewport. With client:visible directive, you can achieve it.

---
import BlogContent from '../components/BlogContent.astro';
import CommentSection from '../components/CommentSection.vue';
---
<BlogContent title="How to Build Websites with Astro and BCMS" />
<p>Welcome to this tutorial blog...</p>
<!-- This  is an interactive component -->
<CommentSection client:visible />

Astro offers a lot of flexibility in regards to when to hydrate interactive components. A common confusion arises about where to use client:load and client:visible directive?

The simple answer is, use client:load when the component is above the fold and needs to work ASAP, and use client:visible when the component is below the fold or no interaction is needed immediately.

Benefits of using Astro Islands

Faster initial load times

With its hybrid rendering approach, visitors can access the content much quicker compared to traditional frontend rendering, which adds a lot of JavaScript to load at first glance.

Better Web Core Vitals

Astro sites improve web core vitals. It reduces Largest Contentful Paint (LCP) and First Contentful Paint (FCP), leading to a better user experience and SEO focus.

Add interactivity without bloat

As your site grows in complexity, you can introduce more interactive features (like live chat, filters, or dynamic content) without impacting the speed of the entire page.

Flexibility

With Astro, you can combine SolidJS, Svelte, and Preact components within a single application.

Imagine you want to use some components from popular UI component libraries like MUI, ANT. With Astro, do run a npm install and import and use the component as usual.

Conclusion: Start building Astro Island websites

Astro architecture gives a new perspective on building user interfaces and websites with minimal JavaScript, only when necessary. Not to mention, Astro has made static site generation, server-side rendering, and cross-framework components reuse simpler and enjoyable. As a developer, I advocate for its simplicity and efficiency.

Combining Astro with BCMS is the perfect solution for creating an efficient, easy-to-manage website for your small business. With this combination, you can save time and costs, go live quickly, and continue to optimize your online presence.

Whether you're showcasing your products, publishing news, or interacting with customers, Astro and BCMS provide your small business with the power and flexibility you need to focus on growing your business, not on technical challenges.

It takes a minute to start using BCMS

Gradient

Join our Newsletter

Get all the latest BCMS updates, news and events.

You’re in!

The first mail will be in your inbox next Monday!
Until then, let’s connect on Discord as well:

Join BCMS community on Discord

By submitting this form you consent to us emailing you occasionally about our products and services. You can unsubscribe from emails at any time, and we will never pass your email to third parties.

Gradient