はじめに
「ちょっとしたアプリを作りたいだけなのに、バックエンドの準備が重すぎる」と感じたことはありませんか。データベースを用意して、認証を実装して、ファイルアップロードのためにストレージを設定して……気づけばフロントエンドを書き始める前に一日が終わっている、という経験は多くの開発者に共通する悩みだと思います。
FirebaseやSupabaseのようなBaaS(Backend as a Service)を使えば楽になりますが、今度は外部サービスへの依存やベンダーロックインが気になってきます。
そこで注目したいのが、今回紹介するBknd(ビーケーエンド)です。Bkndは「フロントエンドアプリに埋め込める軽量バックエンド」という新しいアプローチを取っており、別途バックエンドをデプロイすることなく、Next.jsやAstroなどのアプリの中にデータベース・認証・メディア管理をまるごと組み込めます。
Bkndとは
Bkndは、Firebase/Supabaseの軽量な代替を目指すオープンソースのバックエンドシステムです。Web標準に準拠して作られており、Node.js・Bun・Deno・Cloudflare Workersなど、JavaScriptが動くほぼすべての環境でシームレスに実行できます。gzip圧縮でおよそ300KBからという軽量さで、完全なAPIと管理UIまで提供されるのが驚きです。
主な特徴
- フロントエンドに組み込める - Next.jsやReact Router、Astro、SvelteKitなどのアプリ内にAPIルートとして同居させられるため、バックエンドを別サービスとしてデプロイする必要がありません
- モジュラー設計 - データ(データベース)、認証、メディア、ワークフローの各機能を必要な分だけ選んで使えます
- どこでも動く - Node.js 22+、Bun、Deno、Cloudflare Workers、AWS Lambdaなど、ランタイムを選びません。データベースもSQLite(Turso/LibSQL)、PostgreSQL、Cloudflare D1に対応しています
- 3つの運用モード - 管理UIだけで完結する「UI-onlyモード」、コードで完全管理する「Code-onlyモード」、開発時はUI・本番は読み取り専用設定にする「Hybridモード」を選べます
- 管理UIを標準搭載 - Djangoの管理画面のように、データの閲覧・編集ができるAdmin UIが最初から付いてきます
インストール
npmから通常のライブラリとしてインストールできます。Node.jsは22(LTS)以上が必要です。
# npm
npm install bknd
# pnpm
pnpm add bknd
# bun
bun add bknd
まず雰囲気を掴みたい場合は、インストールなしで即起動できるクイックスタートが便利です。
npx bknd run
このコマンド一発でAPIサーバーと管理UIが立ち上がります。ブラウザで管理画面を開き、エンティティ(テーブル)をポチポチ作るだけでREST APIが手に入る手軽さは、一度体験する価値があります。
また、フレームワーク統合済みのプロジェクトを作りたい場合はCLIスターターが用意されています。
# Next.js用のスターターを対話形式で作成
npx bknd create -i nextjs
基本的な使い方
サーバーを起動する
最小構成はわずか2行です。Node.js環境なら次のコードでBkndサーバーが起動します。
import { serve } from "bknd/adapter/node";
serve();
コードでスキーマを定義する
Bkndの真骨頂は、TypeScriptでスキーマを型安全に定義できる点です。em(Entity Manager)とentityを使って、テーブル・カラム・リレーション・インデックスをコードで表現します。
import { createApp, em, entity, text, number } from "bknd";
const schema = em(
{
posts: entity("posts", {
title: text().required(),
slug: text().required(),
content: text(),
views: number(),
}),
comments: entity("comments", {
content: text(),
}),
},
({ relation, index }, { posts, comments }) => {
// コメントは記事に属する(多対一)
relation(comments).manyToOne(posts);
// インデックスを定義(第2引数trueでユニーク制約)
index(posts).on(["title"]).on(["slug"], true);
},
);
const app = createApp({
connection: { url: "file:data.db" },
config: {
data: schema.toJSON(),
},
});
ORMのスキーマ定義に近い書き味ですが、これだけでCRUD一式のREST APIと管理UIが自動生成されるのがBkndらしいところです。
認証ユーザーとのリレーション
認証モジュールが管理するusersのようなシステムエンティティとも、systemEntityを使って自然にリレーションを張れます。
import { em, entity, text, systemEntity } from "bknd";
const schema = em(
{
posts: entity("posts", {
title: text().required(),
slug: text().required(),
content: text(),
}),
users: systemEntity("users", {}),
},
({ relation }, { posts, users }) => {
// 記事は投稿ユーザーに紐づく
relation(posts).manyToOne(users);
},
);
Reactからデータを取得する
クライアント側にはReact用のフックが用意されています。SWRのような感覚でエンティティのデータを取得できます。
import { useEntityQuery } from "bknd/client";
export default function TodoList() {
const { data } = useEntityQuery("todos");
return (
<ul>
{data?.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
}
実践的なユースケース
Next.jsアプリにバックエンドを丸ごと組み込む
Bkndの魅力が最も分かりやすいのが、Next.jsとの統合です。Vercelにデプロイするだけで、フロントエンドとバックエンドが一体になったアプリが完成します。
まず、プロジェクトルートに設定ファイルを置きます。
// bknd.config.ts
import type { NextjsBkndConfig } from "bknd/adapter/nextjs";
export default {
connection: {
url: "file:data.db",
},
} satisfies NextjsBkndConfig;
次に、キャッチオールルートを作ってBkndのAPIをNext.jsのRoute Handlerとして公開します。
// src/app/api/[[...bknd]]/route.ts
import { serve } from "bknd/adapter/nextjs";
import config from "../../../../bknd.config";
const handler = serve(config);
export const GET = handler;
export const POST = handler;
export const PUT = handler;
export const PATCH = handler;
export const DELETE = handler;
これで/api/data/entity/postsのようなREST APIが生えてきます。サーバーコンポーネントからは、APIヘルパー経由で直接データを取得できます。
// src/app/posts/page.tsx(サーバーコンポーネント)
import { getApi } from "@/bknd";
export default async function PostsPage() {
const api = await getApi();
const { data: posts } = await api.data.readMany("posts", {
limit: 10,
sort: "-id",
});
return (
<main>
{posts.map((post) => (
<article key={post.id}>
<h2>{post.title}</h2>
<p>{post.content}</p>
</article>
))}
</main>
);
}
さらにadmin/[[...admin]]ルートを追加すれば、自分のアプリの中に管理画面まで持てます。「アプリ本体・API・管理画面」が1つのNext.jsプロジェクトに収まる構成は、個人開発や社内ツールでは特に強力です。
メディア管理付きのブログを作る
Bkndはメディアモジュールも備えており、AWS S3・Cloudflare R2・ローカルファイルシステムをストレージとして使えます。エンティティにメディアフィールドを持たせるのも簡単です。
import { em, entity, text, systemEntity, medium, media } from "bknd";
const schema = em(
{
posts: entity("posts", {
title: text().required(),
cover: medium(), // カバー画像(1枚)
gallery: media(), // ギャラリー(複数枚)
}),
media: systemEntity("media", {}),
},
({ relation }, { posts, media }) => {
relation(posts).polyToOne(media, { mappedBy: "cover" });
relation(posts).polyToMany(media, { mappedBy: "gallery" });
},
);
画像アップロードのためにわざわざ署名付きURLの発行処理を書いたり、別サービスを契約したりする必要がないのはうれしいポイントです。
エッジで動く軽量APIサーバー
Bkndは約300KBという軽さとWeb標準準拠の設計のおかげで、Cloudflare Workersのようなエッジ環境でも動作します。データベースにCloudflare D1やTursoを組み合わせれば、世界中どこからでも低レイテンシで応答するバックエンドを、ほぼ設定なしで構築できます。プロトタイプをエッジにそのまま昇格させられるのは、他のBaaSにはなかなかない特徴です。
まとめ
今回は、フロントエンドアプリに埋め込める軽量バックエンドのBkndを紹介しました。
- Bkndはデータベース・認証・メディア管理を備えた、Firebase/Supabaseの軽量な代替です
npx bknd runだけでAPIと管理UIが即座に立ち上がります- TypeScriptで型安全にスキーマを定義でき、CRUD APIと管理画面が自動生成されます
- Next.jsやAstroなどのアプリ内に組み込めるため、バックエンドの別デプロイが不要になります
- Node.js・Bun・Deno・Cloudflare Workersなど、動作環境を選びません
現在はテックプレビュー段階のため本番投入には見極めが必要ですが、開発の勢いは活発で、個人開発やプロトタイピングにはすでに十分魅力的な選択肢です。まずはnpx bknd runで、管理UIからエンティティを作ってAPIが生える体験を味わってみてください。バックエンド構築の億劫さが、きっと過去のものになりますよ。
