@waysnx/ui-docs
v0.1.4
Published
Enterprise-grade documentation framework for rendering documentation entirely from structured metadata — JSON driven, component based, and completely generic
Maintainers
Readme
@waysnx/ui-docs
🤖 AI agents & LLMs: See LLM.md (shipped with this package) for a structured integration guide — metadata-driven documentation rendering, component registry, and adapters.
Enterprise-grade documentation framework for React.
Render documentation entirely from structured metadata — JSON driven, component registry, live rendering, full-text search, and AI-ready architecture.
Installation
npm install @waysnx/ui-docs react-markdown react-syntax-highlighterimport '@waysnx/ui-docs/dist/index.css';Quick Start
import {
DocumentationProvider,
JsonDocumentationAdapter,
ComponentRegistry,
RegistryProvider,
useDocumentation,
ComponentHero,
PropsTable,
MarkdownRenderer,
} from '@waysnx/ui-docs';
// 1. Create adapter
const adapter = new JsonDocumentationAdapter({
libraries: libraryData,
components: componentData,
});
// 2. Register real components for live rendering
const registry = new ComponentRegistry();
registry.register('@waysnx/ui-core', 'Button', Button);
registry.register('@waysnx/ui-core', 'Input', Input);
// 3. Wrap your docs app
function App() {
return (
<DocumentationProvider adapter={adapter}>
<RegistryProvider registry={registry}>
<ComponentPage slug="button" />
</RegistryProvider>
</DocumentationProvider>
);
}
// 4. Render docs for any component
function ComponentPage({ slug }: { slug: string }) {
const { loadComponentBySlug } = useDocumentation();
const [component, setComponent] = React.useState(null);
React.useEffect(() => {
loadComponentBySlug('ui-core', slug).then(setComponent);
}, [slug]);
if (!component) return null;
return (
<div>
<ComponentHero component={component} />
<PropsTable props={component.props ?? []} />
{component.markdown && <MarkdownRenderer content={component.markdown} />}
</div>
);
}4-Artifact Documentation Model
Each component can have up to 4 documentation artifacts:
| Artifact | File | Description |
|---|---|---|
| Metadata | component.json | Name, props, examples, accessibility, tags |
| Schema | component.schema.json | JSON Schema for prop types |
| Markdown | component.md | Long-form documentation |
| Demos | component.demo.generated.json | AI-generated examples with metadata |
The JsonDocumentationAdapter loads all 4 in parallel via getMergedDocumentation(id).
Components
| Component | Description |
|---|---|
| ComponentHero | Component header with name, description, category, accessibility badge, tags |
| PropsTable | Props table with types, defaults, required/deprecated indicators |
| MarkdownRenderer | Markdown with PrismJS syntax highlighting |
| DocumentationDemoViewer | Category tabs, example list, code display, metadata panel |
| LiveComponentRenderer | Renders registered components dynamically with props |
Adapters
JsonDocumentationAdapter
const adapter = new JsonDocumentationAdapter({
// Static data
libraries: libraryArray,
components: componentArray,
searchIndex: searchIndexData,
relationships: relationshipsArray,
// Custom loaders for artifacts
baseUrl: '/docs', // fetches /docs/{libraryId}/components/{slug}.schema.json etc.
// Or inject custom loaders
schemaLoader: async (id) => fetch(`/api/schema/${id}`).then(r => r.json()),
markdownLoader: async (id) => fetch(`/api/docs/${id}.md`).then(r => r.text()),
demoLoader: async (id) => fetch(`/api/demos/${id}`).then(r => r.json()),
});
// Load all 4 artifacts at once
const merged = await adapter.getMergedDocumentation('ui-core:button');
// merged = { component, schema, markdown, demos, loadedArtifacts }Custom Adapter
import { BaseDocumentationAdapter } from '@waysnx/ui-docs';
class GraphQLAdapter extends BaseDocumentationAdapter {
async getLibraries() { /* fetch from GraphQL */ }
async getLibrary(id: string) { /* ... */ }
async getComponent(id: string) { /* ... */ }
async getComponentBySlug(libraryId: string, slug: string) { /* ... */ }
async search(query: string) { /* ... */ }
}Component Registry
The registry enables live component rendering in documentation:
import { ComponentRegistry, RegistryProvider, LiveComponentRenderer } from '@waysnx/ui-docs';
const registry = new ComponentRegistry({
// Optional: custom fallback when component not found
fallbackComponent: ({ exportName }) => <div>Component "{exportName}" not registered</div>,
onMissing: (pkg, name) => console.warn(`Missing: ${pkg}/${name}`),
});
// Register components
registry.register('@waysnx/ui-core', 'Button', Button);
registry.register('@waysnx/ui-core', 'Input', Input);
registry.register('@waysnx/ui-feedback', 'Modal', Modal);
// Use in your docs app
<RegistryProvider registry={registry}>
{/* Render any registered component with dynamic props */}
<LiveComponentRenderer
packageName="@waysnx/ui-core"
exportName="Button"
props={{ variant: 'primary', children: 'Click me' }}
/>
</RegistryProvider>Hooks
useDocumentation
const {
isLoading,
error,
libraries,
currentLibrary,
currentComponent,
loadLibraries,
loadLibrary,
loadComponent,
loadComponentBySlug,
search,
getTokens,
getRelationships,
setCurrentLibrary,
setCurrentComponent,
clearError,
} = useDocumentation();useDocumentationSearch
const {
query,
setQuery,
results, // SearchResult[] sorted by relevance
isSearching,
error,
clearSearch,
} = useDocumentationSearch({
debounceMs: 300,
minChars: 2,
});Data Shapes
Library
interface Library {
id: string;
name: string;
description: string;
version: string;
categories: string[];
components: Component[];
tokens?: DesignToken[];
}Component
interface Component {
id: string;
name: string;
slug: string;
description: string;
category: string;
props?: ComponentProp[];
examples?: CodeExample[];
markdown?: string;
accessibility?: AccessibilityInfo;
schema?: ComponentSchema;
demos?: DemoCategory[];
status?: 'stable' | 'beta' | 'experimental' | 'deprecated';
tags?: string[];
businessDomains?: string[];
useCases?: UseCase[];
}DocumentationProvider Props
<DocumentationProvider
adapter={adapter}
enableCaching={true} // default: true — caches library/component loads
>
{children}
</DocumentationProvider>DocumentationDemoViewer
<DocumentationDemoViewer
demos={component.demos}
categoryTabs={true} // show category tab strip
showMetadata={true} // show source, confidence, keywords
onExampleSelect={(id) => console.log('Selected:', id)}
/>License
Apache License 2.0 © WaysNX Technologies Private Limited
