Skip to content

Commit fb9a93c

Browse files
committed
feat(cosmic-blueprint): add Cosmic Blueprint visual with metadata, sample data, and schema
- Introduced metadata.json for Cosmic Blueprint with essential details. - Created sample-data.json containing a comprehensive birth chart analysis. - Developed schema.ts using Zod for data validation and structure. - Updated list.json to include Cosmic Blueprint in the visuals catalog.
1 parent 8da5302 commit fb9a93c

10 files changed

Lines changed: 1324 additions & 121 deletions

File tree

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
---
2+
name: visual-development
3+
description: Create and edit visual components for VizuLLM. Use when building new visuals, editing schemas, components, or sample data under the visuals/ directory. Covers Zod schema patterns, React component structure, Tailwind styling, print-ready layout, and section title localization.
4+
metadata:
5+
tags: vizullm, visual, component, schema, react, zod, tailwind
6+
---
7+
8+
# Visual Component Development
9+
10+
## Creating a New Visual
11+
12+
Run the generator script:
13+
14+
```bash
15+
npm run generate-visual -- --name "Visual Name" --description "Clear description covering UI and use-cases" --author "github-username"
16+
```
17+
18+
After generation, edit the files inside. Do not change file structure or export defaults.
19+
20+
## File Structure
21+
22+
Every visual has exactly 4 files inside `visuals/<slug>/`:
23+
24+
| File | Purpose |
25+
|---|---|
26+
| `schema.ts` | Zod schema — all data validation |
27+
| `component.tsx` | React component with error handling |
28+
| `sample-data.json` | Realistic data that validates against the schema |
29+
| `metadata.json` | Name, description, author, version |
30+
31+
Do NOT add README, extra sample files, tabs, or accordions.
32+
33+
## Schema Pattern (`schema.ts`)
34+
35+
Use Zod for all validation. Extract reusable helpers to keep the schema concise.
36+
37+
### Section Title Pattern
38+
39+
Every section must support optional `title` and `subtitle` overrides so the LLM can localize them.
40+
41+
**For array sections** — wrap in a `titled()` helper:
42+
43+
```typescript
44+
const Percentage = z.number().min(0).max(100);
45+
46+
const titled = (content: z.ZodTypeAny) =>
47+
z.object({
48+
title: z.string().optional(),
49+
subtitle: z.string().optional(),
50+
content,
51+
});
52+
53+
// Usage — clean and short:
54+
elements: titled(z.array(z.object({ element: z.string(), percentage: Percentage }))),
55+
growthAreas: titled(z.array(z.string())),
56+
motto: titled(z.string()),
57+
```
58+
59+
**For object sections** — add `title` / `subtitle` directly as optional fields:
60+
61+
```typescript
62+
executiveSummary: z.object({
63+
title: z.string().optional(),
64+
summary: z.string(),
65+
overallScore: Percentage,
66+
}),
67+
```
68+
69+
**For sub-labels within sections** — add optional title fields:
70+
71+
```typescript
72+
learningPreferences: z.object({
73+
title: z.string().optional(),
74+
subtitle: z.string().optional(),
75+
methods: z.array(z.object({ label: z.string(), percentage: Percentage })),
76+
learnsBestThrough: z.array(z.string()),
77+
learnsBestThroughTitle: z.string().optional(),
78+
strugglesWith: z.array(z.string()),
79+
strugglesWithTitle: z.string().optional(),
80+
}),
81+
```
82+
83+
### Schema Conciseness Rules
84+
85+
- Extract shared types (`Percentage`, `Degree`) as reusable constants
86+
- Use `titled()` for array/string sections — never repeat `title`/`subtitle`/`content` manually
87+
- Use `.extend({})` on `titled()` when a section needs extra optional fields
88+
- Keep the schema as short as possible — the JSON Schema is copied as an LLM prompt
89+
90+
## Component Pattern (`component.tsx`)
91+
92+
### Required Props Interface
93+
94+
```typescript
95+
interface YourComponentProps {
96+
schema: typeof YourComponentSchema | null;
97+
data?: YourComponentData | null;
98+
}
99+
```
100+
101+
### Error Handling
102+
103+
```typescript
104+
let validatedData: YourComponentData;
105+
try {
106+
validatedData = data
107+
? YourComponentSchema.parse(data)
108+
: YourComponentSchema.parse(sampleData);
109+
} catch (error) {
110+
console.error('Data validation failed:', error);
111+
validatedData = YourComponentSchema.parse(sampleData);
112+
}
113+
```
114+
115+
### Using Titles
116+
117+
Read `title` / `subtitle` directly from each section with inline fallbacks:
118+
119+
```tsx
120+
<SectionTitle number={2} title={d.coreTraits.title ?? 'Core Traits'} subtitle={d.coreTraits.subtitle ?? 'Trait visualization'} />
121+
<RadarChart traits={d.coreTraits.content} />
122+
```
123+
124+
No `t()` function, no `resolveTitle` helper — just `section.title ?? 'Default'`.
125+
126+
For sub-labels:
127+
128+
```tsx
129+
<h3>{d.operatingGuide.worksBestWhenTitle ?? 'Works Best When'}</h3>
130+
```
131+
132+
### Component Registration
133+
134+
Always register at the bottom:
135+
136+
```typescript
137+
if (typeof window !== 'undefined' && window.__registerVisualComponent) {
138+
window.__registerVisualComponent('your-slug', YourComponent);
139+
}
140+
```
141+
142+
## Styling Rules
143+
144+
- **Tailwind CSS 3.4.17** only — no inline styles for layout
145+
- **Mobile-first** responsive design
146+
- **Semantic HTML** (`main`, `section`, `header`)
147+
- **ARIA labels** on interactive elements and SVGs
148+
- **Print-ready**: transparent backgrounds, no dynamic UI (tabs, accordions)
149+
- **No VizuLLM branding** on components
150+
- Use `React.memo` for expensive sub-components (charts, SVGs)
151+
152+
## Sample Data (`sample-data.json`)
153+
154+
- Must validate against the schema
155+
- Use realistic, meaningful content — no "Lorem ipsum"
156+
- Array sections go under `content` key:
157+
158+
```json
159+
{
160+
"coreTraits": {
161+
"content": [
162+
{ "name": "Creativity", "score": 92 }
163+
]
164+
},
165+
"motto": {
166+
"content": "Build first, optimize later."
167+
}
168+
}
169+
```
170+
171+
## Validation
172+
173+
After creating or editing a visual:
174+
175+
1. Run `npm run update-list` to update the visual list
176+
2. Ensure no lint errors in the component files
177+
3. Run `npx tsc --project tsconfig.json --noEmit` to type-check

index.html

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,15 @@
44
<meta charset="UTF-8" />
55
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7-
7+
<!-- Google tag (gtag.js) -->
8+
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XVNZH5E50S"></script>
9+
<script>
10+
window.dataLayer = window.dataLayer || [];
11+
function gtag(){dataLayer.push(arguments);}
12+
gtag('js', new Date());
13+
14+
gtag('config', 'G-XVNZH5E50S');
15+
</script>
816
<!-- Primary Meta Tags -->
917
<title>VizuLLM - Schema-Driven Rendering Engine for LLM-Generated Documents</title>
1018
<meta name="title" content="VizuLLM - Schema-Driven Rendering Engine for LLM-Generated Documents" />
@@ -13,7 +21,7 @@
1321
<meta name="author" content="VizuLLM Community" />
1422
<meta name="robots" content="index, follow" />
1523
<meta name="language" content="English" />
16-
24+
1725
<!-- Open Graph / Facebook -->
1826
<meta property="og:type" content="website" />
1927
<meta property="og:url" content="https://vizullm.com/" />
@@ -24,28 +32,28 @@
2432
<meta property="og:image:height" content="630" />
2533
<meta property="og:site_name" content="VizuLLM" />
2634
<meta property="og:locale" content="en_US" />
27-
35+
2836
<!-- Twitter -->
2937
<meta property="twitter:card" content="summary_large_image" />
3038
<meta property="twitter:url" content="https://vizullm.com/" />
3139
<meta property="twitter:title" content="VizuLLM - Schema-Driven Rendering Engine for LLM-Generated Documents" />
3240
<meta property="twitter:description" content="Transform your LLM outputs into beautiful, printable visualizations with just a few clicks. Type-safe visual components built with React, TypeScript, and Zod schemas." />
3341
<meta property="twitter:image" content="https://vizullm.com/logo.jpg" />
34-
42+
3543
<!-- Additional Meta Tags -->
3644
<meta name="theme-color" content="#3B82F6" />
3745
<meta name="msapplication-TileColor" content="#3B82F6" />
3846
<meta name="apple-mobile-web-app-capable" content="yes" />
3947
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
4048
<meta name="apple-mobile-web-app-title" content="VizuLLM" />
41-
49+
4250
<!-- Canonical URL -->
4351
<link rel="canonical" href="https://vizullm.com/" />
44-
52+
4553
<!-- Preconnect to external domains -->
4654
<link rel="preconnect" href="https://fonts.googleapis.com" />
4755
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
48-
56+
4957
<script type="text/javascript">
5058
// Single Page Apps for GitHub Pages
5159
// MIT License
@@ -59,7 +67,7 @@
5967
// the single page app to route accordingly.
6068
(function(l) {
6169
if (l.search[1] === '/' ) {
62-
var decoded = l.search.slice(1).split('&').map(function(s) {
70+
var decoded = l.search.slice(1).split('&').map(function(s) {
6371
return s.replace(/~and~/g, '&')
6472
}).join('?');
6573
window.history.replaceState(null, null,

0 commit comments

Comments
 (0)