bknd is dead long live userbase
Run Tests / test (pull_request) Successful in 4m57s

This commit is contained in:
2026-09-27 19:34:06 +05:30
parent 05e0086fcd
commit 0bfcb5ad71
529 changed files with 2385 additions and 2924 deletions
+5 -5
View File
@@ -1,5 +1,5 @@
# bknd starter: React Router
A minimal React Router project with bknd integration.
# userbase starter: React Router
A minimal React Router project with userbase integration.
## Project Structure
@@ -9,7 +9,7 @@ Inside of your React Router project, you'll see the following folders and files:
/
├── public/
├── app/
│ ├── bknd.ts
│ ├── userbase.ts
│ ├── root.tsx
│ └── routes/
│ ├── _index.tsx
@@ -18,7 +18,7 @@ Inside of your React Router project, you'll see the following folders and files:
└── package.json
```
To update `bknd` config, check `app/routes/api.$.ts` and `app/routes/admin.$.ts`.
To update `userbase` config, check `app/routes/api.$.ts` and `app/routes/admin.$.ts`.
## Commands
@@ -32,4 +32,4 @@ All commands are run from the root of the project, from a terminal:
## Want to learn more?
Feel free to check [our documentation](https://docs.bknd.io/integration/remix) or jump into our [Discord server](https://discord.gg/952SFk8Tb8).
Feel free to check [our documentation](https://docs.userbase.io/integration/remix) or jump into our [Discord server](https://discord.gg/952SFk8Tb8).
+3 -3
View File
@@ -1,8 +1,8 @@
import { getApp as getBkndApp } from "bknd/adapter/react-router";
import config from "../bknd.config";
import { getApp as getUserbaseApp } from "userbase/adapter/react-router";
import config from "../userbase.config";
export async function getApp() {
return await getBkndApp(config, process.env as any);
return await getUserbaseApp(config, process.env as any);
}
export async function getApi(args?: { request: Request }, opts?: { verify?: boolean }) {
+4 -4
View File
@@ -5,13 +5,13 @@ import {
useFetcher,
useLoaderData,
} from "react-router";
import { getApi } from "~/bknd";
import { getApi } from "~/userbase";
// biome-ignore lint/correctness/noEmptyPattern: <explanation>
export function meta({}: Route.MetaArgs) {
return [
{ title: "New bknd React Router App" },
{ name: "description", content: "Welcome to bknd & React Router!" },
{ title: "New userbase React Router App" },
{ name: "description", content: "Welcome to userbase & React Router!" },
];
}
@@ -38,7 +38,7 @@ export default function Index() {
<div className="flex h-screen items-center justify-center">
<div className="flex flex-col items-center gap-16">
<header className="flex flex-col items-center gap-9">
<img src="/bknd.svg" alt="bknd" className="block w-48 dark:invert" />
<img src="/userbase.svg" alt="userbase" className="block w-48 dark:invert" />
<div className="h-[144px] w-96">
<img
src="/logo-light.svg"
+3 -3
View File
@@ -1,9 +1,9 @@
import { lazy, Suspense, useSyncExternalStore } from "react";
import { type LoaderFunctionArgs, useLoaderData } from "react-router";
import { getApi } from "~/bknd";
import { getApi } from "~/userbase";
const Admin = lazy(() => import("bknd/ui").then((mod) => ({ default: mod.Admin })));
import "bknd/dist/styles.css";
const Admin = lazy(() => import("userbase/ui").then((mod) => ({ default: mod.Admin })));
import "userbase/dist/styles.css";
export const loader = async (args: LoaderFunctionArgs) => {
const api = await getApi(args, { verify: true });
+1 -1
View File
@@ -1,4 +1,4 @@
import { getApp } from "~/bknd";
import { getApp } from "~/userbase";
const handler = async (args: { request: Request }) => {
const app = await getApp();
+9 -9
View File
@@ -1,7 +1,7 @@
import { registerLocalMediaAdapter } from "bknd/adapter/node";
import type { ReactRouterBkndConfig } from "bknd/adapter/react-router";
import { boolean, em, entity, text } from "bknd";
import { secureRandomString } from "bknd/utils";
import { registerLocalMediaAdapter } from "userbase/adapter/node";
import type { ReactRouterUserbaseConfig } from "userbase/adapter/react-router";
import { boolean, em, entity, text } from "userbase";
import { secureRandomString } from "userbase/utils";
// since we're running in node, we can register the local media adapter
const local = registerLocalMediaAdapter();
@@ -15,7 +15,7 @@ const schema = em({
// register your schema to get automatic type completion
type Database = (typeof schema)["DB"];
declare module "bknd" {
declare module "userbase" {
interface DB extends Database {}
}
@@ -33,7 +33,7 @@ export default {
auth: {
enabled: true,
jwt: {
issuer: "bknd-remix-example",
issuer: "userbase-remix-example",
secret: secureRandomString(64),
},
},
@@ -50,15 +50,15 @@ export default {
seed: async (ctx) => {
// create some entries
await ctx.em.mutator("todos").insertMany([
{ title: "Learn bknd", done: true },
{ title: "Learn userbase", done: true },
{ title: "Build something cool", done: false },
]);
// and create a user
await ctx.app.module.auth.createUser({
email: "test@bknd.io",
email: "test@userbase.io",
password: "12345678",
});
},
},
} as const satisfies ReactRouterBkndConfig<{ DB_URL?: string }>;
} as const satisfies ReactRouterUserbaseConfig<{ DB_URL?: string }>;
+1 -1
View File
@@ -12,7 +12,7 @@
"@react-router/fs-routes": "^7.3.0",
"@react-router/node": "^7.3.0",
"@react-router/serve": "^7.3.0",
"bknd": "file:../../app",
"userbase": "file:../../app",
"isbot": "^5.1.17",
"react": "^19.0.0",
"react-dom": "^19.0.0",