Skip to content

Commit f91eeeb

Browse files
committed
adding some docs for the react side of the framework
1 parent 211dc90 commit f91eeeb

13 files changed

Lines changed: 1741 additions & 467 deletions

astro.config.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,6 @@ export default defineConfig({
249249
'react',
250250
'react/intro/get-started',
251251
'react/intro/setup-sanity',
252-
'react/intro/rendering-content',
253-
'react/intro/custom-content-type',
254252
],
255253
},
256254
{
@@ -260,7 +258,17 @@ export default defineConfig({
260258
'react/guides/content-blocks',
261259
'react/guides/layouts',
262260
'react/guides/actions',
263-
'react/guides/conditions'
261+
'react/guides/conditions',
262+
'react/guides/feature-descriptors',
263+
'react/guides/rendering-content',
264+
'react/guides/custom-content-type',
265+
],
266+
},
267+
{
268+
label: 'Examples',
269+
items: [
270+
'react/examples/marketing',
271+
'react/examples/blog',
264272
],
265273
},
266274
],
Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,286 @@
1+
---
2+
title: Blog Feature
3+
description: Example of the blog feature in the Vyuh framework
4+
---
5+
6+
import { Aside } from '@astrojs/starlight/components'
7+
8+
## Blog Feature Overview
9+
10+
The blog feature provides content types and components for building blog sections and displaying blog posts. It's designed to work seamlessly with the Vyuh framework's content system, allowing you to create rich, interactive blog experiences.
11+
12+
## Content Types
13+
14+
The blog feature includes several content types for building blog sections and displaying blog content. Here's the complete list of content types provided by the blog feature:
15+
16+
- **Blog Post Summary** - Individual blog post previews with metadata
17+
- **Blog Group** - Collections of blog posts for display
18+
- **Blog Post** - Full blog post content *(under construction)*
19+
- **Blog Category** - Category definitions for organizing posts *(under construction)*
20+
- **Blog Author** - Author profiles for blog posts *(under construction)*
21+
22+
We'll cover the two main content types in detail below, but you can explore the full source code on GitHub for more information about the other content types.
23+
24+
<Aside title="Source Code">
25+
26+
You can explore the full source code for the blog feature on GitHub:
27+
28+
- [Sanity Schema (blog)](https://github.com/vyuh-tech/vyuh-react/tree/main/features/blog/sanity-schema-blog/src)
29+
- [React Feature (blog)](https://github.com/vyuh-tech/vyuh-react/tree/main/features/blog/react-feature-blog/src)
30+
31+
You can also view the complete [blog feature directory](https://github.com/vyuh-tech/vyuh-react/tree/main/features/blog) in the Vyuh repository.
32+
</Aside>
33+
34+
### Blog Post Summary
35+
36+
The BlogPostSummary content type represents an individual blog post with metadata:
37+
38+
```typescript
39+
// Blog post summary content structure
40+
interface BlogPostSummary extends ContentItem {
41+
// The title of the blog post
42+
readonly title: string;
43+
44+
// A short summary of the post
45+
readonly excerpt?: string;
46+
47+
// Featured image for the blog post
48+
readonly image?: ImageReference;
49+
50+
// Publication date of the blog post
51+
readonly date?: string;
52+
53+
// Author information
54+
readonly author?: {
55+
readonly name?: string;
56+
readonly role?: string;
57+
readonly avatar?: ImageReference;
58+
};
59+
60+
// Categories or tags for the blog post
61+
readonly categories?: string[];
62+
63+
// Whether this post should be featured
64+
readonly featured?: boolean;
65+
66+
// Link to the full post
67+
readonly action?: Action;
68+
}
69+
```
70+
71+
Blog post summaries are used to display previews of blog posts in lists, grids, or featured sections.
72+
73+
### Blog Group
74+
75+
The BlogGroup content type represents a collection of blog posts:
76+
77+
```typescript
78+
// Blog group content structure
79+
interface BlogGroup extends ContentItem {
80+
// The main title for the blog section
81+
readonly title: string;
82+
83+
// A supporting text that appears below the title
84+
readonly subtitle?: string;
85+
86+
// Blog posts to display in the section
87+
readonly posts: {
88+
readonly title: string;
89+
readonly excerpt?: string;
90+
readonly image?: ImageReference;
91+
readonly date: string;
92+
readonly author?: {
93+
readonly name: string;
94+
readonly role?: string;
95+
readonly avatar?: ImageReference;
96+
};
97+
readonly categories?: string[];
98+
readonly featured?: boolean;
99+
readonly action: Action;
100+
}[];
101+
102+
// Optional call-to-action button (e.g., "View all posts")
103+
readonly action?: Action;
104+
}
105+
```
106+
107+
Blog groups are used to display collections of blog posts, such as recent posts, featured posts, or category-specific posts.
108+
109+
## Implementation Structure
110+
111+
### Sanity Studio Side
112+
113+
In Sanity Studio, the blog feature is defined with content descriptors and schema builders:
114+
115+
```typescript
116+
// Blog feature descriptor for Sanity
117+
export const blog = new FeatureDescriptor({
118+
name: 'blog',
119+
title: 'Blog',
120+
description: 'Schema for Blog components including posts and post groups',
121+
122+
// Content descriptors define available content types
123+
contents: [
124+
new BlogGroupDescriptor({
125+
layouts: [defaultBlogGroupLayout],
126+
}),
127+
new RouteDescriptor({
128+
regionItems: [
129+
{ type: BlogGroupDescriptor.schemaName },
130+
{ type: BlogPostSummaryDescriptor.schemaName },
131+
],
132+
}),
133+
],
134+
135+
// Schema builders generate Sanity schemas
136+
contentSchemaBuilders: [
137+
new BlogPostSchemaBuilder(),
138+
new BlogGroupSchemaBuilder(),
139+
],
140+
});
141+
```
142+
143+
The BlogPostSchemaBuilder defines the schema for blog posts:
144+
145+
```typescript
146+
// Blog post schema builder
147+
export class BlogPostSchemaBuilder extends ContentSchemaBuilder {
148+
private schema = defineType({
149+
name: 'blog.post.summary',
150+
title: 'Blog Post Summary',
151+
type: 'object',
152+
icon: Icon,
153+
fields: [
154+
defineField({
155+
name: 'title',
156+
title: 'Post Title',
157+
type: 'string',
158+
validation: (Rule) => Rule.required(),
159+
}),
160+
defineField({
161+
name: 'excerpt',
162+
title: 'Excerpt',
163+
type: 'text',
164+
description: 'A short summary of the post',
165+
}),
166+
// More fields...
167+
],
168+
// Preview configuration...
169+
});
170+
171+
constructor() {
172+
super(BlogPostSummaryDescriptor.schemaName);
173+
}
174+
175+
build(descriptors: ContentDescriptor[]) {
176+
return this.schema;
177+
}
178+
}
179+
```
180+
181+
### React Side
182+
183+
In the React application, the blog feature is defined with content builders that render the content:
184+
185+
```typescript
186+
// Blog feature descriptor for React
187+
export const blog = new FeatureDescriptor({
188+
name: 'blog',
189+
title: 'Blog',
190+
description: 'Blog components for building Blog pages',
191+
icon: <Icon />,
192+
193+
extensions: [
194+
new ContentExtensionDescriptor({
195+
// Content builders render the content
196+
contentBuilders: [
197+
new BlogGroupContentBuilder(),
198+
new BlogPostSummaryContentBuilder(),
199+
],
200+
}),
201+
],
202+
});
203+
```
204+
205+
The BlogPostSummaryContentBuilder defines how blog posts are rendered:
206+
207+
```typescript
208+
// Blog post content builder
209+
export class BlogPostSummaryContentBuilder extends ContentBuilder<BlogPostSummary> {
210+
constructor() {
211+
super({
212+
schemaType: BLOG_POST_SUMMARY_SCHEMA_TYPE,
213+
defaultLayout: new DefaultBlogPostSummaryLayout(),
214+
defaultLayoutDescriptor: DefaultBlogPostSummaryLayout.typeDescriptor,
215+
});
216+
}
217+
}
218+
```
219+
220+
## Components
221+
222+
The blog feature includes several React components for rendering blog content:
223+
224+
### BlogPostCard
225+
226+
The BlogPostCard component renders a blog post summary as a card:
227+
228+
```tsx
229+
export const BlogPostCard: React.FC<BlogPostCardProps> = ({
230+
content,
231+
className,
232+
}) => {
233+
const { getImageUrl } = useMediaUtils();
234+
235+
// Format date to a readable string
236+
const formatDate = (dateString: string | undefined) => {
237+
if (!dateString) return null;
238+
const date = new Date(dateString);
239+
return new Intl.DateTimeFormat('en-US', {
240+
year: 'numeric',
241+
month: 'long',
242+
day: 'numeric',
243+
}).format(date);
244+
};
245+
246+
return (
247+
<div
248+
className={cn(
249+
'flex flex-col overflow-hidden rounded-lg transition-all hover:shadow-md',
250+
content.featured
251+
? 'bg-primary/15 border-primary/20 border'
252+
: 'bg-base-100 border-base-300 border',
253+
'cursor-pointer',
254+
className,
255+
)}
256+
onClick={() => executeAction(content.action)}
257+
>
258+
{/* Featured image */}
259+
{content.image && (
260+
<div className="aspect-video overflow-hidden">
261+
<img
262+
src={getImageUrl(content.image)}
263+
alt={content.title}
264+
className="h-full w-full object-cover"
265+
/>
266+
</div>
267+
)}
268+
269+
{/* Card content */}
270+
<div className="flex flex-1 flex-col p-4">
271+
{/* Title, author, date, excerpt, etc. */}
272+
</div>
273+
</div>
274+
);
275+
};
276+
```
277+
278+
## Usage
279+
280+
The blog feature provides a complete solution for building blog sections in your application. Content creators can use Sanity Studio to create and manage blog posts, while developers can use the React components to render those posts in the application.
281+
282+
<Aside type="tip">
283+
The blog feature works well with the marketing feature for creating complete websites with both marketing pages and blog content.
284+
</Aside>
285+
286+

0 commit comments

Comments
 (0)