Other frameworks
The rendering contract does not change with the framework; only the adapter does, and an adapter is small — bridge, editing state, variants, rich text. SvelteKit, React Router and Astro are walked through side by side in Step by step; this page is the map of all adapters, Vue, and what to do without one.
What an adapter gives you
| SvelteKit | React Router | Astro | Vue | |
|---|---|---|---|---|
| Package | @maravilla/studio-svelte | @maravilla/studio-react | @maravilla/studio-astro | @maravilla/studio-vue |
| Mount the editor | studioEditor({ … }) in the page or root layout | useStudioEditor({ … }) in the route | <StudioEditor /> | useStudioEditor({ … }) in the app root |
| Editing state | getEditing() context | <StudioEditing> + useStudioEditing() | editing prop | provideEditing() + useEditing() |
| Variants | <StudioVariants> / variantContent() | <StudioVariants> / useVariantContent() | <StudioVariants> / pickVariantContent() | <StudioVariants> / useVariantContent() |
| Rich text | <RichText> | <RichText> | <RichText> | <RichText> |
| Preview endpoints | a +server.ts using studioPreviewEnter/Status/Leave | a resource route, same helpers | studioPreviewRoutes() | same helpers |
| Example | examples/site-svelte | examples/site-shadcn, examples/site-react | examples/site-astro | examples/site-vue |
The data layer is yours in all of them and identical in shape: a server-only module with a shared client, a query() on the request’s branch, getPage, getChrome, getArticles. Move it between frameworks unchanged.
SvelteKit
The page calls studioEditor({ mode: 'server', onRevalidate: invalidateAll }) with getter-based initial content so a revalidation resyncs; the catch-all [...path]/+page.server.ts resolves the preview session at the top of its loader and is the route. A block is a .svelte component reading getEditing() from context to render placeholders. The SvelteKit example is the fullest of the set and includes forms, article lists and a product catalogue.
React Router
The root route calls useStudioEditor({ mode: 'server', revalidate: () => revalidator.revalidate() }) and wraps the outlet in <StudioEditing editing={…}>. Loaders run on the server; a component never fetches. The corporate-site example bundles the page and chrome reads with a small concurrency limit and a chrome cache, and publishes to the live branch, which is the pattern to copy for a site with many pages.
Vue / Nuxt
useStudioEditor() in the app root; provideEditing() at the top, useEditing() in blocks. Server rendering through Nuxt or Vite SSR; the route and data layer as above.
Luat
A server-rendered site in Luat — templates and Lua, no JavaScript framework — uses the Luat package @maravilla/studio: content reads, drafts, the preview handshake, inline editing, personalisation and the standard blocks. See Luat sites.
A framework with no adapter
The adapter is convenience, not magic. What the editor needs from a page:
- The
data-studio-*annotations in the HTML. - A script that loads the bridge from the editor’s origin and calls
mountStudioEditorfrom@maravilla/studio-content/bootstrapwithmode: 'server', arevalidatefunction and the allowed editor origins. - Preview endpoints built on
studioPreviewEnter,studioPreviewStatusandstudioPreviewLeavefrom@maravilla/studio-content/preview-session, and a request hook that callsresolveStudioPreviewand selects the branch.
@maravilla/studio-content has no framework dependency and runs anywhere JavaScript runs on the server. A renderer in another language does the same with the REST and SQL endpoints: POST /api/sql/<repo>/<branch> for reads, the display-URL endpoint for assets, and a port of the preview-session HMAC, which is a signed JSON cookie.
Pilot documentation. Studio is in a partner pilot. Screens and YAML shown here are current as of the version noted on each page; tell your Maravilla contact when something does not match what you see.