v0.0.2-alpha.57
Pre-releaseReleased 19 packages at 0.0.2-alpha.57 in lockstep. Every package below ships at this version.
What's changed
Patch Changes
-
#714
5673fffThanks @mobeenabdullah! - The admin now ships with rounded corners and the Geist typeface. Corner radius comes from a single--radiusknob, so changing that one declaration re-rounds the whole panel, and a plugin built against the published Tailwind preset re-rounds with it. -
#699
6936078Thanks @mobeenabdullah! - Add an experimental BreakpointDialog to @nextlyhq/ui, with the validation behind it. The style compiler discards a breakpoint it cannot use rather than raising, so a bad definition is lost silently and surfaces later as stale styles; the dialog refuses to save any set that would lose one. -
#728
38e5e6bThanks @mobeenabdullah! - move the breakpoint editor into the builder, where its rules can be derivedlib/breakpoints.tsandbreakpoint-dialog.tsxrestated the style compiler's
breakpoint drop rules because@nextlyhq/uiis the block-agnostic layer and
cannot depend on@nextlyhq/blocks-engine. Two implementations of one rule
agree the day they are written and drift silently after.They now live in
@nextlyhq/builder, which already depends on the engine and
importsMAX_BREAKPOINTS_PER_AXISand the breakpoint types from it rather than
mirroring them.Breaking, and deliberate: the
@nextlyhq/ui/breakpointssubpath is removed,
along withBreakpointDialogand the breakpoint types from the root barrel.
Nothing in this repository imported them, and every affected export was
@experimental. -
#683
5bfac2fThanks @mobeenabdullah! - Add the builder's host-canvas coordinate mapping: one module converts between the canvas frame and the host page, including the scaled border inset that places the frame's content origin. A sibling test scans for cross-frame rectangle reads elsewhere in the package, recognising a bounded set of spellings; it narrows the paths taken by accident rather than enforcing single ownership. -
#717
5a05e7bThanks @mobeenabdullah! - Add an experimental ColorPicker to @nextlyhq/ui, with the pointer-to-colour geometry behind it on the server-safe @nextlyhq/ui/color entry. The picker knows nothing about design tokens: a swatch carries an opaque value it hands back untouched, so a host storing a token reference keeps it rather than receiving the colour that token happened to resolve to. -
#713
dbd95b3Thanks @mobeenabdullah! - Erase a recipient from the email delivery log.Deleting a user left their delivery rows behind carrying a keyed hash of their
address, which an install holds the key for, so the table went on answering
"was this person written to, and when" for an account that no longer exists.
eraseRecipientDeliveriesoverwrites that hash with a value no address can
produce, keeping the row, its status and its timing so aggregate questions
still have an answer.deleteUsercalls it inside its existing transaction, so
a failed erasure takes the deletion with it rather than leaving the two out of
step.The erasure takes an ADDRESS rather than a user id, because most recipients
never had an account: a password reset to an address that never registered, a
CC, a BCC added by abeforeSendfilter. Those people can ask to be erased too
and no account deletion will ever fire for them, so it is callable directly.EmailDeliveryRecord.recipientHashis nowstring | null, where null means
erased. -
#734
193d5ecThanks @mobeenabdullah! - Advertise the Node range this project actually supports. Every package declared
>=20.0.0while the repository requires^20.19.0 || ^22.12.0 || >=24.0.0, so
installs on 20.6-20.18 or on 23.x succeeded without warning and failed later at
runtime. Release preflight now derives the expected range from the root manifest
and rejects a package that disagrees, so the two cannot drift apart again. -
#722
696281dThanks @mobeenabdullah! - Field group instances now report their stored type throughnextly/field-group-type, a new entry point that reads whichever spelling a document carries and writes the current one. The admin editor uses it, so content saved before and after the storage rename stays readable and selectable in both. -
#700
cf04a67Thanks @mobeenabdullah! - Correct the frame content origin to include the iframe's padding, and measure that inset in one place.An iframe's nested viewport begins at the content box, so padding displaces it exactly as a border does. Callers built the inset from
clientLeft/clientTop, which report the border alone, so every frame-local point mapped toward the border by the scaled padding.frameInsetOfis now exported as the single reader, and both the README recipe and theFrameGeometrydocumentation name it instead of restating arithmetic three call sites had already got wrong. -
#689
213a860Thanks @mobeenabdullah! - Admin list pages now attach their pagination to the table it belongs to, instead of leaving it floating a row below the table on some pages and attached on others. Applies to users, plugins, roles and webhook endpoints. -
#725
73885c6Thanks @mobeenabdullah! - The field-group storage migration can now report what it would rename without changing any content or recording that a run happened, and refuses to run for real unless the caller states that a restorable backup exists. A preview still claims the migration lock, so it needs a role that can write to Nextly's own lock table. -
#719
f61172eThanks @mobeenabdullah! - A stylesheet stored for a page is no longer reused when a block migration has
since turned one of its nodes into one that renders nothing. The rules compiled
for that node, and any image the rules fetched, were still being served for
markup no visitor receives. -
#730
6683ef3Thanks @mobeenabdullah! - Plugin icons now resolve through one shared rule, so the same plugin shows the same icon everywhere in the admin, and a plugin can ship its own logo image instead of naming a built-in glyph.The SEO plugin now describes itself in the plugins list instead of showing a bare package name.
A styling fixture used only by the end-to-end suite no longer appears as an installed plugin, and no longer injects a showcase section into the Posts collection list, in a normal development server.
-
#740
db7122dThanks @mobeenabdullah! -@nextlyhq/plugin-sdknow exportspluginAdminSlug,PLUGIN_CATEGORIESandisPluginCategory(experimental), so a plugin author can derive a plugin's admin slug and check a category against the vocabularydefinePluginaccepts, rather than reimplementing either. They are also onnextlyandnextly/configfor host apps.The admin uses those exports instead of its own copies. It previously derived a plugin's URL slug with its own implementation of core's algorithm, so a plugin page could be linked at one slug and routed at another the moment either side changed, and it kept its own list of valid categories, so it could reject a category
definePluginaccepts.Nothing changes in the admin UI. The plugin directory that consumes these is not built yet; this is the groundwork it needs.
-
#727
53fca3eThanks @mobeenabdullah! - On desktop, the Plugins item in the admin sidebar now opens the plugins page when you click it, instead of only expanding the sub-sidebar and leaving you to find the page yourself. On mobile it still opens the panel, as every sidebar section with a panel does, and Installed Plugins is the first entry inside it. The item also stays visible when no plugins are installed, so a new project can reach the plugins page at all.Users who can read a plugin's collections but cannot manage settings keep the sub-sidebar, since the plugins page itself is settings-guarded.
The secondary sidebar now closes when the category it is showing stops being one of the sidebar's destinations, so a slow or failing permissions load no longer leaves an empty panel open beside the page.
-
#671
75054a8Thanks @mobeenabdullah! - Relationship expansion can now be told WHICH collections a trusted read may
reach, judged per expansion target.overrideAccesssays the caller is trusted. It said nothing about the
collection a relationship points at — which the caller never named and may not
serve to the same audience — so a trusted read spread that trust into every
target it populated. A caller serving one fixed audience can now state its
trusted set, and anything outside it is read as that audience would read it.Absent the new option nothing changes, so the Direct API keeps its semantics: a
caller that has already decided who is asking is not narrowed by a default it
never chose. -
#724
35ff30aThanks @mobeenabdullah! - A page whose stylesheet is reused now keeps it when a block migration turns a
condition-gated node into one that renders nothing. Those nodes never had rules
in the shared sheet, so withholding it cost every other block on the page its
styling. -
#673
67082d1Thanks @mobeenabdullah! - Check the built server-safe entry points against what the build recorded, and stop publishing the
bundler metafiles those checks read.The gate reads two records the build already wrote — the module specifiers surviving in each
artifact and every chunk reachable from it, and the bundler's own metafile of what it inlined. A
bundled dependency leaves no import to find, so the text alone cannot answer what an artifact
reaches. The metafiles are build inputs to that check rather than something a consumer needs, so
they are excluded from the published files. -
#702
8011731Thanks @mobeenabdullah! - fix(ui): ignore a dispatched event that is not a keystrokeThe shortcut manager listens on
document, so every event dispatched anywhere on
the page reaches it — including synthetic ones from code outside the application.
A password manager typing into a credential field dispatches akeydowncarrying
nokey, and the manager spread it as a string, crashing the page with
TypeError: key is not iterable. It now ignores an event it cannot read as a
keystroke, and leaves it propagating to whichever listener does understand it. -
#697
ca1cc48Thanks @mobeenabdullah! - Carry a trusted write's bound into a Single's upload expansion. A Single holding uploads and no relationship field returned whole media rows in its write response, because the bound reached only the relationship expansion beside it, which returns early for such a document. -
#705
ecefaa2Thanks @mobeenabdullah! - A field group instance now reports its type whichever spelling the stored document uses, so content written before and after the storage rename both read. Awherefilter on the type keeps working under either spelling, and version snapshots keep recording the type of components nested inside a dynamic zone. Reading that type is one shared call rather than a key spelled out at each site, which is what keeps the rename a change in a single place. -
#716
cf48bd7Thanks @mobeenabdullah! - A version snapshot now records each field group instance under one spelling of its type key. An entry captured before the storage rename, restored, and captured again previously kept its old key alongside the new one, so the snapshot announced the same instance's type twice. -
#731
298d41eThanks @mobeenabdullah! - Page builder inspector: keep the open panel tab in sync when the selected block changes type, so the inspector no longer shows a tab the block does not have.
Packages
@nextlyhq/adapter-drizzle@nextlyhq/adapter-mysql@nextlyhq/adapter-postgres@nextlyhq/adapter-sqlite@nextlyhq/admin@nextlyhq/admin-css@nextlyhq/blocks-engine@nextlyhq/blocks-react@nextlyhq/builder@nextlyhq/plugin-form-builder@nextlyhq/plugin-page-builder@nextlyhq/plugin-sdk@nextlyhq/plugin-seo@nextlyhq/storage-s3@nextlyhq/storage-uploadthing@nextlyhq/storage-vercel-blob@nextlyhq/uicreate-nextly-appnextly