Skip to main content

Crate islands

Crate islands 

Source
Expand description

§islands — umbrella crate for islands.rs

This is the single dependency users should add to consume the islands.rs framework. All public APIs from the underlying sub-crates are re-exported here so a downstream Cargo.toml looks like:

[dependencies]
islands = { path = "...", features = ["basecoat"] }   # basecoat optional

and a downstream main.rs looks like:

use islands::prelude::*;

§What’s in the box

The framework is a Rust SSR + island-hydration system with shared-core WASM code splitting. The server emits plain HTML with labelled island markers; each island is mounted independently on the client. No whole-page hydration, no virtual-DOM reconciliation, no hydration-mismatch failure mode. See plan.md for the full architectural rationale.

Modules at a glance:

Re-exportWhat it provides
island_marker, page_shell, [page_shell_streaming_head]Server-side HTML markup helpers that emit island placeholders, the document shell, and the streaming-shell head fragment.
[Suspense], [render_streaming], [render_streaming_with], [HtmlChunk], [StreamError], [REPLACE_SCRIPT]Streaming SSR with Suspense boundaries — out-of-order chunk delivery, <template> + $ISLANDS_REPLACE script-based slot filling.
Manifest, ManifestEntryContent-hashed asset manifest loaded at startup; page_shell resolves URLs through it.
cnTailwind class-string merger with shadcn-style conflict resolution.
Signal, register_island, mount_all, init_panic_hook, on_click, on_event, set_class, text_binding, call_action, [navigate]WASM page-author API (available on both wasm32-unknown-unknown and the host target — the rlib path is unconditional). [navigate] triggers client-side navigation programmatically (same path as a link click; full-load fallback on error).
action_router, ActionContext, ActionError, ActionRegistry (non-wasm)Server-side typed-action plumbing.
cache_layer (non-wasm)Tower middleware that sets Cache-Control by path pattern and honors If-None-Match for 304 responses on static assets.
actions_sharedRe-exported sub-crate of pure types shared between server and WASM (request/response shapes).
basecoat_core, basecoat_components, basecoat_css (behind the basecoat feature)shadcn-style UI components and rsx macros, opt-in.

§Suspense — API shape

[Suspense] is invoked through rsx interpolation rather than as a literal tag, because the basecoat-macros rsx! macro auto-routes PascalCase tags to ::basecoat_components::<snake>. (Consumers that want rsx! add basecoat-macros as their own direct dependency — islands does not pull it for them; see “The basecoat feature” below.)

rsx! {
    section class="page" {
        { islands::Suspense::new(
            rsx! { div class="skeleton h-9 w-32" {} },
            async move { island_marker("Counter", &props, body) }
        ).render() }
    }
}

Suspense is streaming-only — it is valid only inside [render_streaming] / [render_streaming_with]. Using it from a non-streaming render path panics at runtime with RenderStreamContext not active. Non-streaming pages should call island_marker directly.

§The basecoat feature

basecoat is off by default. Enabling it pulls in the basecoat UI component layer (basecoat-core / basecoat-components / basecoat-css). The proc-macro layer (basecoat-macros + basecoat-macros-rt) is not pulled by islands or islands-core at all — a consumer that wants rsx! adds those two crates as direct dependencies themselves. This keeps the islands.rs dep tree zero-cost for consumers that only need the SSR primitives and write their HTML another way.

When the feature is on, cargo xtask materializes assets/css/basecoat.css with the full basecoat utility classes; when off, the same file is written as a 2-line disabled stub so the @import "./basecoat.css"; in base.css always resolves but contributes no rules. Toggle at build time via the ISLANDS_FEATURES env var.

§Prelude

See the prelude module for a curated subset of the above suitable for use islands::prelude::*; in most pages and server modules.

Re-exports§

pub use islands_actions_shared as actions_shared;

Modules§

prelude
Curated re-exports for use islands::prelude::*;.

Structs§

ActionContext
Context passed to every action invocation.
ActionRegistry
Registry mapping action names to their handlers.
Manifest
Asset manifest mapping bundle names to their hashed file paths.
ManifestEntry
A single entry in the asset manifest for one page bundle.
RouteEntry
One page route: the URL path, the asset-manifest bundle key ("<example>/<page>", e.g. "counter/page-about"), and the Axum method_router that serves it.
RouteTable
An ordered table of page routes. The one declaration that builds the router AND emits the nav manifest (AC-N1).
Signal

Enums§

ActionError
Typed error enum for server actions.
CoreError

Functions§

action_router
Build an Axum router that exposes all registered actions at /_action/:name.
cache_layer
Returns a tower::Layer that performs three jobs on every response:
call_action
cn
Merge Tailwind class strings, with later classes winning on conflicts.
init_panic_hook
island_marker
Renders an island marker with serialized props and initial server-rendered HTML.
mount_all
on_click
on_event
page_shell
Renders a complete HTML page shell for an interactive (island-bearing) page: base + page stylesheets, the shared core module, and the page’s WASM module.
page_shell_static
Renders a complete HTML page shell for a non-interactive page that has no island, hence no page WASM bundle.
register_island
set_class
text_binding