React Integration
Use Dyrected in a Vite, CRA, or any non-Next.js React application.
The @dyrected/react package is the React integration layer for Dyrected. It provides hooks, a context provider, the Admin UI component, and media components for use in any React app. If you are using Next.js, @dyrected/next builds on top of this package and re-exports everything from it — you do not need to install @dyrected/react separately in a Next.js project.
Installation
pnpm add @dyrected/react @dyrected/sdkTo use <DyrectedAdmin />, your app must also have react-router-dom and @tanstack/react-query installed — these are peer dependencies of the admin UI bundle.
Step 1 — Wrap your app with DyrectedProvider
DyrectedProvider makes a configured DyrectedClient available to any component in the tree via useDyrected().
// src/main.tsx
import { DyrectedProvider } from '@dyrected/react'
import { createClient } from '@dyrected/sdk'
const client = createClient({
baseUrl: import.meta.env.VITE_DYRECTED_URL,
apiKey: import.meta.env.VITE_DYRECTED_API_KEY,
})
ReactDOM.createRoot(document.getElementById('root')!).render(
<DyrectedProvider client={client}>
<App />
</DyrectedProvider>
)Step 2 — Fetch content with useDyrected
useDyrected() returns the shared DyrectedClient instance:
import { useDyrected } from '@dyrected/react'
import { useEffect, useState } from 'react'
export function PostList() {
const { client } = useDyrected()
const [posts, setPosts] = useState([])
useEffect(() => {
client.collection('posts').find().exec().then(res => setPosts(res.docs))
}, [client])
return (
<ul>
{posts.map(post => <li key={post.id}>{post.title}</li>)}
</ul>
)
}Live Preview — useLivePreview
useLivePreview subscribes to postMessage events from the Dyrected Admin UI and keeps your component data in sync in real time.
// src/pages/PostPreview.tsx
import { useLivePreview } from '@dyrected/react'
interface Props {
initialPost: Post
}
export function PostPreview({ initialPost }: Props) {
const { data: post, isLive } = useLivePreview<Post>({
initialData: initialPost,
serverURL: import.meta.env.VITE_CMS_ADMIN_URL,
// ^ Should match the origin of your Admin UI for security
})
return (
<article>
{isLive && (
<div className="preview-banner">Preview Mode — changes appear in real-time</div>
)}
<h1 data-dy-path="title">{post.title}</h1>
<p data-dy-path="excerpt">{post.excerpt}</p>
</article>
)
}Hook API:
const { data, isLive } = useLivePreview<T>({
initialData: T, // Shown until the first postMessage arrives
serverURL?: string, // Admin origin for origin validation (defaults to '*')
})| Return | Type | Description |
|---|---|---|
data | T | Live draft data — starts as initialData, updates on each Admin message |
isLive | boolean | true once the first preview message has been received |
Inline editing
Add data-dy-path attributes to elements to enable click-to-field navigation when the editor activates Edit Mode in the preview toolbar:
<h1 data-dy-path="title">{post.title}</h1>
<p data-dy-path="excerpt">{post.excerpt}</p>
<img src={post.coverImage?.url} data-dy-path="coverImage" />Clicking a marked element sends its field path to the Admin, which scrolls to and focuses the corresponding form input. See Inline Page Editing for the full protocol.
Embed the Admin UI — DyrectedAdmin
DyrectedAdmin renders the full Dyrected Admin UI into your React app. It lazy-loads the admin bundle so it does not affect your page bundle size.
import { DyrectedAdmin } from '@dyrected/react'
import '@dyrected/admin/styles'
export function AdminPage() {
return (
<DyrectedAdmin
baseUrl="/dyrected"
apiKey={import.meta.env.VITE_DYRECTED_API_KEY}
/>
)
}| Prop | Type | Description |
|---|---|---|
baseUrl | string | URL of the Dyrected API (e.g. /dyrected) |
apiKey | string | API key for authenticating requests |
siteId | string | Optional site ID for multi-tenant setups |
onNavigate | (path: string) => void | Called on internal route changes — use to sync your host router |
Media components
DyrectedImage
A plain-<img> wrapper that accepts a Dyrected Media object or a URL string and handles width, height, and alt automatically.
import { DyrectedImage } from '@dyrected/react'
<DyrectedImage media={post.coverImage} width={800} height={400} />DyrectedMedia
Renders the right element based on media type — YouTube embed, image, video, or a download link fallback.
import { DyrectedMedia } from '@dyrected/react'
<DyrectedMedia media={post.featuredMedia} width={800} height={450} />If you are using Next.js, prefer DyrectedImage and DyrectedMedia from @dyrected/next — they use next/image for automatic optimisation.
Icons — DyrectedIcon
The icon field type stores the name of a Lucide icon (e.g. "ChartNoAxesCombined"), not SVG markup. DyrectedIcon resolves that name to the matching Lucide icon so you can render an icon field value directly — no icon library wiring required.
import { DyrectedIcon } from '@dyrected/react'
// feature.icon === "ChartNoAxesCombined"
<DyrectedIcon name={feature.icon} className="w-6 h-6 text-primary" />Any standard Lucide prop (size, color, strokeWidth, className, …) is forwarded to the underlying icon.
Prop
Type
Browse valid icon names at lucide.dev/icons. The Admin UI's icon-picker field uses the same set, so any value an editor can choose will resolve here.
Reference — everything @dyrected/react exports
| Export | Kind | Purpose |
|---|---|---|
DyrectedProvider | Component | Provides the client + config to the tree. Wrap your app once. |
DyPathProvider | Component | Scopes a data-dy-path base for nested live-preview editing. |
DyrectedAdmin | Component | Embeds the full Admin UI (@dyrected/react/admin). |
Blocks | Component | Renders an array of blocks by blockType to your block components. |
DyrectedImage | Component | <img> wrapper for a Media object or URL. |
DyrectedMedia | Component | Renders image / video / YouTube / download by media type. |
DyrectedIcon | Component | Renders an icon field value as a Lucide icon. |
useDyrected | Hook | Fetch a document / collection / global. |
useLivePreview | Hook | Subscribe to Admin preview messages + inline editing. |
useDyPath | Hook | Read the current data-dy-path scope. |
DyrectedClient, DyrectedError | Re-export | SDK client + error type, for convenience. |