Framework guides
How each of the six example stacks reads kura, grounded in real repo code
kura is just a REST API, so it works with any frontend. The six example repos each read from a real kura project in a different stack - clone any one to scaffold a real site. This page shows how each reads kura, grounded in the actual code in each repo.
The shape every framework shares
Every example makes the same call: GET {base}/api/v1/{project}/{type} with an Authorization: Bearer {token} header, and reads body.data (the entries) from the envelope. They keep three values in config:
KURA_BASE_URL=https://kuracms.com
KURA_PROJECT=your-project-slug
KURA_TOKEN=kr_live_your_token Always read kura server-side or at build time so the token never ships in the browser bundle - every example below does this.
Two execution patterns:
- Request-time (SSR): Astro, Next.js, Nuxt, SvelteKit fetch on each request, so published edits appear on the next page load.
- Build-time (static): Eleventy and Hugo fetch during the build into JSON data files, so published edits appear only after a rebuild (see the note at the end).
Astro (kura-property-example)
Config in .env. Fetches at request time in a client() + typed fetch
helper (src/lib/kura.ts):
const url = `${base}/api/v1/${project}/listing${qs.size ? `?${qs}` : ""}`;
const res = await fetch(url, { headers: { Authorization: `Bearer ${token}` } });
const body = await res.json();
return body.data.map((l) => resolveMedia(l, base)); This one shows the media prefix done properly - resolveMedia prepends the base URL to any /media/... value:
if (v.startsWith("/media/")) return base + v; Called from .astro pages during server render.
Next.js (kura-restaurant-example)
Config in wrangler.jsonc vars (falls back to process.env for next dev). Server components fetch at request time with cache: "no-store" so editor changes show immediately (src/lib/kura.ts):
const url = `${base}/api/v1/${project}${qpath}`;
const res = await fetch(url, { headers, cache: "no-store" }); It rewrites /media/ paths inside markdown/HTML body text before rendering:
text.replace(/(\]\()(\/media\/)/g, `$1${base}$2`)
.replace(/(["'\s])(\/media\/)/g, `$1${base}$2`); Deployed to Cloudflare Workers via OpenNext; revalidate = 0 keeps it request-time.
Nuxt (kura-salon-example)
Config via runtimeConfig.public (set from NUXT_PUBLIC_KURA_* vars in wrangler.jsonc). Fetches in a composable with useAsyncData (composables/useKura.ts):
const url = `${cfg.kuraBaseUrl}/api/v1/${cfg.kuraProject}${path}`;
const res = await $fetch(url, { headers: { Authorization: `Bearer ${cfg.kuraToken}` } }); export function useServices() {
return useAsyncData("services", async () => {
const r = await kuraFetch(`/service?limit=50`);
return r.data.filter((s) => s.published);
});
} SvelteKit (kura-clothing-example)
Config from the Cloudflare platform env (falls back to process.env in dev). Fetches
in a +page.server.ts load function (src/lib/kura.ts):
const url = `${cfg.baseUrl}/api/v1/${cfg.project}${path}`;
const res = await fetchFn(url, { headers: { Authorization: `Bearer ${cfg.token}` } }); export async function fetchProducts(fetchFn, platform) {
const r = await kuraFetch(fetchFn, platform, `/product?limit=100`);
return r.data.filter((p) => p.published !== false);
} Eleventy - static (kura-architecture-example)
A static site, so it fetches at build time with a shell script
(fetch-content.sh) that curls kura and writes JSON into _data/, which
Eleventy reads as global data:
curl -fsSL -H "Authorization: Bearer ${KURA_TOKEN}" \
"${KURA_BASE}/api/v1/${KURA_PROJECT}/${type}?limit=50" > _data/${type}-raw.json
# then a small python filter to published-only + sort, written to _data/{type}.json KURA_TOKEN etc are environment variables set at deploy time (see the repo README).
Templates read _data/*.json during eleventy build.
Hugo - static (kura-escape-example)
Same build-time pattern: fetch-content.sh curls kura into data/*.json,
then hugo --minify reads .Site.Data.rooms etc:
curl -fsSL -H "Authorization: Bearer ${KURA_TOKEN}" \
"${KURA_BASE}/api/v1/${KURA_PROJECT}/room?limit=50" > data/rooms-raw.json Two notes that bite
Media paths. kura returns uploaded images as relative /media/{key} strings. The Astro and Next.js examples prefix them with the
base URL (shown above); the others happen to use absolute image URLs in their seed data, so they
render as-is - but if your content uses kura image uploads, prefix /media/ paths
with KURA_BASE_URL. See the REST API reference.
Static sites need a rebuild to show edits. Eleventy and Hugo fetch at build time, so an editor publishing a change won't see it until the site rebuilds. Wire your host's deploy hook (e.g. a Cloudflare Pages / Workers build hook) to fire on publish. The SSR stacks (Astro, Next.js, Nuxt, SvelteKit) don't have this - they read kura on each request.
Building from scratch rather than cloning? See the tutorial and the REST API reference.