Dyrecteddyrected
Integrations

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/sdk

To 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 '*')
})
ReturnTypeDescription
dataTLive draft data — starts as initialData, updates on each Admin message
isLivebooleantrue 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}
    />
  )
}
PropTypeDescription
baseUrlstringURL of the Dyrected API (e.g. /dyrected)
apiKeystringAPI key for authenticating requests
siteIdstringOptional site ID for multi-tenant setups
onNavigate(path: string) => voidCalled 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

ExportKindPurpose
DyrectedProviderComponentProvides the client + config to the tree. Wrap your app once.
DyPathProviderComponentScopes a data-dy-path base for nested live-preview editing.
DyrectedAdminComponentEmbeds the full Admin UI (@dyrected/react/admin).
BlocksComponentRenders an array of blocks by blockType to your block components.
DyrectedImageComponent<img> wrapper for a Media object or URL.
DyrectedMediaComponentRenders image / video / YouTube / download by media type.
DyrectedIconComponentRenders an icon field value as a Lucide icon.
useDyrectedHookFetch a document / collection / global.
useLivePreviewHookSubscribe to Admin preview messages + inline editing.
useDyPathHookRead the current data-dy-path scope.
DyrectedClient, DyrectedErrorRe-exportSDK client + error type, for convenience.

On this page