diff --git a/docs/2-guides/1-building-a-feedback-form/README.md b/docs/2-guides/1-building-a-feedback-form/README.md
index 3f12802c..17168ea0 100644
--- a/docs/2-guides/1-building-a-feedback-form/README.md
+++ b/docs/2-guides/1-building-a-feedback-form/README.md
@@ -81,17 +81,17 @@ jahiaComponent(
nodeType: "hydrogen:feedbackWidget",
componentType: "view",
},
- ({ question }: Props) => ,
+ ({ question }: Props) => ,
);
```
You'll need to restart `yarn dev` for Vite to collect your new client files, but once pushed, should see the exact same button as before, but now it will alert "Hello World!" when clicked.
-The `RenderInBrowser` component is a wrapper that will ensure the code of `Widget` gets forwarded to the browser, enabling what is called Island Architecture: this component will be rendered client-side, but the rest of the page will remain server-rendered. This is a great way to improve performance, as it allows to only ship the JavaScript that is needed for the interactive parts of your page.
+The `Island` component is a wrapper that will ensure the code of `Widget` gets forwarded to the browser, enabling what is called Island Architecture: this component will be rendered client-side, but the rest of the page will remain server-rendered. This is a great way to improve performance, as it allows to only ship the JavaScript that is needed for the interactive parts of your page.
-The `props` prop of `RenderInBrowser` allows you to pass props to the component that will be rendered in the browser. Because they will be sent to the browser, they should be serializable.
+The `props` prop of `Island` allows you to pass props to the component that will be rendered in the browser. Because they will be sent to the browser, they should be serializable.
-If you nest children to `RenderInBrowser`, they will be displayed until `Widget` is loaded. This is where you can put a loading message for instance: `The widget is loading...`.
+If you nest children to `Island` in `clientOnly` mode, they will be displayed until `Widget` is loaded. This is where you can put a loading message for instance: `The widget is loading...`.
You now have all the tools needed to build any client-side component, but keep on reading to learn how to send data to jCustomer.
diff --git a/docs/2-guides/2-accessibility-and-performance/README.md b/docs/2-guides/2-accessibility-and-performance/README.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/2-guides/2-island-architecture/README.md b/docs/2-guides/2-island-architecture/README.md
new file mode 100644
index 00000000..c37a98e5
--- /dev/null
+++ b/docs/2-guides/2-island-architecture/README.md
@@ -0,0 +1,337 @@
+# Island Architecture
+
+Jahia JavaScript Modules offers a first-class support for this architectural pattern, allowing interactivity without compromising on performance.
+
+## What is Island Architecture?
+
+We have written a [complete article on the topic,](https://www.jahia.com/blog/leveraging-the-island-architecture-in-jahia-cms) but here is a quick summary:
+
+- Instead of shipping fully static or fully dynamic pages, Island Architecture is the middle ground where most of the page is static, but specific parts are made interactive on page load.
+
+ [A page mockup with two interactive islands: a navigation bar and a video player](./islands.svg)
+
+ In this example, the page is mostly static, with the exception of the `` and `` components, which are the islands of interactivity of the page. After the initial page load, JavaScript is used to make them interactive without affecting the rest of the page.
+
+- Island Architecture offers the performance and SEO benefits of server-side rendering, but makes it easy to create highly interactive user experiences.
+
+- The difference between islands and using server-side rendering with a bit of jQuery is that, when building islands, the exact same React components run on the server and the client. Having a single-language codebase is easier to maintain in the long run.
+
+## The `` component
+
+The `` component is the base of the Island Architecture in Jahia. It can be imported from the `@jahia/javascript-modules-library` and used in any React view or template:
+
+```tsx
+import { Island } from "@jahia/javascript-modules-library";
+```
+
+As with all imports from `@jahia/javascript-modules-library`, the `` component **can only be used on the server.**
+
+Server files, files in `.server.tsx`, are used as entry points for your server code. They contain views and templates to be registered by Jahia.
+
+Client files, files in `.client.tsx`, are used as entry points for your client code. All client files, as well as all their imports, will be made available for the browser to download. They should not contain any sensitive information, and cannot import server APIs (`@jahia/javascript-modules-library` and `.server.tsx` files).
+
+In client files, **only the default export** can be used to create an island. For instance, here is a minimal interactive button:
+
+```tsx
+// Button.client.tsx
+export default function Button() {
+ return (
+
+ );
+}
+```
+
+If you use this button directly in a server file, it will not work as you might have expected:
+
+```tsx
+// default.server.tsx
+import { jahiaComponent } from "@jahia/javascript-modules-library";
+import Button from "./Button.client.tsx";
+
+jahiaComponent(
+ {
+ componentType: "view",
+ nodeType: "hydrogen:example",
+ },
+ () => (
+
+
Hello World
+
+ {/* ❌ Do not do that, it does not work */}
+
+
+
+ ),
+);
+```
+
+Your button will be sent properly to the client, but **not be made interactive.** This is because the default rendering mode of JavaScript Modules (and Jahia in general) is server-side rendering. **No JS is sent to the browser by default,** and therefore your button doesn't get its event listener attached.
+
+The solution is the `` component:
+
+```tsx
+// default.server.tsx
+import { Island, jahiaComponent } from "@jahia/javascript-modules-library";
+import Button from "./Button.client.tsx";
+
+jahiaComponent(
+ {
+ componentType: "view",
+ nodeType: "hydrogen:example",
+ },
+ () => (
+
+
Hello World
+
+ {/* ✅ This works*/}
+
+
+
+ ),
+);
+```
+
+The `` component always takes a `component` prop, which is the React component to be rendered as an island. It must be the default export from a `.client.tsx` file, otherwise it will not work.
+
+It can also take other props, which are detailed in the following sections.
+
+## `clientOnly`
+
+By default, all islands are rendered on the server and made interactive on the client (the process is called [hydration](https://18.react.dev/reference/react-dom/client/hydrateRoot#hydrating-server-rendered-html)). This is great for the perceived performance of your application because even before being interactive, your page can be read by the user.
+
+Sometimes, the server cannot render the content (for instance, because it needs browser APIs like `window`, `document` or `navigator`). For these cases, the `` component has a `clientOnly` mode, which will skip server-side rendering and only render your component on the client.
+
+```tsx
+// Language.client.tsx
+export default function Language() {
+ // The `navigator.language` API is only available in the browser,
+ // and would error on the server as being undefined
+ return
According to your browser, you speak {navigator.language}.
;
+}
+```
+
+```tsx
+// default.server.tsx
+import { Island, jahiaComponent } from "@jahia/javascript-modules-library";
+import Language from "./Language.client.tsx";
+
+jahiaComponent(
+ {
+ componentType: "view",
+ nodeType: "hydrogen:example",
+ },
+ () => (
+
+
+
+ ),
+);
+```
+
+This ensures that `` only runs on the client (the browser).
+
+## `props`
+
+Your island component, as any React component, may take props. To do so, pass all the props of your component through the `props` prop of ``.
+
+Because these props will be sent to the browser, two constraints apply:
+
+- **Do not pass any sensitive information,** such as API keys.
+- **The props must be serializable,** which means only a subset of all JS objects can be used. The serialization is performed by [devalue](https://www.npmjs.com/package/devalue), which offers a wider range of supported types than `JSON.stringify`, but still has limitations. For instance, you cannot send a JCR node through the props of a client component.
+
+Here is an example of what you can do:
+
+```tsx
+// Pizza.client.tsx
+export default function Pizza({
+ toppings,
+ selection,
+}: {
+ /** All available pizza ingredients */
+ toppings: string[];
+ /** The user's current selection */
+ selection: Set;
+}) {
+ return (
+ // You can use React fragments, your island does not have to be a single element
+ <>
+
+ >
+ );
+}
+```
+
+```tsx
+// default.server.tsx
+import { Island, jahiaComponent } from "@jahia/javascript-modules-library";
+import Pizza from "./Pizza.client.tsx";
+
+jahiaComponent(
+ {
+ componentType: "view",
+ nodeType: "hydrogen:example",
+ },
+ () => (
+
+
+
+ ),
+);
+```
+
+Our `` component receives its props during both server-side and client-side rendering.
+
+## `children`
+
+Last but not least, the `children` prop, which is the technical name for all children passed to a React component. (`} />` is the same as ``.)
+
+The `` component can take children, but its behavior depends on its `clientOnly` prop.
+
+In default mode (without `clientOnly`), the children are rendered on the server and sent to the client, as children of your island component. The children will not be made interactive.
+
+This behavior enables components like accordions, where the `` is not a leaf of the component tree.
+
+[Schema of the accordion component](./accordion.svg)
+
+Such a component can be implemented as follows:
+
+```tsx
+// Accordion.client.tsx
+import type { ReactNode } from "react";
+
+export default function Accordion({ children }: { children: ReactNode }) {
+ // The accordion can be opened and closed
+ const [isOpen, setIsOpen] = useState(false);
+
+ return (
+
+
+
+ {/* Children will be inserted here: */}
+ {children}
+
+
+ );
+}
+```
+
+And on the server:
+
+```tsx
+// default.server.tsx
+import { Island, jahiaComponent } from "@jahia/javascript-modules-library";
+import Accordion from "./Accordion.client.tsx";
+
+jahiaComponent(
+ {
+ componentType: "view",
+ nodeType: "hydrogen:example",
+ },
+ () => (
+
+
+
I'm rendered on the server!
+
+
+ ),
+);
+```
+
+A few things to note:
+
+- The `{children}` insertion point must always be there. If you want to hide the children of your component, use CSS instead of a JS condition. Otherwise, they will not be sent to the client and your component will appear to have no children.
+- Children will be wrapped in a `jsm-children` element. This should not affect your code most of the time, but don't use the `>` CSS selector to target children of your component.
+
+In `clientOnly` mode, the children of an island will not be used as children of your island component. Instead, they will be rendered on the server and used as a placeholder until the client component is loaded.
+
+```tsx
+// default.server.tsx
+import { Island, jahiaComponent } from "@jahia/javascript-modules-library";
+import Map from "./Map.client.tsx";
+
+jahiaComponent(
+ {
+ componentType: "view",
+ nodeType: "hydrogen:example",
+ },
+ () => (
+
+
+ {/* Placeholder until has loaded */}
+
The map is loading...
+
+
+ ),
+);
+```
+
+This is a good UX practice to tell users that your site is currently loading instead of leaving an empty space. It can also prevent [layout shifts](https://web.dev/articles/cls) when the component finally loads.
+
+## Implementation details
+
+It is not necessary to know any of this to create a successful Jahia integration, but it might come in handy if you need to debug your application:
+
+- The `` component will be sent to the client as a `` custom element. In client only mode, it will have a `data-client-only` attribute.
+
+ Do not target `jsm-island` nor `jsm-children` in your CSS as they are implementation details and may change in non-major versions.
+
+- Client-side libraries used by your islands will be imported on the server, by the chain of top-level imports:
+
+ ```ts
+ // Map.client.tsx
+ import { foo, bar } from "map-provider";
+
+ export default function Map() {}
+
+ // default.server.tsx
+ import Map from "./Map.client.tsx"; // Will indirectly import "map-provider"
+ ```
+
+ This is not an issue for modern, well-built libraries, but can be troublesome for libraries with top-level side effects. If you have error messages on the server like `window/document is not defined`, it is likely that one of your dependencies is not compatible with server-side rendering (SSR).
+
+ To work around this problem, you can use the `import()` function in an effect instead of a top-level import:
+
+ ```tsx
+ // Map.client.tsx
+ import { useEffect } from "react";
+
+ export default function Map() {
+ // useEffect only runs on the client, it is skipped during SSR
+ useEffect(() => {
+ import("map-provider").then(({ foo, bar }) => {
+ // Use foo and bar here
+ });
+ }, []);
+ }
+
+ // default.server.tsx
+ import Map from "./Map.client.tsx"; // "map-provider" no longer imported here
+ ```
+
+ You can also report this issue (_the library is not compatible with server-side rendering_) to the library maintainers.
+
+- We have written a complete article on the implement details of the `` component. You can read it on our blog: [Under the Hood: Hydrating React Components in Java](https://www.jahia.com/blog/under-the-hood-hydrating-react-components-in-java).
diff --git a/docs/2-guides/2-island-architecture/accordion.svg b/docs/2-guides/2-island-architecture/accordion.svg
new file mode 100644
index 00000000..2f978119
--- /dev/null
+++ b/docs/2-guides/2-island-architecture/accordion.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/2-guides/2-island-architecture/islands.svg b/docs/2-guides/2-island-architecture/islands.svg
new file mode 100644
index 00000000..b9084c8a
--- /dev/null
+++ b/docs/2-guides/2-island-architecture/islands.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/docs/2-guides/3-building-a-menu-and-sitemap/README.md b/docs/2-guides/3-building-a-menu-and-sitemap/README.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/2-guides/4-adding-icons/README.md b/docs/2-guides/4-adding-icons/README.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/2-guides/5-adding-tailwind/README.md b/docs/2-guides/5-adding-tailwind/README.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/2-guides/6-building-for-production/README.md b/docs/2-guides/6-building-for-production/README.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/2-guides/7-rendering-markdown/README.md b/docs/2-guides/7-rendering-markdown/README.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/2-guides/8-rss-feed/README.md b/docs/2-guides/8-rss-feed/README.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/2-guides/9-debugging/README.md b/docs/2-guides/9-debugging/README.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/2-guides/A-using-web-components/README.md b/docs/2-guides/A-using-web-components/README.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/2-guides/README.md b/docs/2-guides/README.md
index 900c96c0..fdd0aac9 100644
--- a/docs/2-guides/README.md
+++ b/docs/2-guides/README.md
@@ -3,15 +3,7 @@
This section contains independent, self-contained guides that help you build specific features or solve specific problems. Each guide is a step-by-step tutorial that you can follow to achieve a specific goal.
- [Building a Feedback Form](./1-building-a-feedback-form/)
-- [Accessibility and Performance](./2-accessibility-and-performance/)
-- [Building a Menu and Sitemap](./3-building-a-menu-and-sitemap/)
-- [Adding Icons](./4-adding-icons/)
-- [Adding Tailwind](./5-adding-tailwind/)
-- [Building for Production](./6-building-for-production/)
-- [Rendering Markdown](./7-rendering-markdown/)
-- [RSS Feed](./8-rss-feed/)
-- [Debugging](./9-debugging/)
-- [Using Web Components](./A-using-web-components/)
+- [Island Architecture](./2-island-architecture/)
More guides are coming soon, and contributions are welcome!
diff --git a/docs/3-reference/2-tools/README.md b/docs/3-reference/2-tools/README.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/3-reference/3-jcr/README.md b/docs/3-reference/3-jcr/README.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/3-reference/4-mixins/README.md b/docs/3-reference/4-mixins/README.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/3-reference/5-children-and-area/README.md b/docs/3-reference/5-children-and-area/README.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/3-reference/6-nav-builder/README.md b/docs/3-reference/6-nav-builder/README.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/3-reference/7-ui-extensions/README.md b/docs/3-reference/7-ui-extensions/README.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/3-reference/8-single-directory-components-and-resources/README.md b/docs/3-reference/8-single-directory-components-and-resources/README.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/3-reference/9-java-interoperability/README.md b/docs/3-reference/9-java-interoperability/README.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/3-reference/A-ssr-and-hydration/README.md b/docs/3-reference/A-ssr-and-hydration/README.md
deleted file mode 100644
index e69de29b..00000000
diff --git a/docs/README.md b/docs/README.md
index 03e156c0..73dcce36 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -25,6 +25,7 @@ Start here: [Setting up your dev environment](./1-getting-started/1-dev-environm
This section contains independent, self-contained guides that help you build specific features or solve specific problems. Each guide is a step-by-step tutorial that you can follow to achieve a specific goal.
- [Building a Feedback Form](./2-guides/1-building-a-feedback-form/)
+- [Island Architecture](./2-guides/2-island-architecture/)