Atlas Forms
Registering a Custom Player
Once you have built a custom player component, you register it with the global PlayerRegistry using registerFormPlayer(). Registration makes the player discoverable in Atlas Forms Studio's player selection dropdown and allows it to be referenced by ID in form schemas.
PlayerRegistryEntry Type
// packages/player-registry/src/types.ts
interface PlayerRegistryEntry {
/** Unique identifier — used in schema metadata.playerOverride */
id: string;
/** Human-readable name shown in Atlas Forms Studio */
label: string;
/** Optional description shown in the Studio player picker tooltip */
description?: string;
/** The React component that renders the form */
component: React.ComponentType<FormPlayerProps>;
/** Optional thumbnail URL shown in Studio's visual player picker */
thumbnail?: string;
}
interface FormPlayerProps {
schema: FormSchema;
initialValues?: Record<string, any>;
mode?: FormMode;
onSubmit?: (values: Record<string, any>) => Promise<void>;
onCancel?: () => void;
}
registerFormPlayer()
import { registerFormPlayer } from '@atlas-forms/player-registry';
import { CardSectionPlayer } from './players/CardSectionPlayer';
registerFormPlayer({
id: 'card-section',
label: 'Card Section Player',
description: 'Renders each form section inside its own card panel. Best for admin consoles and multi-section data entry.',
component: CardSectionPlayer,
thumbnail: '/assets/players/card-section-thumb.png',
});
Registration Timing
Call registerFormPlayer() once, early in your application bootstrap — before any form renders. The registry is a singleton; subsequent calls with the same id overwrite the previous entry and log a warning.
// src/index.tsx — application entry point
import React from 'react';
import { createRoot } from 'react-dom/client';
import { App } from './App';
// Register all custom players before mounting
import './players/registerPlayers'; // side-effect import
const root = createRoot(document.getElementById('root')!);
root.render(<App />);
// ─── src/players/registerPlayers.ts ─────────────────────────────────────────
import { registerFormPlayer } from '@atlas-forms/player-registry';
import { CardSectionPlayer } from './CardSectionPlayer';
import { MobilePlayer } from './MobilePlayer';
import { WizardPlayer } from './WizardPlayer';
registerFormPlayer({
id: 'card-section',
label: 'Card Section',
component: CardSectionPlayer,
});
registerFormPlayer({
id: 'mobile',
label: 'Mobile',
component: MobilePlayer,
});
registerFormPlayer({
id: 'wizard',
label: 'Step Wizard',
component: WizardPlayer,
});
Reading the Registry
import { getFormPlayer, listFormPlayers } from '@atlas-forms/player-registry';
// Retrieve a single entry by ID
const entry = getFormPlayer('card-section');
// Returns: PlayerRegistryEntry | undefined
// List all registered players (e.g. to populate a UI dropdown)
const allPlayers = listFormPlayers();
// Returns: PlayerRegistryEntry[]
// Example: build a select element from all registered players
const options = listFormPlayers().map(p => ({
value: p.id,
label: p.label,
}));
How FormRenderer Resolves the Player
When FormRenderer receives a schema that contains metadata.playerOverride, it looks up that ID in the registry and mounts the registered component instead of the default layout:
// Simplified FormRenderer resolution logic
import { getFormPlayer } from '@atlas-forms/player-registry';
function resolvePlayer(schema: FormSchema): React.ComponentType<FormPlayerProps> {
const overrideId = schema.metadata?.playerOverride;
if (overrideId) {
const entry = getFormPlayer(overrideId);
if (entry) return entry.component;
console.warn(`[AtlasForms] Player "${overrideId}" is not registered. Falling back to default.`);
}
return DefaultFormLayout; // built-in player
}
Registration Is Required Before Schema Loading
If a form schema references a
playerOverride ID that has not been registered yet, FormRenderer will fall back to the default player and log a warning. Ensure all custom player registrations run before any form schema is loaded or rendered.
Player IDs — Naming Convention
| Scope | Convention | Example |
|---|---|---|
| Built-in players | Single word, lowercase | default, mobile, wizard |
| Product-specific | product-name | crm-detail, hr-onboarding |
| Tenant-specific | tenant-name | acme-branded, gov-accessible |
| Experimental | exp-name prefix | exp-canvas |
Unregistering a Player
import { unregisterFormPlayer } from '@atlas-forms/player-registry';
// Remove a player — useful in test teardown or hot-reload scenarios
unregisterFormPlayer('card-section');
Studio Integration
Registered players appear in the Player dropdown in Atlas Forms Studio's Form Settings panel. The
label string is what users see; the id is written into metadata.playerOverride when the user selects it. If you provide a thumbnail, Studio will show it in the visual card picker.