A lightweight, production-ready frontend SDK for creating beautiful galleries
npm install playbook-sdkA lightweight frontend SDK for creating masonry grid galleries with search, board navigation, and modal views. Works for asset management, photo galleries, and media libraries.
- Fully responsive - adapts from 2 to 8 columns based on screen size
- Search with AI toggle - regular and semantic search
- Board navigation - organize assets into categories
- Modal viewer - full-screen asset view with keyboard navigation
- Download support - one-click downloads
- Customizable - extensive configuration options
- Framework agnostic - works with vanilla JS, React, Vue, Angular
- Zero dependencies
- TypeScript support
- Accessible - ARIA labels and keyboard navigation
- Lightweight - ~15KB minified
``html
`
`bash`
npm install playbook-sdk
`javascript
import PlaybookSDK from "playbook-sdk";
const gallery = PlaybookSDK.init({
containerId: "my-gallery",
organizationSlug: "your-org-slug",
authToken: "your-auth-token",
});
`
Download playbook-sdk.min.js and include it in your project:
`html`
Request API access at dev.playbook.com or email beta@playbook.com. You'll need:
- Organization Slug (e.g., playbook-sdk)
- Auth Token (OAuth2 bearer token)
- Board ID (optional - to scope gallery to specific board)
`html`
`javascript`
const gallery = PlaybookSDK.init({
containerId: "gallery-container",
organizationSlug: "playbook-sdk", // Your organization/workspace slug
authToken: "your-token-here", // Your API access token
boardId: "", // Optional: Scope gallery to specific board
enableSearch: true,
enableBoards: true,
enableModal: true,
});
The SDK will fetch and display your assets from Playbook.
`javascript
PlaybookSDK.init({
// ===== Required =====
containerId: "my-gallery", // ID of the container element
organizationSlug: "your-org-slug", // Your Playbook workspace slug
authToken: "your-auth-token", // Your API bearer token
// ===== Optional Scoping =====
boardId: "", // Scope to specific board (empty = workspace-wide)
// When boardId is set:
// - "All Assets" shows only assets from this board + nested boards
// - Board navigation shows only children of this board
// - Users cannot navigate outside this board tree
// ===== Features =====
enableSearch: true, // Show search bar with AI toggle
enableBoards: true, // Show board/collection navigation
enableModal: true, // Enable full-screen asset viewer
enableDownload: true, // Show download button in modal
enableInfo: true, // Show info button in modal
// ===== Responsive Columns =====
columnBreakpoints: {
default: 2, // Mobile (< 768px)
768: 3, // Tablet
1024: 4, // Desktop
1280: 5, // Large desktop
1536: 6, // XL screens
1800: 7, // 2XL screens
2000: 8, // Ultra-wide
},
// ===== Styling =====
theme: "light", // 'light' or 'dark' (future)
customStyles: {}, // Custom CSS overrides
// ===== Callbacks =====
onAssetClick: function (asset) {
console.log("Asset clicked:", asset);
},
onSearch: function (query) {
console.log("Search performed:", query);
},
onBoardChange: function (boardId, boardTitle) {
console.log("Board changed:", boardTitle || boardId);
},
onModalOpen: function (asset) {
console.log("Modal opened:", asset);
},
onModalClose: function () {
console.log("Modal closed");
},
onDownload: function (asset) {
console.log("Asset downloaded:", asset);
},
});
`
Workspace-wide gallery:
`javascript`
PlaybookSDK.init({
containerId: "gallery",
organizationSlug: "acme-corp",
authToken: "abc123...",
boardId: "", // Empty = show all workspace assets
});
Board-scoped gallery:
`javascript`
PlaybookSDK.init({
containerId: "gallery",
organizationSlug: "acme-corp",
authToken: "abc123...",
boardId: "SddGjNcAFZThZb3yVTSvbGbe", // Only this board + children
});
`html
Asset Library
`
`javascript
const gallery = PlaybookSDK.init({
containerId: "gallery",
organizationSlug: "my-company",
authToken: "your-token",
onAssetClick: function (asset) {
// Track analytics
gtag("event", "asset_view", {
asset_id: asset.token,
asset_name: asset.title,
});
},
onSearch: function (query) {
// Track search
console.log("User searched for:", query);
},
onBoardChange: function (boardId, boardTitle) {
// Track board navigation
console.log("Navigated to:", boardTitle);
},
onDownload: function (asset) {
// Track downloads
gtag("event", "asset_download", {
asset_id: asset.token,
});
},
});
`
`javascript
PlaybookSDK.init({
containerId: "gallery",
organizationSlug: "my-company",
authToken: "your-token",
// Custom breakpoints for your design
columnBreakpoints: {
default: 1, // 1 column on mobile
640: 2, // 2 columns on small tablets
1024: 3, // 3 columns on desktop
1440: 4, // 4 columns on large screens
},
});
`
`jsx
import { useEffect, useRef } from "react";
import PlaybookSDK from "playbook-sdk";
function GalleryComponent() {
const galleryRef = useRef(null);
const sdkInstance = useRef(null);
useEffect(() => {
if (galleryRef.current && !sdkInstance.current) {
sdkInstance.current = PlaybookSDK.init({
containerId: "react-gallery",
organizationSlug: "your-org-slug",
authToken: "your-auth-token",
onAssetClick: (asset) => {
console.log("Asset clicked:", asset);
},
});
}
return () => {
if (sdkInstance.current) {
PlaybookSDK.destroy("react-gallery");
sdkInstance.current = null;
}
};
}, []);
return
;export default GalleryComponent;
`
TypeScript definitions included:
`typescript
import PlaybookSDK, {
PlaybookConfig,
GalleryInstance,
Asset,
Board,
} from "playbook-sdk";
import { useEffect, useRef } from "react";
function TypeScriptGallery() {
const sdkInstance = useRef
useEffect(() => {
const config: PlaybookConfig = {
containerId: "ts-gallery",
organizationSlug: "your-org-slug",
authToken: "your-auth-token",
enableSearch: true,
enableBoards: true,
onAssetClick: (asset: Asset) => {
console.log("Asset clicked:", asset.title);
},
onBoardChange: (boardId: string, boardTitle: string) => {
console.log("Board changed:", boardTitle);
},
};
sdkInstance.current = PlaybookSDK.init(config);
return () => {
if (sdkInstance.current) {
PlaybookSDK.destroy("ts-gallery");
}
};
}, []);
return
;Public API Methods
Interact with the gallery instance:
`javascript
const gallery = PlaybookSDK.init({
/ config /
});// Refresh the gallery
gallery.refresh();
// Programmatically search
gallery.search("logo");
// Select a specific board
gallery.selectBoardById("brand-assets");
// Get current assets
const assets = gallery.getAssets();
// Destroy the gallery
gallery.destroy();
// Get gallery instance later
const instance = PlaybookSDK.getInstance("my-gallery");
`Styling & Customization
CSS classes are prefixed with
pb- to avoid conflicts:`css
/ Override styles in your CSS /
.pb-masonry-item img {
border-radius: 12px !important;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2) !important;
}.pb-board-btn.active {
background-color: #your-brand-color !important;
}
.pb-modal-content {
border-radius: 20px !important;
}
`Keyboard Shortcuts
Modal controls:
-
← Previous asset
- → Next asset
- Esc` Close modal- Chrome/Edge (latest)
- Firefox (latest)
- Safari (latest)
- Mobile browsers (iOS Safari, Chrome Mobile)
For issues and questions:
- Documentation: Development Portal
- Email: beta@playbook.com
- [ ] Dark theme support
- [ ] Video preview in grid
- [ ] Drag & drop upload
- [ ] Batch download
- [ ] Grid/List view toggle
- [ ] Advanced filtering
- [ ] Asset metadata display
- [ ] Lazy loading optimization