React
Use the Opinly SDK in any React app (Vite, CRA, Remix, Astro islands) — no Next.js required.
@opinly/react is a plain React renderer with no Next.js dependency. Use it in Vite, Remix,
Astro React islands, or anywhere React runs. (On Next.js, add @opinly/next
on top for image rewrites + metadata helpers.)
Install
pnpm add @opinly/backend @opinly/reactnpm i @opinly/backend @opinly/reactyarn add @opinly/backend @opinly/reactFetch + render
Fetch on the server (or in a server-side data loader) so your API key never reaches the browser.
import { createOpinlyClient } from '@opinly/backend'
import { OpinlyContent } from '@opinly/react'
const opinly = createOpinlyClient() // reads OPINLY_API_KEY
export async function Post({ slug }: { slug: string }) {
const post = await opinly.post(slug)
if (!post) return null
return (
<article className="prose">
<h1>{post.title}</h1>
<OpinlyContent
content={post.content}
config={{ imagesPrefix: '/images', siteUrl: 'https://acme.com' }}
/>
</article>
)
}Customize rendering
<OpinlyContent> accepts classNames (per-node-type CSS classes) and components (override how
a node type renders — e.g. swap in your own <img> or a router <Link>):
<OpinlyContent
content={content}
config={config}
classNames={{ paragraph: 'text-base leading-7', heading: 'font-display' }}
components={{
image: ({ node }) => <img src={`/images/${node.attrs?.fileKey}`} alt={node.attrs?.alt ?? ''} loading="lazy" />,
}}
/>See Rendering for the full node/mark coverage and the
components contract.
SEO
There's no React-specific SEO adapter — use @opinly/shared's framework-neutral builders
(buildMetadata, buildBlogPostingJsonLd) and feed them into your app's head management
(React Helmet, Remix meta, etc.). See SEO.