Concepts
Regions
Islands are one kind of region. Server islands, lakes, and held regions round out the model.
On this page
An island is the most familiar region, but it is not the only one. ogygia models the whole page as a set of regions, each with its own answer to two questions: where does it run and when does its content settle. Once you see the four region types, the render modes fall out naturally.
The four regions
| Region | Runs on | Interactive | Typical use |
|---|---|---|---|
| Client island | Client | Yes | Counters, menus, anything the user drives. |
| Server island | Server | No | Per-request data that must not ship to the client. |
| Lake | Server | No | A large static block rendered once and cached. |
| Held region | Server, then client | Yes | Content that starts static and later becomes live. |
Client islands
The regions you already met. They render on the server for the first paint, then hydrate on the client according to their wake strategy. State lives in the browser.
<script>
import Counter from '$lib/playground/demos/Counter.svelte' with { wake: 'visible' };
</script>
<Counter />Server islands
A server island renders on the server on every request and never ships its code to the client. Use it when the component needs secrets, private data, or heavy dependencies you do not want in the browser bundle.
<script>
import Greeting from './Greeting.svelte' with { region: 'server' };
</script>
<Greeting />Because there is no client code, a server island cannot hold interactive state. It is HTML the moment it reaches the browser, and it stays that way.
Lakes
A lake is a large static region rendered once and cached. Where a server island runs per request, a lake runs per build (or per cache miss) and is reused across requests. Think of a rendered changelog or a generated API table — expensive to produce, identical for everyone.
<script>
import ApiTable from './ApiTable.svelte' with { region: 'lake' };
</script>
<ApiTable />Held regions
A held region is the interesting one. It renders static on the server, ships as HTML, and is held until some condition promotes it to a live client island. Until then it costs nothing on the client. The classic case is a search box that is plain HTML until the user focuses it, at which point it wakes into a full live component.
<script>
import Search from './Search.svelte' with { region: 'held', wake: 'interaction' };
</script>
<Search />Held vs. interaction wake. They look similar but differ in intent.
wake: 'interaction'on a client island still ships the chunk eagerly-ish and hydrates existing HTML. A held region defers even the decision to hydrate, keeping the region a candidate for staying static forever if the user never engages.
Render modes
Regions decide where and when things run. Render modes decide when content is allowed to change. Each region supports one or more modes.
| Mode | Meaning |
|---|---|
static | Rendered once. Never changes after paint. |
deferred | Rendered on the server, streamed in after the shell. |
live | Re-renders in response to state or server pushes. |
static
The default. The region’s HTML is final. Prose, tables, and code blocks are all static.
deferred
The shell paints immediately and the region streams in when its data is ready. Good for a slow query that should not block the rest of the page.
<script>
import Report from './Report.svelte' with { region: 'server', render: 'deferred' };
</script>
<Report />live
The region re-renders when its inputs change — local state, a query.live subscription, or a server push. Only client islands and promoted held regions can be live, because live rendering needs code in the browser.
<script>
import Feed from './Feed.svelte' with { wake: 'load', render: 'live' };
</script>
<Feed />Putting it together
The mental model is a grid: pick a region for where and when it runs, pick a render mode for when its content settles.
- Static prose and tables are lakes in static mode — rendered once, shipped as HTML.
- A private per-request widget is a server island in static or deferred mode.
- A user-driven control is a client island, usually static-then-live once it wakes.
- A maybe-interactive control is a held region that only becomes a live island on demand.
Why this matters. Every region you leave static is JavaScript you do not ship. The framework’s whole performance story is choosing the smallest region and the calmest render mode that still does the job.
See how the static regions themselves are produced from files in content collections.