License change to Apache 2.0
bknd is now licensed under the Apache 2.0 license, making it even more permissive and enterprise-friendly.
Postgres support now included
The separate @bknd/postgres package has been merged into the main bknd package. PostgreSQL connections are now available directly:
import { pgPostgres, postgresJs } from "bknd";
import { Pool } from "pg";
import postgres from 'postgres'
// using pg library
const connection = pg({
pool: new Pool({
connectionString: "postgresql://user:password@localhost:5432/database",
}),
});
// using postgres.js
const connection = postgresJs({
postgres: postgres("postgresql://user:password@localhost:5432/database"),
});MCP in admin navigation
The MCP (Model Context Protocol) tool is now accessible directly from the main navigation when enabled. The UI has been improved to be route-aware, making it easier to interact with AI tools directly from the admin interface.
Improved hybrid mode
The hybrid mode has been enhanced with better type inference and improved configuration handling:
- Reader function can now return objects directly (not just strings)
- Automatic schema syncing in development with
sync_requiredflag - Better handling of missing config files with automatic defaults
Repository auto-join for related entities
When querying with where clauses that reference related entities, bknd now automatically adds the necessary joins. This means you can filter by related entity fields without explicitly specifying joins:
// automatically joins "author" when filtering by author.name
const posts = await api.data.readMany("posts", {
where: { "author.name": "John" },
});Email OTP plugin
A new authentication plugin for passwordless login using one-time passwords sent via email. The plugin supports both login and registration flows, with configurable TTL, custom email templates, and automatic code invalidation.
import { emailOTP } from "bknd/plugins";
import { resendEmail } from "bknd";
export default {
options: {
plugins: [
emailOTP({
generateEmail: (otp) => ({
subject: "OTP Code",
body: `Your OTP code is: ${otp.code}`,
}),
})
],
},
} satisfies BkndConfig;Plunk email driver
Added support for Plunk as an email driver, joining Resend as supported transactional email services:
import { plunkEmail } from "bknd";
export default {
options: {
drivers: {
email: plunkEmail({
apiKey: "<api-key>",
from: "hello@example.com",
}),
},
}
}Special thanks to @cameronapak for adding this 🔥
SvelteKit adapter
bknd now has first-class support for SvelteKit applications. The new adapter follows the same pattern as the existing Astro and Next.js adapters. Read more in the SvelteKit integration guide. Special thanks to @screenfluent for adding this 🔥
MediaAPI uploadToEntity now supports overwrite
While already available using the REST endpoints, the SDK itself didn't add an option to specify to overwrite existing media entries. Now it is possible to overwrite existing entries if max items reached:
const { data } = await api.media.uploadToEntity(
"pets",
pet.id,
"pet_photo",
file,
{ overwrite: true } // This parameter
);Special thanks to @jonaspm for adding this 🔥
Run bknd in your browser with SQLocal
You can now run bknd entirely in your browser without any server required. Using SQLocal, bknd now supports in-browser SQLite databases using OPFS (Origin Private File System), with data persisting locally in your browser. This is perfect for offline-first applications, local development, or demo purposes.
The new BkndBrowserApp component wraps everything you need to get started:
import { BkndBrowserApp } from "bknd/adapter/browser";
import { Route } from "wouter";
export function App() {
return (
<BkndBrowserApp
config={{
/* ... your bknd config */
adminOptions: { basepath: "/admin" }
}}
/* add additional options you're used to from `bknd.config.ts` */
onBuilt={async (app) => {}}
>
{/* your routes */}
<Route path="/" component={() => <div>hello</div>} />
</BkndBrowserApp>
);
}Additionally, bknd now includes the OpfsStorageAdapter for media storage, allowing full file upload/download support in the browser environment.
Changelog
- upgrade deps by @dswbx in #290
- upgrade biome and vscode settings by @dswbx in #293
- fix hybrid schema sync by @dswbx in #295
- Update Astro integration documentation by @jonaspm in #296 🔥
- Update import path for getApi in astro.mdx by @jonaspm in #297 🔥
- Email Driver: Add Plunk Support by @cameronapak in #294 🔥
- Fix: cf proxy and modes by @dswbx in #302
- Add Cloudflare Vite templates for fullstack deployments by @dswbx in #303
- fix cli url opener and add minimal debug docker config by @dswbx in #301
- fix: recursive
withomitted join clauses by @dswbx in #299 - OTP plugin by @dswbx in #292
- fix config reconciliation for specific field types, remove lodash by @dswbx in #311
- Fix UI client import by @dswbx in #307
- fix: putting schema related endpoints behind schema permission and added tests by @dswbx in #312
- feat: Add implicit joins in repository where clauses by @dswbx in #313
- docs: updated react-router and react sdk by @dswbx in #314
- feat: move postgres as part of the main repo by @dswbx in #289
- feat: opfs and sqlocal by @dswbx in #308
- feat: add local auth support if api storage provided by @dswbx in #315
- docs: Add documentation for auth.logout method in SDK usage by @jonaspm in #319 🔥
- feat: add
default_role_registerand passwordminLengthconfig by @dswbx in #320 - feat(admin): add mcp as main navigation item when enabled, and make it route-aware by @dswbx in #321
- docs: Document data.readOneBy method with usage examples by @jonaspm in #323 🔥
- change license to apache 2.0 by @dswbx in #331
- feat: add SvelteKit adapter by @screenfluent in #324 🔥
- fix: Add overwrite option to uploadToEntity method by @jonaspm in #330 🔥
New Contributors
- @jonaspm made their first contribution in #296
- @screenfluent made their first contribution in #324
Full Changelog: v0.19.0...v0.20.0