@creatiq/ui-sdk Reference
Overview
@creatiq/ui-sdk is a React component library that packages Creatiq's content management, AI generation, and H5P player/editor functionality as embeddable components. The SDK allows external applications (LMS platforms, corporate portals, whitelabel products) to integrate Creatiq's features without hosting the Creatiq backend -- the backend remains at creatiq.app while the SDK provides the UI layer.
The SDK ships 9 export paths, each independently tree-shakeable:
| Export Path | Purpose |
|---|---|
@creatiq/ui-sdk | Root -- provider, hooks, types, player, editor, picker, workspace |
@creatiq/ui-sdk/browser | Content browsing components (grid, filters, cards) |
@creatiq/ui-sdk/player | H5P content player (iframe-based) |
@creatiq/ui-sdk/editor | H5P content editor (iframe-based) |
@creatiq/ui-sdk/collections | Collection management UI |
@creatiq/ui-sdk/ai | AI copilot for content generation |
@creatiq/ui-sdk/ui | Shared UI primitives (Radix-based) |
@creatiq/ui-sdk/picker | Content picker sheet (3-tab selector) |
@creatiq/ui-sdk/workspace | Full workspace embed (all views) |
Installation
npm install @creatiq/ui-sdk
Peer Dependencies
{
"react": "^18.0.0",
"react-dom": "^18.0.0",
"@lumieducation/h5p-react": "^10.0.0",
"@lumieducation/h5p-server": "^10.0.0"
}
CSS Import
The SDK ships a bundled CSS file that must be imported once:
import '@creatiq/ui-sdk/styles.css';
Configuration -- CreatiqProvider
All SDK components must be wrapped in <CreatiqProvider>. This component:
- Injects configuration, authentication, and theme into the React tree
- Fetches user profile and plan features on mount via
GET /api/auth/me - Applies theme CSS custom properties to
:root - Handles token refresh via the
onTokenExpiredcallback
Setup
import { CreatiqProvider } from '@creatiq/ui-sdk';
import '@creatiq/ui-sdk/styles.css';
function App() {
return (
<CreatiqProvider
config={{
baseUrl: 'https://creatiq.app',
token: '<sdk-token>',
locale: 'en',
theme: {
colorPrimary: '#6366f1',
borderRadius: '0.5rem',
},
ai: {
enabled: true,
features: { chat: true, bulkGenerate: true, remix: true },
},
onTokenExpired: async () => {
// Call your backend to get a fresh SDK token
const res = await fetch('/api/creatiq/refresh-token');
const { token } = await res.json();
return token;
},
}}
>
{/* SDK components go here */}
</CreatiqProvider>
);
}
CreatiqConfig
interface CreatiqConfig {
baseUrl: string; // Creatiq API base URL
token: string; // SDK token (from POST /api/sdk/token)
locale?: 'en' | 'tr' | 'fr' | 'es' | 'ar'; // UI locale (default: 'en')
theme?: Partial<CreatiqTheme>; // Theme overrides
ai?: CreatiqAIConfig; // AI module config (undefined = disabled)
onTokenExpired?: () => Promise<string>; // Token refresh callback
onLogout?: () => void; // Logout callback
onLocaleChange?: (locale: string) => void; // Locale change callback
tenantId?: string; // Optional tenant identifier
}
CreatiqTheme
Theme tokens are injected as CSS custom properties prefixed with --crq-:
| Property | CSS Variable |
|---|---|
colorPrimary | --crq-color-primary |
colorPrimaryForeground | --crq-color-primary-foreground |
colorBackground | --crq-color-background |
colorSurface | --crq-color-surface |
colorText | --crq-color-text |
colorMuted | --crq-color-muted |
colorBorder | --crq-color-border |
colorDestructive | --crq-color-destructive |
borderRadius | --crq-border-radius |
fontFamily | --crq-font-family |
CreatiqAIConfig
interface CreatiqAIConfig {
enabled: boolean;
features?: {
chat?: boolean;
bulkGenerate?: boolean;
remix?: boolean;
imageAnalysis?: boolean;
videoAnalysis?: boolean;
};
}
Context Hooks
useCreatiq() // Full context (config, user, features, getToken, refreshToken, apiUrl)
useCreatiqConfig() // SDK configuration only
useCreatiqUser() // Authenticated user (CreatiqUser | null)
useCreatiqFeatures() // Plan features and usage limits (CreatiqFeatures | null)
CreatiqUser
interface CreatiqUser {
id: string;
email: string;
name: string;
role: string;
plan: 'free' | 'pro' | 'premium';
}
CreatiqFeatures
interface CreatiqFeatures {
plan: string;
contentTypes: string[];
limits: {
monthlyGenerations: number;
remainingGenerations: number;
monthlyContents: number;
remainingContents: number;
};
flags: Record<string, boolean>;
}
Export Modules
@creatiq/ui-sdk/browser
Content browsing and filtering components. Renders the user's H5P content library with search, filters, and sorting.
Components:
| Component | Description |
|---|---|
ContentBrowser | Full content browser with filters, search, grid/list toggle |
ContentCard | Individual content card with actions (play, edit, export, delete) |
ContentCardList | Content list layout |
ContentFilters | Filter controls (content type, framework, grade, subject, difficulty) |
ContentEmptyState | Empty state placeholder |
ContentSkeleton | Loading skeleton |
DifficultyBadge | Difficulty level badge |
PublicContentBrowser | Community marketplace browser with pagination |
PublicContentCard | Public content card |
CurriculumFilters | Curriculum-specific filter controls |
Utilities:
| Export | Description |
|---|---|
CONTENT_TYPE_CONFIG | Map of H5P content type metadata (icon, label, category) |
getContentTypeConfig(slug) | Get config for a content type slug |
getContentTypeLabelBySlug(slug) | Get display label for a content type |
Usage:
import { ContentBrowser } from '@creatiq/ui-sdk/browser';
import { useContentBrowser } from '@creatiq/ui-sdk';
function MyContentPage() {
const browser = useContentBrowser();
useEffect(() => {
browser.loadContents();
}, []);
return (
<ContentBrowser
contents={browser.contents}
filteredContents={browser.filteredContents}
loading={browser.loading}
displayMode="grid"
// ... filter props from browser hook
/>
);
}
@creatiq/ui-sdk/player
Iframe-based H5P content player. Renders content via {baseUrl}/embed/{contentId} and communicates through postMessage.
Exports:
| Export | Description |
|---|---|
CreatiqPlayer | Player component |
isCreatiqMessage(data) | Type guard for child-to-parent messages |
isCreatiqParentMessage(data) | Type guard for parent-to-child messages |
ParentMessage | Union type for SDK-to-iframe messages |
ChildMessage | Union type for iframe-to-SDK messages |
CreatiqPlayerProps:
interface CreatiqPlayerProps {
contentId: string; // H5P content ID
onXAPIStatement?: (statement: unknown) => void; // xAPI statement callback
onReady?: (contentId: string) => void; // Content loaded callback
onError?: (error: string) => void; // Error callback
onFullscreen?: (active: boolean) => void; // Fullscreen toggle callback
className?: string; // Wrapper div class
minHeight?: number; // Min height in px (default: 200)
maxHeight?: number; // Max height in px (default: none)
fillContainer?: boolean; // Fill parent height (default: false)
}
Usage:
import { CreatiqPlayer } from '@creatiq/ui-sdk/player';
<CreatiqPlayer
contentId="abc123"
onXAPIStatement={(stmt) => console.log('xAPI:', stmt)}
onReady={(id) => console.log('Ready:', id)}
minHeight={300}
/>
The player automatically:
- Builds the iframe URL with token authentication
- Listens for
creatiq:resizemessages and adjusts height - Forwards locale and theme changes to the iframe via postMessage
- Shows a loading spinner until
creatiq:readyis received - Validates message origins against
config.baseUrl
@creatiq/ui-sdk/editor
Iframe-based H5P content editor. Renders via {baseUrl}/embed/editor/{contentId} for editing, or {baseUrl}/embed/editor/new for creation.
Exports:
| Export | Description |
|---|---|
CreatiqEditor | Editor component |
CreatiqEditorSaveResult | Save result type |
CreatiqEditorProps:
interface CreatiqEditorProps {
contentId?: string; // Existing content ID (undefined = new)
language?: string; // Editor UI language (default: config.locale)
onSave?: (result: CreatiqEditorSaveResult) => void; // Content saved callback
onContentChanged?: () => void; // Dirty flag callback
onError?: (error: string) => void; // Error callback
onReady?: (contentId: string) => void; // Editor loaded callback
className?: string; // Wrapper div class
height?: number; // Height in px (default: 600)
}
interface CreatiqEditorSaveResult {
contentId: string;
metadata: unknown;
}
Usage:
import { CreatiqEditor } from '@creatiq/ui-sdk/editor';
// Edit existing content
<CreatiqEditor
contentId="abc123"
onSave={(result) => console.log('Saved:', result.contentId)}
height={700}
/>
// Create new content
<CreatiqEditor
onSave={(result) => console.log('Created:', result.contentId)}
/>
@creatiq/ui-sdk/collections
Collection management components for organizing H5P content into curated sets.
Components:
| Component | Description |
|---|---|
CollectionList | Grid of collection cards |
CollectionCard | Single collection card with metadata |
CollectionDetail | Full collection view with items, reordering, suggestions |
CollectionItemCard | Individual item within a collection |
CollectionCreateModal | Modal for creating new collections with curriculum metadata |
CollectionPickerModal | Modal for selecting an existing collection |
ContentPickerModal | Modal for adding content to a collection |
ContentPreviewModal | Content preview overlay |
BloomsDistributionChart | Bloom's taxonomy distribution chart |
LibraryPicker | Content picker from user's library |
CommunityPicker | Content picker from community marketplace |
Data hooks (from root export):
useCollections() // List, create, delete collections
useCollectionDetail(collectionId) // Detail view, items, suggestions, CRUD
Usage:
import { CollectionList, CollectionCard } from '@creatiq/ui-sdk/collections';
import { useCollections } from '@creatiq/ui-sdk';
function MyCollections() {
const { collections, isLoading, createCollection, deleteCollection } = useCollections();
return (
<div className="grid grid-cols-2 gap-4">
{collections.map((c) => (
<CollectionCard
key={c.id}
collection={c}
onClick={(id) => navigate(`/collections/${id}`)}
onDelete={deleteCollection}
/>
))}
</div>
);
}
@creatiq/ui-sdk/ai
AI copilot module for AI-powered H5P content generation. This is the largest SDK module, providing a full multi-screen generation wizard.
Main Components:
| Component | Description |
|---|---|
CreatiqAISidebar | Full sidebar with view routing (Home -> Generate -> Result -> Chat) |
CreatiqAISidebarProps:
interface CreatiqAISidebarProps {
onContentCreated?: (content: { contentId: string; params: unknown; library: string }) => void;
onClose?: () => void;
collapsed?: boolean;
onToggleCollapse?: () => void;
onCreateContent?: (content: { library: string; params: unknown; tempImageFiles?: string[] }, title?: string) => Promise<void>;
courseContext?: CourseCreationContext | null;
language?: string;
userPlan?: string;
className?: string;
}
Views (CreatiqAIView): 'home' | 'generate' | 'result' | 'chat'
Source Types (SourceType): 'topic' | 'document' | 'video' | 'url' | 'image' | 'remix'
Generation Modes: 'single' | 'bulk' | 'differentiated' | 'remix' | 'scenario'
Sub-components (30+ exported):
- Views:
AIHome,AIHeader,ResultView,ChatView,Onboarding,Upsell,CurriculumBar - Generate screens:
GenerateText,GenerateDocument,GenerateVideo,GenerateUrl,GenerateImage,GenerateRemix,GenerateScreenShell - Result views:
ResultBulkView,ResultDiffView,ResultQualitySection,ResultActionButtons,ContentPreview - Utilities:
BloomsBadge,BloomsDistributionChart,QualityBadge,RemixMenu,BaseDropZone,FileDropZone,ImageDropZone,SelectField,DecisionTreePreview,StockImagePicker,ContentTypeCard,ContentTypeGrid,TopicSelector,TypingIndicator
Hooks:
| Hook | Description |
|---|---|
useCreatiqAI() | Main generation hook (generate function, API client, store access) |
useAIChat() | Chat conversation management |
useTextGeneration() | Text-based content generation |
useDocumentGeneration() | Document upload and generation |
useVideoGeneration() | Video analysis and generation |
useImageGeneration() | Image analysis and generation |
useBulkGeneration() | Bulk content generation |
useMultimodalGeneration() | Multimodal (video/image) generation |
useContentTypeRegistry() | H5P content type registry |
useStockImageSearch() | Stock image search |
Store:
useCreatiqAIStore() // Zustand store for AI panel state, generation state, chat messages, preferences
The store persists user preferences (language, difficulty) to localStorage under key creatiq-ai-store.
API Client:
createAIApi(ctx) // Returns CreatiqAIApiClient with methods for all AI endpoints
Usage:
import { CreatiqAISidebar } from '@creatiq/ui-sdk/ai';
<CreatiqAISidebar
onContentCreated={(content) => {
console.log('Created:', content.contentId);
}}
courseContext={{
frameworkCode: 'CCSS',
gradeCode: '5',
subjectCode: 'MATH',
}}
language="en"
userPlan="pro"
/>
@creatiq/ui-sdk/ui
Shared UI primitives built on Radix UI. These are the building blocks used by all other SDK modules.
Components:
| Component | Based On |
|---|---|
Button, buttonVariants | Custom with CVA |
Input | Custom |
Label | @radix-ui/react-label |
Badge, badgeVariants | Custom with CVA |
Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent | Custom |
Dialog, DialogPortal, DialogOverlay, DialogClose, DialogTrigger, DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription | @radix-ui/react-dialog |
Tooltip, TooltipTrigger, TooltipContent, TooltipProvider | @radix-ui/react-tooltip |
Skeleton | Custom |
ScrollArea, ScrollBar | @radix-ui/react-scroll-area |
Select, SelectGroup, SelectValue, SelectTrigger, SelectContent, SelectLabel, SelectItem, SelectSeparator, SelectScrollUpButton, SelectScrollDownButton | @radix-ui/react-select |
Popover, PopoverTrigger, PopoverContent | @radix-ui/react-popover |
Textarea | Custom |
Sheet, SheetPortal, SheetOverlay, SheetTrigger, SheetClose, SheetContent, SheetHeader, SheetFooter, SheetTitle, SheetDescription | @radix-ui/react-dialog |
Tabs, TabsList, TabsTrigger, TabsContent | @radix-ui/react-tabs |
Toast, ToastProvider, ToastViewport, ToastTitle, ToastDescription, ToastClose, ToastAction | @radix-ui/react-toast |
@creatiq/ui-sdk/picker
Content picker sheet -- a slide-out panel with three tabs for selecting H5P content from multiple sources.
Exports:
| Export | Description |
|---|---|
ContentPickerSheet | Sheet component with My Content, Collections, Community tabs |
ContentPickerSheetProps | Props type |
SelectedContentItem | Selected item type |
ContentPickerSheetProps:
interface ContentPickerSheetProps {
open: boolean;
onOpenChange: (open: boolean) => void;
existingContentIds?: string[]; // IDs to disable (already attached)
onContentSelected: (items: SelectedContentItem[]) => void; // Selection callback
title?: string; // Custom sheet title
}
interface SelectedContentItem {
contentId: string;
title: string;
contentType: string;
contentTypeSlug: string;
thumbnailUrl?: string | null;
}
Tabs:
- My Content -- User's own H5P content library with filters
- Collections -- Browse collections, drill into collection items
- Community -- Public marketplace content
Usage:
import { ContentPickerSheet } from '@creatiq/ui-sdk/picker';
const [open, setOpen] = useState(false);
<ContentPickerSheet
open={open}
onOpenChange={setOpen}
existingContentIds={['id1', 'id2']}
onContentSelected={(items) => {
items.forEach((item) => attachContent(item.contentId));
}}
/>
@creatiq/ui-sdk/workspace
Full workspace embed that bundles all views into a single component with top-bar navigation and animated view switching.
Exports:
| Export | Description |
|---|---|
CreatiqWorkspace | Full workspace component |
WorkspaceTopBar | Context-aware navigation bar (also usable standalone) |
WorkspaceView: 'collections' | 'collection-detail' | 'smart-collection' | 'create' | 'play' | 'settings'
CreatiqWorkspaceProps:
interface CreatiqWorkspaceProps {
defaultView?: WorkspaceView; // Initial view (default: 'collections')
onContentCreated?: (content: { contentId: string }) => void; // Content created callback
onViewChange?: (view: WorkspaceView) => void; // View change callback
className?: string;
compact?: boolean; // Compact mode for embed
searchQuery?: string; // External search query
}
Views:
collections-- Grid of collections with search and create actionscollection-detail-- Single collection with items, reorderingsmart-collection-- Virtual collections (uncategorized, recent)create-- H5P editor with AI wizardplay-- H5P playersettings-- User settings
Usage:
import { CreatiqWorkspace } from '@creatiq/ui-sdk/workspace';
<div style={{ height: '100vh' }}>
<CreatiqWorkspace
defaultView="collections"
onContentCreated={(c) => console.log('Created:', c.contentId)}
onViewChange={(view) => console.log('View:', view)}
/>
</div>
Data Hooks (Root Export)
These hooks are exported from the root @creatiq/ui-sdk path and use useSdkFetch internally for authenticated API calls.
useContentBrowser
Provides content browsing, filtering, sorting, visibility toggle, delete, and export.
const {
contents, // ContentItem[]
filteredContents, // Filtered and sorted array
loading, // boolean
searchQuery, // string
contentTypeFilter, // string | null
frameworkFilter, // string | null
gradeFilter, // string | null
subjectFilter, // string | null
difficultyFilter, // string | null
sortBy, // 'newest' | 'oldest' | 'az' | 'za' | 'quality'
availableContentTypes, // string[] (derived from contents)
availableFrameworks, // string[]
availableGrades, // string[]
availableSubjects, // string[]
setSearchQuery,
setContentTypeFilter,
setFrameworkFilter,
setGradeFilter,
setSubjectFilter,
setDifficultyFilter,
setSortBy,
loadContents, // () => Promise<void>
handleToggleVisibility,
deleteContent,
exportContent,
} = useContentBrowser();
useCollections
const {
collections, // Collection[]
total, // number
isLoading, // boolean
error, // string | null
loadCollections, // (offset?, limit?) => Promise<void>
createCollection, // (data: CreateCollectionPayload) => Promise<Collection>
deleteCollection, // (id: string) => Promise<void>
} = useCollections();
useCollectionDetail
const {
detail, // CollectionDetail | null
suggestions, // CollectionSuggestions | null
isLoading,
isSuggestionsLoading,
error,
loadDetail, // (id: string) => Promise<void>
loadSuggestions, // (id: string) => Promise<void>
updateCollection, // (updates: UpdateCollectionPayload) => Promise<void>
addItem, // (contentId: string) => Promise<void>
addItems, // (contentIds: string[]) => Promise<void>
removeItem, // (itemId: string) => Promise<void>
reorderItems, // (items: { id, position }[]) => Promise<void>
} = useCollectionDetail(collectionId);
usePublicContents
const {
contents, // PublicContentItem[]
total, // number
filter, // PublicContentFilter
isLoading,
error,
facets, // MarketplaceFacets | null
updateFilter, // (updates: Partial<PublicContentFilter>) => void
nextPage,
prevPage,
refetch,
} = usePublicContents(initialFilter?);
API Utilities
sdkFetch
Low-level fetch utility with automatic token injection, 401 retry with token refresh, and 30-second timeout.
import { sdkFetch } from '@creatiq/ui-sdk';
const result = await sdkFetch<MyType>(ctx, '/api/some-endpoint', {
method: 'POST',
body: JSON.stringify(data),
});
useSdkFetch
Hook providing typed HTTP helpers bound to the current SDK context.
const { get, post, patch, put, del } = useSdkFetch();
const result = await get<ContentItem[]>('/h5p/content');
const created = await post<Collection>('/api/collections', { title: 'My Set' });
All methods return ApiResponse<T>:
interface ApiResponse<T = unknown> {
success: boolean;
data?: T;
error?: string;
total?: number;
}
Internationalization
The SDK uses an isolated i18next instance (via i18next.createInstance()) so it never conflicts with the host app's i18n setup.
Supported locales: en, tr, fr, es, ar
Translations are bundled at build time. The SDK locale follows config.locale passed to CreatiqProvider.
import { initSDKI18n, getSDKI18n, resetSDKI18n } from '@creatiq/ui-sdk';
// Initialize with overrides
await initSDKI18n('tr', { 'picker.title': 'Custom Title' });
// Inside components
import { useSDKI18n } from '@creatiq/ui-sdk';
const { t } = useSDKI18n();
Animations
The SDK includes framer-motion animation presets with reduced-motion support.
import {
fadeInUp, fadeIn, scaleIn, scaleUp,
pageVariants, panelVariants,
slideInFromRight, slideInFromLeft,
staggerContainer, staggerItem,
counterUp, createStaggerContainer,
getReducedMotionVariants,
useReducedMotion, useMotionSafe,
} from '@creatiq/ui-sdk';
useReducedMotion() reads prefers-reduced-motion from the OS and disables animations when enabled.
Build Configuration
The SDK is built with Vite library mode producing both ESM and CJS outputs.
| Setting | Value |
|---|---|
| Build tool | Vite 6 + @vitejs/plugin-react |
| Type generation | vite-plugin-dts |
| Output formats | ESM (.js) + CJS (.cjs) |
| Output directory | dist/ |
| CSS | Bundled as dist/styles.css |
| External dependencies | react, react-dom, react/jsx-runtime, @lumieducation/h5p-react, @lumieducation/h5p-server |
| Shared chunk | shared-context (ensures single CreatiqContext instance across sub-path imports) |
| Path alias | @sdk -> src/ |
Entry Points
Each export path has its own entry:
src/index.ts -> dist/index.js + dist/index.cjs
src/browser/index.ts -> dist/browser/index.js + dist/browser/index.cjs
src/player/index.ts -> dist/player/index.js + dist/player/index.cjs
src/editor/index.ts -> dist/editor/index.js + dist/editor/index.cjs
src/collections/index.ts -> dist/collections/index.js + dist/collections/index.cjs
src/ai/index.ts -> dist/ai/index.js + dist/ai/index.cjs
src/ui/index.ts -> dist/ui/index.js + dist/ui/index.cjs
src/picker/index.ts -> dist/picker/index.js + dist/picker/index.cjs
src/workspace/index.ts -> dist/workspace/index.js + dist/workspace/index.cjs
Development
npm run dev # Watch mode
npm run build # Production build
npm run lint # ESLint
npm run typecheck # TypeScript check
Key Types
ContentItem
interface ContentItem {
id: string;
title: string;
mainLibrary: string;
contentTypeSlug: string;
createdAt: string;
updatedAt: string;
embedTypes?: string[];
curriculum?: {
frameworkName: string;
stageName: string | null;
gradeName: string;
subjectName: string;
topicNames: string[];
difficulty: string;
language: string;
} | null;
quality?: { overallScore: number; bloomsLevel: string } | null;
visibility?: 'private' | 'public';
viewCount?: number;
}
Collection
interface Collection {
id: string;
userId: string;
title: string;
description: string | null;
coverImageUrl: string | null;
visibility: 'private' | 'public';
frameworkCode: string | null;
frameworkName: string | null;
gradeCode: string | null;
gradeName: string | null;
subjectCode: string | null;
subjectName: string | null;
topicCodes: string[];
topicNames: string[];
difficulty: string | null;
language: string | null;
itemCount: number;
createdAt: string;
updatedAt: string;
}
PostMessage Protocol
// SDK -> iframe (parent -> child)
type ParentMessage =
| { type: 'creatiq:auth'; token: string }
| { type: 'creatiq:locale'; locale: string }
| { type: 'creatiq:theme'; theme: Record<string, string> };
// iframe -> SDK (child -> parent)
type ChildMessage =
| { type: 'creatiq:ready'; contentId: string }
| { type: 'creatiq:xapi'; contentId: string; statement: unknown }
| { type: 'creatiq:resize'; contentId: string; height: number }
| { type: 'creatiq:error'; contentId: string; message: string }
| { type: 'creatiq:fullscreen'; contentId: string; active: boolean }
| { type: 'creatiq:saved'; contentId: string; metadata: unknown }
| { type: 'creatiq:content-changed'; contentId: string };