The seed is the only read model. Document GET places it in
#__keel_seed. Visits return it as JSON (X-Keel-Visit: true). Bootstrap
parses it and passes a typed context into mount().
{
"v": 1,
"page": "harbor.home",
"path": "/",
"params": {},
"data": {
"viewer": { "id": "ada", "displayName": "Ada" },
"feed": []
},
"errors": {},
"theme": { "id": "harbor", "version": "0.1.0" },
"entry": "/__keel/pack/harbor/pages/harbor.home.js",
"css": ["/__keel/pack/harbor/assets/mount.css"],
"build": "9f1c6e0b…",
"host": "#__keel_root",
"head": {
"title": "Harbor",
"description": "An in-memory message board.",
"canonical": "https://example.com/"
}
}
Each adapter reads that payload from its page store (page() in Svelte,
usePage() elsewhere). No second fetch.
<script lang="ts">
import { page } from "@kolektiv/keel-svelte"
import type { HomePage } from "@app/page-types"
const ctx = page<HomePage>()
</script>
<p>{ctx.data.viewer?.displayName ?? "Anonymous"}</p>
<p>{ctx.path}</p>
<p>{ctx.page}</p><script>
import { page } from "@kolektiv/keel-svelte"
const ctx = page()
</script>
<p>{ctx.data.viewer?.displayName ?? "Anonymous"}</p>
<p>{ctx.path}</p>
<p>{ctx.page}</p>import { usePage } from "@kolektiv/keel-react"
import type { HomePage } from "@app/page-types"
export default function Whoami() {
const seed = usePage<HomePage>()
return (
<>
<p>{seed.data.viewer?.displayName ?? "Anonymous"}</p>
<p>{seed.path}</p>
<p>{seed.page}</p>
</>
)
}import { usePage } from "@kolektiv/keel-react"
export default function Whoami() {
const seed = usePage()
return (
<>
<p>{seed.data.viewer?.displayName ?? "Anonymous"}</p>
<p>{seed.path}</p>
<p>{seed.page}</p>
</>
)
}<script setup lang="ts">
import { usePage } from "@kolektiv/keel-vue"
import type { HomePage } from "@app/page-types"
const seed = usePage<HomePage>()
</script>
<template>
<p>{{ seed.data.viewer?.displayName ?? "Anonymous" }}</p>
<p>{{ seed.path }}</p>
<p>{{ seed.page }}</p>
</template><script setup>
import { usePage } from "@kolektiv/keel-vue"
const seed = usePage()
</script>
<template>
<p>{{ seed.data.viewer?.displayName ?? "Anonymous" }}</p>
<p>{{ seed.path }}</p>
<p>{{ seed.page }}</p>
</template>import { usePage } from "@kolektiv/keel-solid"
import type { HomePage } from "@app/page-types"
export default function Whoami() {
const seed = usePage<HomePage>()
return (
<>
<p>{seed().data.viewer?.displayName ?? "Anonymous"}</p>
<p>{seed().path}</p>
<p>{seed().page}</p>
</>
)
}import { usePage } from "@kolektiv/keel-solid"
export default function Whoami() {
const seed = usePage()
return (
<>
<p>{seed().data.viewer?.displayName ?? "Anonymous"}</p>
<p>{seed().path}</p>
<p>{seed().page}</p>
</>
)
}import { usePage } from "@kolektiv/keel-preact"
import type { HomePage } from "@app/page-types"
export default function Whoami() {
const seed = usePage<HomePage>()
return (
<>
<p>{seed.data.viewer?.displayName ?? "Anonymous"}</p>
<p>{seed.path}</p>
<p>{seed.page}</p>
</>
)
}import { usePage } from "@kolektiv/keel-preact"
export default function Whoami() {
const seed = usePage()
return (
<>
<p>{seed.data.viewer?.displayName ?? "Anonymous"}</p>
<p>{seed.path}</p>
<p>{seed.page}</p>
</>
)
}import { html } from "lit"
import { KeelElement } from "@kolektiv/keel-lit"
import type { HomePage } from "@app/page-types"
export default class Whoami extends KeelElement<HomePage> {
render() {
return html`
<p>${this.page.data.viewer?.displayName ?? "Anonymous"}</p>
<p>${this.page.path}</p>
<p>${this.page.page}</p>
`
}
}import { html } from "lit"
import { KeelElement } from "@kolektiv/keel-lit"
export default class Whoami extends KeelElement {
render() {
return html`
<p>${this.page.data.viewer?.displayName ?? "Anonymous"}</p>
<p>${this.page.path}</p>
<p>${this.page.page}</p>
`
}
}import { Component } from "@angular/core"
import { injectKeelPage } from "@kolektiv/keel-angular"
import type { HomePage } from "@app/page-types"
@Component({
selector: "app-whoami",
standalone: true,
template: `
<p>{{ page().data.viewer?.displayName ?? "Anonymous" }}</p>
<p>{{ page().path }}</p>
<p>{{ page().page }}</p>
`,
})
export default class Whoami {
readonly page = injectKeelPage<HomePage>()
}import { Component } from "@angular/core"
import { injectKeelPage } from "@kolektiv/keel-angular"
@Component({
selector: "app-whoami",
standalone: true,
template: `
<p>{{ page().data.viewer?.displayName ?? "Anonymous" }}</p>
<p>{{ page().path }}</p>
<p>{{ page().page }}</p>
`,
})
export default class Whoami {
readonly page = injectKeelPage()
}theme is the serving pack’s { id, version }; entry, css, and build
come from that pack. build is the pack’s content hash (also X-Keel-Build);
a client whose mounted build differs reloads itself — see
Pack hot reload.
Optional fields: shared, layout, redirect, head. path is absolute.
page and entry are non-blank.
On a document GET the host writes head into the HTML shell. Visits return
the same head so <Head> stays in sync. See
Document head and SEO.
Partial reloads (only / except) filter top-level data keys on visits
only — see Partial reloads.
The field list and X-Keel-* headers are on
the wire protocol.