App Association
registerFormGroup() is the call that associates a Form Group definition with the running application. It writes the group into the global Form Group Registry, validates ID range integrity, and makes the group's forms discoverable by Studio and the AI generation pipeline.
registerFormGroup()
import { registerFormGroup } from '@atlas-forms/form-group-registry';
import { guardRailsGroup } from './formGroups/guardRailsGroup';
// Call once at application bootstrap — before any form loading
registerFormGroup(guardRailsGroup);
FormGroupRegistryEntry Type
// The registry stores the definition plus a list of known forms in the group
interface FormGroupRegistryEntry {
definition: FormGroupDefinition;
/** Declared forms — populated by registerFormGroup() calls and by Studio discovery */
forms: FormEntryDescriptor[];
}
interface FormEntryDescriptor {
formId: number;
formCode: string;
formTypeId: number; // 1=List, 2=Property, 3=Wizard, 4=Dashboard
primaryUsage: string;
nodeUsage?: string;
role: 'list' | 'property' | 'wizard' | 'dashboard';
}
Declaring Forms Within the Group
You can pre-declare the forms that belong to a group at registration time. This gives Studio accurate auto-complete and lets the AI pipeline know which FormIDs are already taken:
import { registerFormGroup } from '@atlas-forms/form-group-registry';
registerFormGroup({
...guardRailsGroup,
forms: [
{ formId: 13000, formCode: 'GuardRail_List', formTypeId: 1, primaryUsage: 'guardrails', role: 'list' },
{ formId: 13001, formCode: 'GuardRail_Edit', formTypeId: 2, primaryUsage: 'guardrails', nodeUsage: 'guardrail-edit', role: 'property' },
{ formId: 13002, formCode: 'GuardRail_View', formTypeId: 2, primaryUsage: 'guardrails', nodeUsage: 'guardrail-view', role: 'property' },
{ formId: 13003, formCode: 'GuardRail_RateLimit_Edit', formTypeId: 2, primaryUsage: 'guardrails', nodeUsage: 'guardrail-rate-limit', role: 'property' },
{ formId: 13004, formCode: 'GuardRail_ContentFilter_Edit', formTypeId: 2, primaryUsage: 'guardrails', nodeUsage: 'guardrail-content-filter', role: 'property' },
{ formId: 13005, formCode: 'GuardRail_TopicBlock_Edit', formTypeId: 2, primaryUsage: 'guardrails', nodeUsage: 'guardrail-topic-block', role: 'property' },
{ formId: 13006, formCode: 'GuardRail_AccessControl_Edit', formTypeId: 2, primaryUsage: 'guardrails', nodeUsage: 'guardrail-access-control', role: 'property' },
{ formId: 13007, formCode: 'GuardRail_Audit', formTypeId: 4, primaryUsage: 'guardrails', role: 'dashboard' },
],
});
PrimaryUsage — Tab Routing
The PrimaryUsage value on each form drives tab routing in the host application. The router reads this value and maps the form to the correct navigation tab without any per-form route declaration:
// Router setup — one line per product area tab
const tabMap: Record<string, React.ComponentType> = {
'guardrails': GuardRailsTab,
'node-policies': NodePoliciesTab,
'workdesk': WorkDeskTab,
};
// In the form loader, the tab is resolved automatically:
const tab = tabMap[form.primaryUsage];
// → GuardRailsTab for any form with primaryUsage = 'guardrails'
NodeUsage — Workflow Dispatch
The nodeUsage field lets FlowStudio workflow nodes look up a form by a stable string key rather than a numeric FormID. This decouples workflow definitions from form IDs:
// FlowStudio node configuration (in the workflow schema JSON)
{
"type": "atlas-form",
"config": {
"formLookup": "guardrail-edit" // resolves to FormID 13001
}
}
// Form loader in the node executor
async function loadFormByNodeUsage(nodeUsage: string): Promise<FormSchema> {
const form = await db.query(
'SELECT SchemaJson FROM Atlas_Forms WHERE NodeUsage = @nodeUsage AND IsActive = 1',
{ nodeUsage }
);
return parseSchema(JSON.parse(form.SchemaJson));
}
forms[] list you pass to registerFormGroup() is used by Studio and the AI pipeline at design time. At runtime, the application always loads form schemas from the database — the registry list is not the authoritative source of schemas.