v4.1.0
Byline 4.1 is a developer-experience release focused on how applications consume Byline's typed surface. The app-local plumbing that every project previously carried — a clients.server.ts type-assertion shim and path-based imports into the generated types file — is replaced by two package imports: request-bound client getters from @byline/client/server and collection types from the new @byline/generated-types declaration-merge target. Under the hood, the entire server-side client stack moved out of the TanStack Start adapter and into the framework-neutral client SDK, behind a new three-function HostRequestBridge seam — so application read/write modules no longer import the host framework at all.
📖 Migration guide: Upgrading from 3.21 to 4.x now lands 3.21 applications directly on the 4.1 import surface (steps 5–6). Apps already on 4.0 need only the short list under Migrations below.
Highlights
-
@byline/client— a new server-only subpath,@byline/client/server, exports the four request-authority client singletons (getAdminBylineClient,getPublicBylineClient,getSystemBylineClient,getViewerBylineClient) plusisPreviewActiveandgetAdminRequestContext. In an app whose generated types are registered (see below), every getter returns a fully typedBylineClient—client.collection('news')autocompletes collection paths and returns the generated field shapes with no explicit generics and no type assertions. The subpath ships abrowserexport condition that resolves to a throwing stub, so an accidental import from client-side code fails loudly at bundle time instead of leaking session machinery to the browser. -
@byline/client— the SDK now exposes aRegisterinterface (the TanStack Router / Payload declaration-merge pattern). The app's generated types register theirCollectionFieldsByPathon it, after which every bareBylineClientin the app's program — includingcreateBylineClientwithout an explicit generic — resolves to the app's typed registry. Unaugmented programs fall back to the looseCollectionRegistry, so packages, scripts, and tests compiled outside the app keep working unchanged. -
@byline/generated-types— a new, deliberately empty package that acts as the declaration-merge target for each application's generated collection types. Apps import their own schema-derived types by package name —import type { NewsFields } from '@byline/generated-types'— from anywhere in the program. Imports are type-only and erased at runtime; the app's tsconfigincludecarrying the generated file is what populates the module. Exactly one application per TypeScript program can augment it (one app per tsconfig — the supported layout — is safe). -
@byline/core/@byline/host-tanstack-start— everything request-scoped in the server client stack (per-request memoization, session cookies with the transparent refresh dance, preview cookies) now bottoms out in a newHostRequestBridgeseam in core: three functions — request identity, cookie read, cookie write — that a host adapter implements and registers at server boot (registerTanstackStartHostBridge()from@byline/host-tanstack-start/integrations/host-bridge). The whole client/preview/session stack is implemented once against the bridge in@byline/client/server, which is what makes a future non-TanStack host adapter cheap: implement three functions and the entire stack comes for free. The host adapter shrank accordingly to bridge + server fns + route factories + admin shell. -
@byline/core— the codegen emitter moved to format 2: every generated type is declared inside the@byline/generated-typesaugmentation block (making the package the single canonical import path), and a second block registers the collection registry with@byline/client'sRegisterinterface viaimport('@byline/generated-types').CollectionFieldsByPath.
Chores
@byline/cli— templates (minimal and examples sets) migrated to the new import surface, template generated types regenerated to format 2, and@byline/generated-typesadded to the installer's dependency manifest. Template scripts dropped their explicitcreateBylineClientgenerics — theRegistermerge covers them.@byline/cli— repaired a latent CI failure: a workspace-link test fixture pinned@byline/coreat a literal3.21.4, which the version-derived release policy (correctly) rejected once 4.0 shipped; the fixture now tracksCLI_PACKAGE_VERSIONso it can never drift again. The ts-morph-heavy template-contract and scaffold suites also gained CI-runner timeout headroom.@byline/host-tanstack-start— dropped the now-unuseduuiddependency (its only consumer moved to@byline/client).- monorepo — the webapp's
regenerate-mediascript was refactored into a tested, status-preserving operation module (also mirrored into the CLI's example templates).
Migrations
- monorepo — to adopt the new surface in an existing 4.0 app: add
@byline/generated-typesto dependencies; regenerate collection types (pnpm byline:generate— output moves to format 2); respell~/clients.serverimports to@byline/client/serverand~/generated/collection-types.jsimports to@byline/generated-types; addregisterTanstackStartHostBridge()tobyline/server.config.tsbeforeinitBylineCore(); then deletebyline/clients.server.ts. Regeneration is the opt-in moment — an un-regenerated 4.0 app compiles and runs unchanged against 4.1 packages except for the removed host modules listed under Breaking Changes.
Breaking Changes
@byline/host-tanstack-start— the modules that moved to@byline/client/serverwere removed without a deprecation cycle (coordinated with all known 4.0 consumers): the./auth/*subpath (auth-context,auth-cookies,preview-cookies,request-scope) and theintegrations/byline-client,integrations/byline-public-client, andintegrations/byline-viewer-clientmodules. Required action: import the same symbols from@byline/client/server— every export kept its name and behaviour.
All other @byline/* packages bumped to 4.1.0 in lockstep with no behavioural changes this cycle.