bknd allows you to extend its functionality by creating plugins. These allows to hook into the app lifecycle and to provide a data structure that is guaranteed to be merged. A plugin is a function that takes in an instance of App and returns the following structure:
To create a simple plugin which guarantees an entity pages to be available and an additioanl endpoint to render a html list of pages, you can create it as follows:
myPagesPlugin.tsx
/** @jsxImportSource hono/jsx */import { type App, type AppPlugin, em, entity, text } from "bknd";export const myPagesPlugin: AppPlugin = (app) => ({ name: "my-pages-plugin", // define the schema of the plugin // this will always be merged into the app's schema schema: () => em({ pages: entity("pages", { title: text(), content: text(), }), }), // execute code after the app is built onBuilt: () => { // register a new endpoint, make sure that you choose an endpoint that is reachable for bknd app.server.get("/my-pages", async (c) => { const { data: pages } = await app.em.repo("pages").findMany({}); return c.html( <body> <h1>Pages: {pages.length}</h1> <ul> {pages.map((page: any) => ( <li key={page.id}>{page.title}</li> ))} </ul> </body>, ); }); },});
And then register it in your bknd.config.ts file:
import type { BkndConfig } from "bknd/adapter";import { myPagesPlugin } from "./myPagesPlugin";export default { options: { plugins: [myPagesPlugin], }} satisfies BkndConfig;
The schema returned from the plugin will be merged into the schema of the app.
A simple plugin that logs the routes of your app in the console.
bknd.config.ts
import { showRoutes } from "bknd/plugins";export default { options: { plugins: [ showRoutes({ // whether to show the routes only once (on first build) once: true }) ], },} satisfies BkndConfig;
A plugin that add Cloudflare Image Optimization to your app's media storage.
bknd.config.ts
import { cloudflareImageOptimization } from "bknd/plugins";export default { options: { plugins: [ cloudflareImageOptimization({ // the url to access the image optimization plugin accessUrl: "/api/plugin/image/optimize", // the path to resolve the image from, defaults to `/api/media/file` resolvePath: "/api/media/file", // for example, you may want to have default option to limit to a width of 1000px defaultOptions: { width: 1000, } }) ], },} satisfies BkndConfig;
Here is a break down of all configuration options:
Prop
Type
Default
accessUrl?
string
/api/plugin/image/optimize
resolvePath?
string
/api/media/file
explain?
boolean
false
defaultOptions?
any
{}
fixedOptions?
any
{}
cacheControl?
string
public, max-age=31536000, immutable
When enabled, you can now access your images at your configured accessUrl. For example, if you have a media file at /api/media/file/image.jpg, you can access the optimized image at /api/plugin/image/optimize/image.jpg for optimization.
Now you can add query parameters for the transformations, e.g. ?width=1000&height=1000.