Native Adobe UXP panel integrating Kaltura's enterprise video platform with Adobe Premiere Pro and Photoshop. UXP-only (no CEP/ExtendScript). React 18 + Spectrum Web Components. Minimum versions: Premiere Pro v25.6, Photoshop v25.1.0.
- Runtime: Adobe UXP (Manifest v5) — lightweight JS engine, NOT a browser
- UI: React 18 + Spectrum Web Components (custom elements:
sp-button,sp-textfield, etc.) - API Client: Custom
KalturaClientwith multi-request batching and error normalization - Host API: HostService interface → PremiereHostAdapter, PhotoshopHostService
- Auth: Email/password login + App Token (
appToken.startSession) + SSO (three-party OAuth) - Distribution:
.ccxpackage via installer scripts or Adobe Admin Console
plugin/manifest.json # UXP manifest v5
src/
index.tsx # UXP entrypoints.setup() — registers 2 panels + 2 commands
panels/ # Panel root components + inner panels
BrowsePanelRoot.tsx # Media Browser panel entry (AuthGate → BrowseContent)
PublishPanelRoot.tsx # Publish panel entry (AuthGate → PublishContent)
BrowsePanel.tsx # Asset browser: search, filters, grid/list, detail flyout
PublishPanel.tsx # Export + upload workflow
LoginPanel.tsx # Email/password + SSO login (rendered by AuthGate)
SettingsPanel.tsx # Preferences, cache, about (rendered by SettingsCommand)
commands/ # Command entrypoints (no React — vanilla JS + UXP dialogs)
SettingsCommand.ts # Opens settings modal via uxpShowModal()
SignOutCommand.ts # Clears session + dispatches kaltura:signout event
components/ # Shared UI components (incl. ErrorBoundary, AuthGate)
AuthGate.tsx # Auth wrapper: inline login per panel, cross-panel sync
services/ # Service modules
singleton.ts # Shared singleton instances (all panels/commands share these)
KalturaClient.ts # Low-level HTTP: single/multi-request, KS injection, HTTPS validation
AuthService.ts # Login, session persistence, auto-refresh
MediaService.ts # CRUD, eSearch, batched detail fetching, download URLs
UploadService.ts # Chunked resumable uploads (5 MB chunks, XHR for progress)
DownloadService.ts # Download + import with progress tracking
MetadataService.ts # Metadata, tags, categories, custom schemas
CaptionService.ts # REACH captioning/translation, JSON/SRT/VTT parsing, serveAsJson transcript
SearchService.ts # eSearch-powered transcript/visual/in-video search
PublishWorkflowService.ts # Multi-destination, approval, versioning, scheduling
BatchService.ts # Multi-request batch ops, offline cache, governance
PremiereService.ts # UXP API: sequence, import, markers, transcript attach, export
AuditService.ts # Audit trail, access control, DRM, license expiry
OfflineService.ts # LRU cache, operation queue, offline/online detection
HostService.ts # Host app abstraction interface
PhotoshopHostService.ts # Document open, image import
HostServiceFactory.ts # Auto-detect host app and create service
i18n/ # Internationalization (20 languages)
index.ts # i18n system: locale detection, translate(), React context + useTranslation()
loadLocales.ts # Eagerly registers all locale bundles at startup
locales/ # Translation JSON files (en + 19 languages)
hooks/ # 3 custom React hooks (useAuth, useDebounce, useContainerWidth)
types/ # TypeScript type definitions
utils/ # Constants, error classes, formatters, logger, thumbnail URLs
settings.ts # Shared settings load/save utilities
tests/ # Jest unit tests (mirrors src/ structure)
scripts/ # Build, package, and dev scripts
docs/ # Documentation
- Strict mode enabled (
strict: truein tsconfig) - No
anytypes except at API boundaries with explicit// eslint-disable-next-line - Prefer
interfaceovertypefor object shapes - Export types from
src/types/— co-locate only when truly private
- Functional components only (except ErrorBoundary which must be a class)
- Custom hooks for shared logic; prefix with
use - Memoize expensive computations with
useMemo/useCallback - Props interfaces named
{ComponentName}Props
- No CSS Grid — use Flexbox only
- No
windowglobal — use UXP equivalents - No
@font-face— use system fonts only - No
TextEncoder/TextDecoder— use manualcharCodeAtfor string-to-bytes - No
data-*attribute CSS selectors - No Node.js APIs — no
fs,path,cryptofrom Node; use UXPuxp.storage - No
floatCSS — Flexbox only FormData+Blobunreliable for binary uploads — build multipart bodies manuallyfs.readFile(path)without encoding returnsArrayBuffer— never pass{ encoding: "buffer" }fetch()is available butXMLHttpRequestneeded for upload progress trackingWebSocketis available in UXP runtime- Spectrum Web Components are custom HTML elements, typed in
src/types/spectrum.d.ts - SWC
preCreateCallbackassertion — defer view transitions withsetTimeout(0)to avoid crash - Uncaught exceptions crash Premiere — ErrorBoundary at app root is mandatory
- See
docs/UXP_LESSONS_LEARNED.mdfor comprehensive patterns and workarounds
- Always use multi-request batching when making 2+ related API calls
- Thumbnail URLs constructed client-side (no API call)
- KS (Kaltura Session) stored in
SecureStorage, never inlocalStorage - Error responses: check
objectType === 'KalturaAPIException'on every response - Client tag:
kaltura-premiere-panel:v{version}
- Jest + jsdom for unit tests;
tests/mirrorssrc/directory structure - Mock
premiereproanduxpmodules globally intests/setup.ts(photoshopis NOT mocked — host service tests unavailable state) - Mock
fetchglobally — never hit live API in CI - 488 tests across 40 suites — all passing
- Panel tests use duck-typed service mocks and React Testing Library
- Use
renderHook+actfor hook tests;jest.useFakeTimers()for debounce tests - Coverage thresholds enforced (
jest.config.js): statements 65%, branches 50%, functions 64%, lines 66%
- ESLint + Prettier enforced via pre-commit hooks and CI
- No
console.login production code — usecreateLogger()utility - All async operations must have error handling
- Secrets: NEVER commit
KALTURA_ADMIN_SECRETor any API secrets
npm run dev— development build with watch modenpm run build— production buildnpm test— run all testsnpm run lint— ESLint checknpm run typecheck— TypeScript type checkingnpm run package— build + verify + Exchange metadata for .ccx distribution
Services are module-level singletons in src/services/singleton.ts. All panels and commands
import from this module, so login from any panel authenticates every panel.
KalturaClient→ base HTTP client (partner ID updated on login)AuthService,MediaService,UploadService,MetadataService→ core CRUDDownloadService,CaptionService,SearchService→ import/searchPublishWorkflowService,BatchService→ publish/batchAuditService→ governance audit trail, access control, DRM, complianceOfflineService→ offline caching and operation queuecreateHostService()→ auto-detects host app, returns PremiereHostAdapter | PhotoshopHostService
Not directly instantiated (used internally):
PremiereService→ wrapped byPremiereHostAdapterinside factory
Multi-panel + command architecture (UXP Manifest v5 entrypoints):
- Media Browser (panel) —
BrowsePanelRoot→AuthGate→BrowsePanel - Publish (panel) —
PublishPanelRoot→AuthGate→PublishPanel - Settings (command) —
SettingsCommand→uxpShowModal()dialog (no auth needed) - Sign Out (command) —
SignOutCommand→ clears session, dispatcheskaltura:signout
Cross-panel auth sync uses DOM events (kaltura:signin, kaltura:signout) since panels
share the same document context but have separate React trees. AuthGate wraps each panel
with inline login UI and listens for these events via useAuth.
Panels use duck-typed service interfaces for loose coupling. All panels follow:
- No
entryId→<EmptyState>with guidance - Loading →
<LoadingSpinner>with descriptive label - Error →
<ErrorBanner>with dismiss/retry - Loaded → tabbed sub-views with data display and action forms
Version must be updated in 3 files when bumping:
package.json→"version"plugin/manifest.json→"version"src/utils/constants.ts→PLUGIN_VERSION