v3.0.0
Highlights
-
@byline/core,@byline/db-postgres,@byline/i18n— Content-locale resolution. Document reads now resolve a requested content locale against a per-document fallback chain instead of assuming every value exists in every locale. A new version-grain completeness ledger (byline_document_version_locales) records which locales each version was actually authored in, surfaced on read results as_availableVersionLocales. A newonMissingLocaleread switch ('empty' | 'fallback' | 'omit') controls what happens when a requested locale is absent — return empties, fall back to the document's source locale, or omit the field entirely. -
@byline/core,@byline/db-postgres,@byline/admin,@byline/host-tanstack-start— Editorial available-locales advertising. A first-classadvertiseLocales: truecollection directive replaces the old hand-rolledavailableLanguagesFieldpattern. Editors choose which locales a document advertises via a new admin sidebar widget; the set persists to a document-grainbyline_document_available_localestable and is surfaced on reads asavailableLocales(with the publicly-safe advertised set beingavailableLocales ∩ _availableVersionLocales). Wired end-to-end through the admin write path and the client read path. -
@byline/core,@byline/db-postgres,@byline/admin— Switchable default content locale. Each document now carries its ownsource_localeanchor, so the site-wide default content locale can be changed safely without rewriting existing data — documents keep reading in the locale they were authored in. Includes a boot-time backfill that stampssource_localeon pre-existing rows, a bulkre-anchorcommand for moving fully-translated documents onto a new default, and a source-locale badge next to the document title in the editor.
Bug Fixes
@byline/i18n,@byline/core— Admin reads now show raw per-locale values rather than fallback-resolved ones, so editors see exactly what exists in each locale. The read-resolution switch was renamed toonMissingLocaleas part of this correction.- monorepo — Fixed the admin dashboard intermittently rendering "Byline has not been configured" by registering the Byline client config before the admin route loaders run.
Chores
@byline/db-postgres— Squashed the migration set to a single 3.0 baseline for fresh installs (supersedes0000–0004), with a standalone, idempotentsql/upgrade-2.7.0-to-3.0.sqldelta script for existing installs.@byline/cli— Brought templates and the init migration to 3.0, and migratedimport-docsfromavailableLanguagestoadvertiseLocales.
Migrations
@byline/db-postgres— Existing installs: apply the schema delta withpsql "$DATABASE_URL" -f packages/db-postgres/sql/upgrade-2.7.0-to-3.0.sql(equivalent to migrations0001→0004; transactional and re-runnable). Do not rundrizzle:migrateagainst an upgraded DB — after the squash its journal points at superseded hashes. Fresh installs run the squashed baseline viadrizzle:migrate.- monorepo — Required data backfill: run
cd apps/webapp && pnpm tsx byline/scripts/backfill-version-locales.tsto populate the version-locale ledger for pre-existing documents (without it,onMissingLocale: 'omit'reads can't see old docs and_availableVersionLocalesis empty on old versions). Thesource_localebackfill is automatic —initBylineCore()stamps NULL rows on boot, so deploying the 3.0 server is the backfill. Full per-site guide indocs/MIGRATION-TO-3.0.md.
Breaking Changes
@byline/client,@byline/core— breaking: theClientDocumentread surface renamed_availableLocales→_availableVersionLocales(the structural ledger fact), and added the editorialavailableLocalesand_localeAgnostic. Any frontend reading_availableLocales(e.g. hreflang / "also available in…" UI) must move to the new fields.@byline/core— breaking:availableLocalesis now a reserved field name — a collection can no longer declare a user field by that name. The deprecatedavailableLanguagesField()pattern is retired; collections using it must remove the field and its import and addadvertiseLocales: trueto the collection definition.@byline/core— breaking (semantics):i18n.content.defaultLocaleis no longer the data anchor — it now means "default authoring locale + request fallback," with each document riding its ownsource_locale. No code change required, but switching it now affects new authoring/fallback behaviour rather than rewriting existing data.
All other @byline/* packages bumped to 3.0.0 in lockstep with no behavioural changes this cycle.