Docs / Websites

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

SvelteKitReact RouterAstroVue
Package@maravilla/studio-svelte@maravilla/studio-react@maravilla/studio-astro@maravilla/studio-vue
Mount the editorstudioEditor({ … }) in the page or root layoutuseStudioEditor({ … }) in the route<StudioEditor />useStudioEditor({ … }) in the app root
Editing stategetEditing() context<StudioEditing> + useStudioEditing()editing propprovideEditing() + useEditing()
Variants<StudioVariants> / variantContent()<StudioVariants> / useVariantContent()<StudioVariants> / pickVariantContent()<StudioVariants> / useVariantContent()
Rich text<RichText><RichText><RichText><RichText>
Preview endpointsa +server.ts using studioPreviewEnter/Status/Leavea resource route, same helpersstudioPreviewRoutes()same helpers
Exampleexamples/site-svelteexamples/site-shadcn, examples/site-reactexamples/site-astroexamples/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:

  1. The data-studio-* annotations in the HTML.
  2. A script that loads the bridge from the editor’s origin and calls mountStudioEditor from @maravilla/studio-content/bootstrap with mode: 'server', a revalidate function and the allowed editor origins.
  3. Preview endpoints built on studioPreviewEnter, studioPreviewStatus and studioPreviewLeave from @maravilla/studio-content/preview-session, and a request hook that calls resolveStudioPreview and 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.