#Server Island and HTMX

5 messages · Page 1 of 1 (latest)

vital elbow
#

How do I use https://docs.astro.build/en/guides/server-islands/#server-island-components server islands... I want to render some astro components on click and have them populate with data from my cms, so basically its not fetching the data until it needs to (user clicks on a card, the component opens in a panel).

How can i do this? do i use htmx? been trying htmx but the styles and scripts get confusing.

Docs

Combine high performance static HTML with dynamic server-rendered content.

gentle reefBOT
#

Hi @vital elbow. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

Great question! You're describing two slightly different patterns, and it's worth clarifying what each one does before picking the right tool.

What Server Islands Do

Server islands (server:defer) are designed to defer rendering of a component at page load time — they render in the background while the rest of the page loads immediately. They are not triggered by user interaction (like a click). They load automatically when the page is requested, just independently from the main page render. [server islands guide]

So server islands alone won't solve your "fetch on click" use case.


What You Actually Want: Page Partials + HTMX

For your use case — render a component only when a user clicks a card — the right Astro feature is Page Partials, which pair well with htmx. [page partials]

Here's how it works:

  1. Create a partial .astro page that fetches your CMS data and renders the panel content.
  2. Use htmx on your card to request that partial on click and inject it into a panel.

Example

src/pages/partials/card-detail.astro — fetches from your CMS on demand:

---
export const partial = true;

// This only runs when the partial is requested (i.e., on click)
const response = await fetch('<https://your-cms.com/api/item/123'>);
const data = await response.json();
---
<div>
  <h2>{data.title}</h2>
  <p>{data.description}</p>
</div>

src/pages/index.astro — triggers the fetch on click:

#
<html>
  <head>
    <title>My Page</title>
    <script src="<https://unpkg.com/htmx.org@1.9.6">
      integrity="sha384-FhXw7b6AlE/jyjlZH5iHa/tTe9EpJ1Y55RjcgPbjeWMskSxZt1v9qkxLJWNJaGni"
      crossorigin="anonymous"></script>
  </head>
  <body>
    <div id="detail-panel"></div>

    <button
      hx-get="/partials/card-detail/"
      hx-trigger="click"
      hx-target="#detail-panel"
      hx-swap="innerHTML"
    >
      Open Card
    </button>
  </body>
</html>

About the Styles/Scripts Issue

The docs do note an important caveat: partials should not be used if the component contains scoped styles or scripts, as these will be stripped from the HTML output. If you need scoped styles, you're better off using regular (non-partial) pages with a frontend library that can merge <head> content. [page partials]

Workaround: Use global CSS classes (e.g., from Tailwind or a global stylesheet) inside your partials instead of scoped <style> blocks.


Summary

Feature When it loads Triggered by
server:defer (Server Island) Page load (deferred) Automatic
Page Partial + htmx On demand User interaction ✅

For your use case, Page Partials + htmx is the correct approach.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@vital elbow Kapa.ai is still learning and improving, please let me know how I did by reacting below.