Hi Roel,
Great question and a very common pain point when migrating from KX13 to XbK. You've correctly identified that the Content Hub's reusability-first design conflicts with ownership semantics. Here's how I'd approach it:
The core problem The Content Hub has no native concept of ownership — items can be referenced by many parents, so cascade deletion isn't built in by design. What you need isn't a reference relationship, it's an ownership relationship.
Option 1 — Custom module table (recommended for your use case) Keep EducationContent as a Content Hub item, but store EducationStartdateContent as a custom module class instead of a Content Hub item:
Add a ParentContentItemID column (FK to CMS_ContentItem) with ON DELETE CASCADE at the DB level — this gives you automatic cascade delete
Build a custom admin UI section scoped to the parent, so child records are never visible as standalone items in the Content Hub
Optionally inject the child management UI into the parent's edit form via a custom form component
This satisfies all your requirements: children cannot exist without a parent, deleting the parent cascades automatically, and ghost records are impossible.
Option 2 — Pages (when channel binding is acceptable) If the education content is always tied to one channel and reusability across channels isn't needed, the page tree remains a valid choice. XbK pages still support the parent-child tree structure you know from KX13, with cascade delete built in. You lose Content Hub benefits, but for channel-specific content this is often the cleanest solution with zero custom code.
Option 3 — Soft enforcement via application logic If you want to stay entirely within the Content Hub but avoid the custom module overhead, you can implement a softer ownership pattern in application code:
Use a dedicated IsStandalone boolean field on EducationStartdateContent — set to false when created via a parent selector, preventing it from being independently published or selected elsewhere
Hook into ContentItemInfo.TYPEINFO.Events.Delete on the parent to explicitly delete all referenced child items in the same transaction
Restrict the child content type from appearing in global Content Hub listings via a custom admin UI filter or a scoped ContentItemSelector that only surfaces these items in the context of their parent
This avoids ghost records through convention and code rather than DB constraints. It's more fragile than Option 1 but requires no schema changes outside the Content Hub.
On your ContentItemSelector idea Your instinct is sound. A ParentID-aware selector that hides child-bound items from the Content Hub would be a valuable addition. I'd pair it with an event handler on ContentItemInfo.TYPEINFO.Events.Delete as a safety net for reference-based relationships where you don't control DB-level cascades.
Bottom line: For strict ownership with no independent child meaning, go with Option 1 (custom module). Option 2 is the zero-code path if channel binding is acceptable. Option 3 is a middle ground if you need to stay within Content Hub conventions but can accept application-level enforcement over database-level guarantees.