Islands Architecture

Islands Architecture is the idea that a page is mostly static HTML with isolated interactive "islands" that load their own behavior independently. We've already applied this thinking to the backend (modular routes and functions) and the frontend (component templates). Now let's take it further: individual Markdown files can carry their own styles, scripts, and dynamic data.

Page-specific styles

Any Markdown file can include a <style> block. LiteNode passes the rendered HTML to the template as-is, so the browser receives it and applies the styles only for that page.

Add this to any .md file, right after the frontmatter:

---
title: My Page
---

<style>
  .highlight-box {
    background: rgba(129, 140, 248, 0.1);
    border-left: 3px solid #818cf8;
    padding: 1rem;
    border-radius: 4px;
  }
</style>

# My Page

<div class="highlight-box">This box only appears on this page.</div>

The style tag renders into the HTML string and affects only what's on that page. Global styles are unaffected.

Page-specific scripts

The same approach works for JavaScript:

<script>
  document.addEventListener("DOMContentLoaded", () => {
    const boxes = document.querySelectorAll(".highlight-box")
    boxes.forEach(box => {
      box.addEventListener("click", () => box.classList.toggle("active"))
    })
  })
</script>

The script runs only when that page is loaded.

Page-specific dynamic data

You can generate data on the server specifically for one page and inject it via the data object.

As an example, generate a table of contents for pages that need one:

In routes/tutorialRoute.js:

const html_content = marked.parse(current.content)
const html_toc = app.generateTOC(html_content)

res.render("layouts/index.html", {
    title,
    description,
    html_content,
    html_toc,
    tutorialRoute: true,
})

generateTOC extracts all heading tags from the rendered HTML and returns a nested <ul> list of links. Then in the template:

{{#if html_toc}}
    <aside class="toc-sidebar">
        <span class="toc-label">On this page</span>
        {{html_toc}}
    </aside>
{{/if}}

The TOC only appears when there are headings — otherwise it's more noise than signal.

The bigger picture

Each Markdown file is its own island: it has its own styles and its own scripts. The shared templates provide structure. The individual files provide character.

This is what makes the approach scale cleanly — adding a new page with unique behavior doesn't require touching the global layout, the routes, or the CSS.