Summary
CollectionAdminConfig and SingletonAdminConfig identify their target collection with a field named slug, while the thing it holds is a collection's path. defineAdmin() literally assigns slug: schema.path. The two names should agree, and path is the right one — slug names nothing that exists elsewhere in the model.
// packages/core/src/@types/admin-types.ts
export function defineAdmin<T = any>(
schema: MultiCollectionDefinition,
config: Omit<CollectionAdminConfig<T>, 'slug' | 'singleton'>
): CollectionAdminConfig<T> {
return { ...config, singleton: false, slug: schema.path }
}
validate-admin-configs.ts:170 already documents the rule in terms that give the game away:
1. Slug pairing — admin.slug matches exactly one collection.path.
Why it is worth fixing rather than tolerating
This is not only cosmetic. It caused a silent failure in the 6.0 pre-upgrade capability scan, a tool whose entire job is to warn before content breaks.
apps/webapp/src/lib/richtext-capability-targets.ts resolved a field's editor with:
const adminForCollection = (config.admin ?? []).find(
(entry: any) => entry.path === collection.path // always undefined === '<path>'
)
Every collection-level field override therefore fell through to the globally registered editor, and the generated manifest overstated what those fields accept — the dangerous direction. Measured against www.forru.org: eleven fields reported 26 node types where their minimal and compact editors register 8 to 10, and the scan reported zero findings where a correct manifest reports four.
Two things kept it invisible:
- The
(entry: any) cast meant .path on a type with no path was not a compile error.
- The unit test did cover the collection branch and passed, because its fixture was hand-written as
path: 'pages' — invented to match the implementation rather than what defineAdmin() returns.
Block-level overrides were unaffected (they resolve through blockType, a key that exists), which is why it survived: the reference app's only narrowed fields sit inside blocks, so the collection branch was never exercised by real config.
Fixed in d1511472 (reference app) and ported downstream, but the underlying naming mismatch remains.
Scope of the rename
Small, and contained to @byline/core.
Nobody writes it. slug is Omitted from what callers pass to defineAdmin() / defineSingletonAdmin(); both derive it from schema.path. No downstream application sets it.
Almost nobody reads it — 12 sites, all in this repo:
| Location |
Reads |
Notes |
packages/core/src/config/validate-admin-configs.ts |
8 |
mostly error-message text |
packages/core/src/config/config.ts |
1 |
getCollectionAdminConfig lookup |
packages/core/src/config/group-collections.ts |
1 |
|
apps/webapp/src/lib/richtext-capability-targets.ts |
1 |
the one above |
Checked across all three known downstream applications (modulus-learning.org, www.forru.org, bylinecms.app): zero admin-config slug references. Every slug occurrence in those repos is an unrelated content/URL slug.
Compatibility
Renaming a field on an exported type is nominally breaking for anyone who built an admin config as an object literal instead of calling defineAdmin(). No known consumer does. Confirmed acceptable as a non-major on that basis, since there are no other downstream applications we are aware of.
Suggested change
- Rename
slug to path on CollectionAdminConfig and SingletonAdminConfig.
- Update
defineAdmin / defineSingletonAdmin to assign path: schema.path, and their Omit<…, 'slug' | 'singleton'> signatures.
- Update the ~10 read sites, including the error strings, which currently say "Admin resource" and "Slug pairing".
- Update
apps/webapp/src/lib/richtext-capability-targets.ts and the copy in www.forru.org when it takes the release.
- Keep the typed parameter rather than restoring
(entry: any) — that annotation is what turns this class of mistake into a compile error.
Summary
CollectionAdminConfigandSingletonAdminConfigidentify their target collection with a field namedslug, while the thing it holds is a collection'spath.defineAdmin()literally assignsslug: schema.path. The two names should agree, andpathis the right one —slugnames nothing that exists elsewhere in the model.validate-admin-configs.ts:170already documents the rule in terms that give the game away:Why it is worth fixing rather than tolerating
This is not only cosmetic. It caused a silent failure in the 6.0 pre-upgrade capability scan, a tool whose entire job is to warn before content breaks.
apps/webapp/src/lib/richtext-capability-targets.tsresolved a field's editor with:Every collection-level field override therefore fell through to the globally registered editor, and the generated manifest overstated what those fields accept — the dangerous direction. Measured against www.forru.org: eleven fields reported 26 node types where their minimal and compact editors register 8 to 10, and the scan reported zero findings where a correct manifest reports four.
Two things kept it invisible:
(entry: any)cast meant.pathon a type with nopathwas not a compile error.path: 'pages'— invented to match the implementation rather than whatdefineAdmin()returns.Block-level overrides were unaffected (they resolve through
blockType, a key that exists), which is why it survived: the reference app's only narrowed fields sit inside blocks, so the collection branch was never exercised by real config.Fixed in
d1511472(reference app) and ported downstream, but the underlying naming mismatch remains.Scope of the rename
Small, and contained to
@byline/core.Nobody writes it.
slugisOmitted from what callers pass todefineAdmin()/defineSingletonAdmin(); both derive it fromschema.path. No downstream application sets it.Almost nobody reads it — 12 sites, all in this repo:
packages/core/src/config/validate-admin-configs.tspackages/core/src/config/config.tsgetCollectionAdminConfiglookuppackages/core/src/config/group-collections.tsapps/webapp/src/lib/richtext-capability-targets.tsChecked across all three known downstream applications (modulus-learning.org, www.forru.org, bylinecms.app): zero admin-config
slugreferences. Everyslugoccurrence in those repos is an unrelated content/URL slug.Compatibility
Renaming a field on an exported type is nominally breaking for anyone who built an admin config as an object literal instead of calling
defineAdmin(). No known consumer does. Confirmed acceptable as a non-major on that basis, since there are no other downstream applications we are aware of.Suggested change
slugtopathonCollectionAdminConfigandSingletonAdminConfig.defineAdmin/defineSingletonAdminto assignpath: schema.path, and theirOmit<…, 'slug' | 'singleton'>signatures.apps/webapp/src/lib/richtext-capability-targets.tsand the copy in www.forru.org when it takes the release.(entry: any)— that annotation is what turns this class of mistake into a compile error.