@@ -40,17 +40,19 @@ Define a TypeScript interface for your content type:
4040
4141``` tsx
4242// content/blog-post.ts
43- import { ContentItem } from ' @vyuh/react-extension-content'
43+ import {ImageReference } from ' @vyuh/react-core' ;
44+ import {ContentItem } from ' @vyuh/react-extension-content' ;
45+ import {PortableText } from ' @vyuh/react-feature-system' ;
4446
45- export const BLOG_POST_SCHEMA_TYPE = ' blog.post'
47+ export const BLOG_POST_SCHEMA_TYPE = ' blog.post' ;
4648
4749export interface BlogPost extends ContentItem {
48- title: string
49- publishDate: string
50- author: string
51- content: any // This would typically be a Portable Text block from Sanity
52- featuredImage? : string
53- tags? : string []
50+ title: string ;
51+ publishDate: string ;
52+ author: string ;
53+ content: PortableText ;
54+ featuredImage? : ImageReference ;
55+ tags? : string [];
5456}
5557```
5658
@@ -60,10 +62,9 @@ Create a React component that will render your content type:
6062
6163``` tsx
6264// content/blog-post-layout.tsx
65+ import {LayoutConfiguration , TypeDescriptor } from ' @vyuh/react-core'
6366import React from ' react'
64- import { LayoutConfiguration , TypeDescriptor } from ' @vyuh/react-core'
65- import { BlogPost , BLOG_POST_SCHEMA_TYPE } from ' ./blog-post'
66- import { PortableText } from ' @portabletext/react'
67+ import {BLOG_POST_SCHEMA_TYPE , BlogPost } from ' ./blog-post'
6768
6869export class DefaultBlogPostLayout extends LayoutConfiguration <BlogPost > {
6970 static readonly schemaName = ` ${BLOG_POST_SCHEMA_TYPE }.layout.default `
@@ -77,42 +78,53 @@ export class DefaultBlogPostLayout extends LayoutConfiguration<BlogPost> {
7778 }
7879
7980 render(content : BlogPost ): React .ReactNode {
80- return (
81- <article className = " max-w-2xl mx-auto py-8" >
82- { content .featuredImage && (
83- <img
84- src = { content .featuredImage }
85- alt = { content .title }
86- className = " w-full h-64 object-cover rounded-lg mb-6"
87- />
88- )}
89- <div className = " mb-6" >
90- <h1 className = " text-3xl font-bold mb-2" >{ content .title } </h1 >
91- <div className = " text-gray-600" >
92- <span >By { content .author } </span >
93- <span className = " mx-2" >•</span >
94- <time >{ new Date (content .publishDate ).toLocaleDateString ()} </time >
95- </div >
96- { content .tags && (
97- <div className = " flex flex-wrap gap-2 mt-3" >
98- { content .tags .map ((tag ) => (
99- <span
100- key = { tag }
101- className = " px-3 py-1 bg-gray-100 text-gray-800 text-sm rounded-full"
102- >
103- { tag }
104- </span >
105- ))}
106- </div >
107- )}
108- </div >
109- <div className = " prose prose-lg" >
110- <PortableText value = { content .content } />
111- </div >
112- </article >
113- )
81+ return <BlogPostContent content = { content } />
11482 }
11583}
84+
85+ // Separate component for rendering blog post content
86+ const BlogPostContent: React .FC <{ content: BlogPost }> = ({ content }) => {
87+ const { plugins } = useVyuh ()
88+ const imageUrl = content .featuredImage
89+ ? plugins .content .provider .image (content .featuredImage )
90+ : undefined
91+
92+ return (
93+ <article className = " max-w-2xl mx-auto py-8" >
94+ { imageUrl && (
95+ <img
96+ src = { imageUrl }
97+ alt = { content .title }
98+ className = " w-full h-64 object-cover rounded-lg mb-6"
99+ />
100+ )}
101+ <div className = " mb-6" >
102+ <h1 className = " text-3xl font-bold mb-2" >{ content .title } </h1 >
103+ <div className = " text-gray-600" >
104+ <span >By { content .author } </span >
105+ <span className = " mx-2" >•</span >
106+ <time >{ new Date (content .publishDate ).toLocaleDateString ()} </time >
107+ </div >
108+ { content .tags && (
109+ <div className = " flex flex-wrap gap-2 mt-3" >
110+ { content .tags .map ((tag ) => (
111+ <span
112+ key = { tag }
113+ className = " px-3 py-1 bg-gray-100 text-gray-800 text-sm rounded-full"
114+ >
115+ { tag }
116+ </span >
117+ ))}
118+ </div >
119+ )}
120+ </div >
121+ <div className = " prose prose-lg" >
122+ { content .content && plugins .content .render (content .content )}
123+ </div >
124+ </article >
125+ )
126+ }
127+
116128```
117129
118130## 4. Create a content builder
@@ -165,9 +177,11 @@ Wrap your application with the `VyuhProvider` component:
165177
166178``` tsx
167179// App.tsx
168- import { VyuhProvider } from ' @vyuh/react-core'
180+ import { VyuhProvider , PluginDescriptor } from ' @vyuh/react-core'
169181import { systemFeature } from ' @vyuh/react-feature-system'
170182import { blogFeature } from ' ./features/blog'
183+ import { DefaultContentPlugin } from ' @vyuh/react-extension-content'
184+ import {SanityContentProvider } from ' @vyuh/react-plugin-content-provider-sanity' ;
171185
172186const plugins = new PluginDescriptor ({
173187 content: new DefaultContentPlugin (
0 commit comments