@ayo-core/puck-kit
v0.1.3
Published
Shared Puck components, configuration, and resolver for ayo-frontend and ayo-microsite-frontend
Downloads
690
Maintainers
Readme
@ayo/puck-kit
Shared Puck components, configuration, and utilities for both ayo-frontend (creator studio) and ayo-microsite-frontend (live rendering).
Overview
This package ensures that published Puck JSON renders identically in both the creator preview and the live microsite. It provides:
- Component Registry: Unified set of Puck blocks used across both apps
- Configuration Builder: Factory for creating Puck config in editor or render mode
- Theme Tokens: Shared CSS variables and design tokens
- Resolver: Data hydration system for API-powered blocks
- Services Interface: Contract for environment-specific API implementations
- Schemas & Validation: Zod schemas for type safety
Installation
Option A: Local workspace dependency (development)
In both ayo-frontend and ayo-microsite-frontend:
{
"dependencies": {
"@ayo/puck-kit": "file:../ayo-puck-kit"
}
}Then run npm install or yarn install.
Option B: Private npm registry (production)
Publish to GitHub Packages or a private npm registry and install normally:
npm install @ayo/puck-kitDirectory Structure
src/
├── types/ # Shared type definitions
│ ├── index.ts
│ ├── microsite.ts # MicrositeServices, MicrositeData
│ └── puck.ts # Puck-specific types
├── components/ # Puck block implementations
│ ├── index.ts
│ ├── branding/ # TopNav, BannerHeader, etc.
│ ├── streaming/ # LiveStreamCard, IvsPlayer, etc.
│ ├── videos/ # VideosGrid, VideoPlayerModal
│ ├── games/ # GamesGrid, GameLauncher
│ ├── quests/ # QuestsList, QuestTracking
│ ├── economy/ # Rewards, Leaderboard, Badges
│ └── layout/ # Container, Section, Spacer
├── config/
│ ├── index.ts
│ ├── createMicrositePuckConfig.ts
│ └── fieldDefinitions.ts
├── resolver/ # Data hydration
│ ├── index.ts
│ ├── resolvePuckData.ts
│ └── resolvers/ # Module-specific resolvers
├── tokens/ # Theme & design tokens
│ ├── index.ts
│ ├── theme.ts
│ ├── colors.ts
│ └── tailwind.preset.ts
├── schemas/ # Zod validation
│ ├── index.ts
│ ├── puck.ts
│ └── microsite.ts
└── index.ts # Main exportUsage
1. Basic Setup in ayo-frontend (Creator Studio)
import { createMicrositePuckConfig } from '@ayo/puck-kit/config';
import { applyThemeTokens } from '@ayo/puck-kit/tokens';
const creatorServices = {
getVideos: async (params) => { /* authenticated creator endpoint */ },
getGames: async (params) => { /* ... */ },
// ... other service methods
};
export const puckConfig = createMicrositePuckConfig({
mode: 'editor',
services: creatorServices,
featureFlags: { /* ... */ }
});2. Basic Setup in ayo-microsite-frontend (Live Rendering)
import { createMicrositePuckConfig, resolvePuckData } from '@ayo/puck-kit';
import { applyThemeTokens } from '@ayo/puck-kit/tokens';
const publicServices = {
getVideos: async (params) => { /* public API endpoint */ },
getGames: async (params) => { /* ... */ },
// ... other service methods
};
// Fetch published Puck JSON from API
const puckData = await fetchPublishedPuckData(subdomain);
// Resolve data (fetch any external data blocks need)
const resolvedData = await resolvePuckData(puckData, publicServices);
// Render
const config = createMicrositePuckConfig({
mode: 'render',
services: publicServices,
});
export function MicrositePage() {
return (
<div style={applyThemeTokens(puckData.root?.props?.theme)}>
<Render config={config} data={resolvedData} />
</div>
);
}Key Concepts
Services Interface
All data fetching goes through a MicrositeServices interface:
export interface MicrositeServices {
// Microsite config
getMicrosite(subdomain: string): Promise<Microsite>;
// Streaming
getActiveLiveStream(micrositeId: string): Promise<LiveStream | null>;
// Videos
getMicrositeVideos(micrositeId: string): Promise<Video[]>;
// Quests
getMicrositeQuests(micrositeId: string): Promise<Quest[]>;
// Rewards
getMicrositeRewards(micrositeId: string): Promise<Reward[]>;
// ... more methods
}Each app implements this interface differently:
- Creator: Uses authenticated endpoints, preview data
- Microsite: Uses public endpoints, caching, guest auth
Puck Config Modes
// Editor mode: full fields + editing helpers
const editorConfig = createMicrositePuckConfig({ mode: 'editor', ... });
// Render mode: stripped down, production-ready
const renderConfig = createMicrositePuckConfig({ mode: 'render', ... });Both use identical component names — this is critical for JSON compatibility.
Data Resolver
Before rendering, resolve external data:
const resolvedData = await resolvePuckData(puckData, services);
// Now puckData blocks have props.resolved with fetched dataThis ensures:
- Creator preview ≈ live output
- No loading jank during render
- Deterministic testing
Theme Tokens
Apply theme via CSS variables:
const themeStyle = applyThemeTokens({
primaryColor: '#6366f1',
backgroundColor: '#ffffff',
radius: 'md'
});
<div style={themeStyle}>
<Render config={config} data={data} />
</div>Migration Checklist
- [ ] Move existing Puck components into
src/components/ - [ ] Extract theme tokens and Tailwind preset
- [ ] Create
MicrositeServicesimplementations in both apps - [ ] Build resolver for priority data-powered blocks (Videos, Quests, Rewards)
- [ ] Add snapshot tests for key components
- [ ] Publish initial version
- [ ] Update both apps to import from
@ayo/puck-kit - [ ] Verify no "unknown block type" errors in published data
- [ ] Add schema version + migrations (phase 2)
Testing
npm run build # TypeScript compilation
npm run type-check # Type checking only
npm run test # Run vitest suite
npm run test:ui # Interactive test UIDevelopment
npm run dev # Watch mode TypeScript compilation
npm run lint # ESLintVersioning & Breaking Changes
Since Puck JSON is stored long-term:
- Never rename component types without a migration
- Use
schemaVersionin root props to track migrations - Maintain migration functions in
src/schemas/ - Always backward-compatible resolver
Contributing
- Keep components framework-light (avoid Next.js-only APIs)
- If something is Next-specific, provide two implementations
- All new blocks should have TypeScript interfaces
- Add tests for resolver changes
- Update this README with new exports
License
UNLICENSED (Internal to Ayo)
