Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 39 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,33 +69,54 @@ export function PreviewWrapper({ children }) {

### Mark Your Content

Add `data-hygraph-*` attributes to make content editable:
Add `data-hygraph-*` attributes to make content editable. The SDK supports two patterns:

#### Pattern 1: Inherited Entry ID (Recommended)

Child elements with `data-hygraph-field-api-id` automatically inherit `data-hygraph-entry-id` from their nearest ancestor. This keeps your markup clean:

```tsx
<article data-hygraph-entry-id="entry-123">
<h1
data-hygraph-entry-id="entry-123"
data-hygraph-field-api-id="title"
>
My Article Title
<article data-hygraph-entry-id={post.id}>
<h1 data-hygraph-field-api-id="title">
{post.title}
</h1>

<p
data-hygraph-entry-id="entry-123"
data-hygraph-field-api-id="content"
>
Article content here...
<p data-hygraph-field-api-id="content">
{post.content}
</p>
</article>
```

Required attribute:
- `data-hygraph-entry-id`: The entry ID from Hygraph. Every element you want to make editable must include this.
#### Pattern 2: Explicit Entry ID

You can also set `data-hygraph-entry-id` explicitly on each element. This is useful when you have nested content from different entries:

```tsx
<article data-hygraph-entry-id={page.id}>
<h1 data-hygraph-field-api-id="title">
{page.title}
</h1>

{/* This recipe comes from a different entry */}
<div
data-hygraph-entry-id={recipe.id}
data-hygraph-field-api-id="name"
>
{recipe.name}
</div>
</article>
```

Both patterns work together—explicit entry IDs take precedence over inherited ones. Use whichever fits your code structure.

#### Attributes Reference

Common optional attributes:
- `data-hygraph-field-api-id`: Identifies which field to open. Without it the edit button opens the entry without focusing a field.
- `data-hygraph-rich-text-format`: Set to `html`, `markdown`, or `text` so the SDK knows which format to update on field sync.
- `data-hygraph-component-chain`: JSON string describing the path to nested components (see below).
| Attribute | Required | Description |
|-----------|----------|-------------|
| `data-hygraph-entry-id` | On element or ancestor | The Hygraph entry ID. Can be set on a parent and inherited by children with `field-api-id`. |
| `data-hygraph-field-api-id` | No | Which field to open. Elements with this attribute inherit entry-id from ancestors if not explicitly set. |
| `data-hygraph-rich-text-format` | No | Set to `html`, `markdown`, or `text` so the SDK knows which format to update on field sync. |
| `data-hygraph-component-chain` | No | JSON string describing the path to nested components (see below). |

```tsx
<div
Expand Down
15 changes: 8 additions & 7 deletions examples/nextjs-example/src/app/recipes/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,8 @@ export default async function RecipePage({ params }: { params: Promise<{ id: str
</Link>
</div>

<div className="grid lg:grid-cols-2 gap-12 items-start">
{/* Entry ID inheritance: children with field-api-id inherit entry-id from this parent */}
<div className="grid lg:grid-cols-2 gap-12 items-start" data-hygraph-entry-id={recipe.id}>
{/* Hero Image */}
{recipe.heroImage && (
<div data-hygraph-field-api-id="heroImage">
Expand All @@ -221,40 +222,40 @@ export default async function RecipePage({ params }: { params: Promise<{ id: str
)}

<div className="lg:pl-8">
<h1 className="text-5xl md:text-6xl font-bold text-white mb-6 leading-tight tracking-tight" data-hygraph-field-api-id="title" data-hygraph-entry-id={recipe.id}>
<h1 className="text-5xl md:text-6xl font-bold text-white mb-6 leading-tight tracking-tight" data-hygraph-field-api-id="title">
{recipe.title}
</h1>

{/* Rich Text field with HTML format preference */}
<div className="prose prose-xl prose-invert mb-8 text-gray-300 leading-relaxed" data-hygraph-field-api-id="description" data-hygraph-entry-id={recipe.id} data-hygraph-rich-text-format="html">
<div className="prose prose-xl prose-invert mb-8 text-gray-300 leading-relaxed" data-hygraph-field-api-id="description" data-hygraph-rich-text-format="html">
<div dangerouslySetInnerHTML={{ __html: recipe.description.html }} />
</div>

{/* Recipe Meta */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8">
{recipe.prepTime && (
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="prepTime" data-hygraph-entry-id={recipe.id}>
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="prepTime">
<div className="text-3xl mb-3">⏱️</div>
<div className="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Prep Time</div>
<div className="text-2xl font-bold text-white">{recipe.prepTime}<span className="text-sm font-normal text-gray-400">min</span></div>
</div>
)}
{recipe.cookTime && (
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="cookTime" data-hygraph-entry-id={recipe.id}>
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="cookTime">
<div className="text-3xl mb-3">🔥</div>
<div className="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Cook Time</div>
<div className="text-2xl font-bold text-white">{recipe.cookTime}<span className="text-sm font-normal text-gray-400">min</span></div>
</div>
)}
{recipe.servings && (
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="servings" data-hygraph-entry-id={recipe.id}>
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="servings">
<div className="text-3xl mb-3">🍽️</div>
<div className="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Servings</div>
<div className="text-2xl font-bold text-white">{recipe.servings}</div>
</div>
)}
{recipe.difficulty && (
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="difficulty" data-hygraph-entry-id={recipe.id}>
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="difficulty">
<div className="text-3xl mb-3">📊</div>
<div className="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Difficulty</div>
<div className="text-2xl font-bold text-white">{recipe.difficulty}</div>
Expand Down
15 changes: 8 additions & 7 deletions examples/nextjs-pages-example/pages/recipes/[id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@ export default function RecipePage({ recipe }: PageProps) {
</Link>
</div>

<div className="grid lg:grid-cols-2 gap-12 items-start">
{/* Entry ID inheritance: children with field-api-id inherit entry-id from this parent */}
<div className="grid lg:grid-cols-2 gap-12 items-start" data-hygraph-entry-id={recipe.id}>
{/* Hero Image */}
{recipe.heroImage && (
<div data-hygraph-field-api-id="heroImage">
Expand All @@ -220,40 +221,40 @@ export default function RecipePage({ recipe }: PageProps) {
)}

<div className="lg:pl-8">
<h1 className="text-5xl md:text-6xl font-bold text-white mb-6 leading-tight tracking-tight" data-hygraph-field-api-id="title" data-hygraph-entry-id={recipe.id}>
<h1 className="text-5xl md:text-6xl font-bold text-white mb-6 leading-tight tracking-tight" data-hygraph-field-api-id="title">
{recipe.title}
</h1>

{/* Rich Text field with HTML format preference */}
<div className="prose prose-xl prose-invert mb-8 text-gray-300 leading-relaxed" data-hygraph-field-api-id="description" data-hygraph-entry-id={recipe.id} data-hygraph-rich-text-format="html">
<div className="prose prose-xl prose-invert mb-8 text-gray-300 leading-relaxed" data-hygraph-field-api-id="description" data-hygraph-rich-text-format="html">
<div dangerouslySetInnerHTML={{ __html: recipe.description.html }} />
</div>

{/* Recipe Meta */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8">
{recipe.prepTime && (
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="prepTime" data-hygraph-entry-id={recipe.id}>
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="prepTime">
<div className="text-3xl mb-3">⏱️</div>
<div className="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Prep Time</div>
<div className="text-2xl font-bold text-white">{recipe.prepTime}<span className="text-sm font-normal text-gray-400">min</span></div>
</div>
)}
{recipe.cookTime && (
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="cookTime" data-hygraph-entry-id={recipe.id}>
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="cookTime">
<div className="text-3xl mb-3">🔥</div>
<div className="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Cook Time</div>
<div className="text-2xl font-bold text-white">{recipe.cookTime}<span className="text-sm font-normal text-gray-400">min</span></div>
</div>
)}
{recipe.servings && (
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="servings" data-hygraph-entry-id={recipe.id}>
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="servings">
<div className="text-3xl mb-3">🍽️</div>
<div className="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Servings</div>
<div className="text-2xl font-bold text-white">{recipe.servings}</div>
</div>
)}
{recipe.difficulty && (
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="difficulty" data-hygraph-entry-id={recipe.id}>
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="difficulty">
<div className="text-3xl mb-3">📊</div>
<div className="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Difficulty</div>
<div className="text-2xl font-bold text-white">{recipe.difficulty}</div>
Expand Down
15 changes: 8 additions & 7 deletions examples/remix-example/app/routes/recipes.$id.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ export default function RecipePage() {
</Link>
</div>

<div className="grid lg:grid-cols-2 gap-12 items-start">
{/* Entry ID inheritance: children with field-api-id inherit entry-id from this parent */}
<div className="grid lg:grid-cols-2 gap-12 items-start" data-hygraph-entry-id={recipe.id}>
{/* Hero Image */}
{recipe.heroImage && (
<div data-hygraph-field-api-id="heroImage">
Expand All @@ -64,40 +65,40 @@ export default function RecipePage() {
)}

<div className="lg:pl-8">
<h1 className="text-5xl md:text-6xl font-bold text-white mb-6 leading-tight tracking-tight" data-hygraph-field-api-id="title" data-hygraph-entry-id={recipe.id}>
<h1 className="text-5xl md:text-6xl font-bold text-white mb-6 leading-tight tracking-tight" data-hygraph-field-api-id="title">
{recipe.title}
</h1>

{/* Rich Text field with HTML format preference */}
<div className="prose prose-xl prose-invert mb-8 text-gray-300 leading-relaxed" data-hygraph-field-api-id="description" data-hygraph-entry-id={recipe.id} data-hygraph-rich-text-format="html">
<div className="prose prose-xl prose-invert mb-8 text-gray-300 leading-relaxed" data-hygraph-field-api-id="description" data-hygraph-rich-text-format="html">
<div dangerouslySetInnerHTML={{ __html: recipe.description.html }} />
</div>

{/* Recipe Meta */}
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8">
{recipe.prepTime && (
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="prepTime" data-hygraph-entry-id={recipe.id}>
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="prepTime">
<div className="text-3xl mb-3">⏱️</div>
<div className="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Prep Time</div>
<div className="text-2xl font-bold text-white">{recipe.prepTime}<span className="text-sm font-normal text-gray-400">min</span></div>
</div>
)}
{recipe.cookTime && (
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="cookTime" data-hygraph-entry-id={recipe.id}>
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="cookTime">
<div className="text-3xl mb-3">🔥</div>
<div className="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Cook Time</div>
<div className="text-2xl font-bold text-white">{recipe.cookTime}<span className="text-sm font-normal text-gray-400">min</span></div>
</div>
)}
{recipe.servings && (
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="servings" data-hygraph-entry-id={recipe.id}>
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="servings">
<div className="text-3xl mb-3">🍽️</div>
<div className="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Servings</div>
<div className="text-2xl font-bold text-white">{recipe.servings}</div>
</div>
)}
{recipe.difficulty && (
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="difficulty" data-hygraph-entry-id={recipe.id}>
<div className="bg-gray-800/50 backdrop-blur-sm rounded-2xl p-5 text-center shadow-lg ring-1 ring-white/10 hover:ring-white/20 hover:bg-gray-800/80 transition-all" data-hygraph-field-api-id="difficulty">
<div className="text-3xl mb-3">📊</div>
<div className="text-xs font-semibold text-gray-400 uppercase tracking-wider mb-2">Difficulty</div>
<div className="text-2xl font-bold text-white">{recipe.difficulty}</div>
Expand Down
Loading