mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 04:27:21 +00:00
updated README and documentation (first part) to match 0.6
This commit is contained in:
@@ -1,106 +0,0 @@
|
||||
---
|
||||
title: 'Development'
|
||||
description: 'Preview changes locally to update your docs'
|
||||
---
|
||||
|
||||
<Info>
|
||||
**Prerequisite**: Please install Node.js (version 19 or higher) before proceeding.
|
||||
</Info>
|
||||
|
||||
Follow these steps to install and run Mintlify on your operating system:
|
||||
|
||||
**Step 1**: Install Mintlify:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```bash npm
|
||||
npm i -g mintlify
|
||||
```
|
||||
|
||||
```bash yarn
|
||||
yarn global add mintlify
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
**Step 2**: Navigate to the docs directory (where the `mint.json` file is located) and execute the following command:
|
||||
|
||||
```bash
|
||||
mintlify dev
|
||||
```
|
||||
|
||||
A local preview of your documentation will be available at `http://localhost:3000`.
|
||||
|
||||
### Custom Ports
|
||||
|
||||
By default, Mintlify uses port 3000. You can customize the port Mintlify runs on by using the `--port` flag. To run Mintlify on port 3333, for instance, use this command:
|
||||
|
||||
```bash
|
||||
mintlify dev --port 3333
|
||||
```
|
||||
|
||||
If you attempt to run Mintlify on a port that's already in use, it will use the next available port:
|
||||
|
||||
```md
|
||||
Port 3000 is already in use. Trying 3001 instead.
|
||||
```
|
||||
|
||||
## Mintlify Versions
|
||||
|
||||
Please note that each CLI release is associated with a specific version of Mintlify. If your local website doesn't align with the production version, please update the CLI:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```bash npm
|
||||
npm i -g mintlify@latest
|
||||
```
|
||||
|
||||
```bash yarn
|
||||
yarn global upgrade mintlify
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## Validating Links
|
||||
|
||||
The CLI can assist with validating reference links made in your documentation. To identify any broken links, use the following command:
|
||||
|
||||
```bash
|
||||
mintlify broken-links
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
<Tip>
|
||||
Unlimited editors available under the [Pro
|
||||
Plan](https://mintlify.com/pricing) and above.
|
||||
</Tip>
|
||||
|
||||
If the deployment is successful, you should see the following:
|
||||
|
||||
<Frame>
|
||||
<img src="/images/checks-passed.png" style={{ borderRadius: '0.5rem' }} />
|
||||
</Frame>
|
||||
|
||||
## Code Formatting
|
||||
|
||||
We suggest using extensions on your IDE to recognize and format MDX. If you're a VSCode user, consider the [MDX VSCode extension](https://marketplace.visualstudio.com/items?itemName=unifiedjs.vscode-mdx) for syntax highlighting, and [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode) for code formatting.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title='Error: Could not load the "sharp" module using the darwin-arm64 runtime'>
|
||||
|
||||
This may be due to an outdated version of node. Try the following:
|
||||
1. Remove the currently-installed version of mintlify: `npm remove -g mintlify`
|
||||
2. Upgrade to Node v19 or higher.
|
||||
3. Reinstall mintlify: `npm install -g mintlify`
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Issue: Encountering an unknown error">
|
||||
|
||||
Solution: Go to the root of your device and delete the \~/.mintlify folder. Afterwards, run `mintlify dev` again.
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
Curious about what changed in the CLI version? [Check out the CLI changelog.](https://www.npmjs.com/package/mintlify?activeTab=versions)
|
||||
@@ -52,7 +52,7 @@ export const ALL = serve({
|
||||
}
|
||||
});
|
||||
```
|
||||
For more information about the connection object, refer to the [Setup](/setup/introduction) guide. In the
|
||||
For more information about the connection object, refer to the [Database](/usage/database) guide. In the
|
||||
special case of astro, you may also use your Astro DB credentials since it's also using LibSQL
|
||||
under the hood. Refer to the [Astro DB documentation](https://docs.astro.build/en/guides/astro-db/) for more information.
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ serve({
|
||||
}
|
||||
});
|
||||
```
|
||||
For more information about the connection object, refer to the [Setup](/setup/introduction) guide.
|
||||
For more information about the connection object, refer to the [Database](/usage/database) guide.
|
||||
|
||||
Run the application using Bun by executing:
|
||||
```bash
|
||||
|
||||
@@ -31,7 +31,7 @@ export default serve({
|
||||
})
|
||||
});
|
||||
```
|
||||
For more information about the connection object, refer to the [Setup](/setup/introduction) guide.
|
||||
For more information about the connection object, refer to the [Database](/usage/database) guide.
|
||||
|
||||
Now run the worker:
|
||||
```bash
|
||||
|
||||
94
docs/integration/introduction.mdx
Normal file
94
docs/integration/introduction.mdx
Normal file
@@ -0,0 +1,94 @@
|
||||
---
|
||||
title: 'Introduction'
|
||||
description: 'Integrate bknd into your runtime/framework of choice'
|
||||
---
|
||||
|
||||
import { cloudflare, nextjs, remix, astro, bun, node, docker, vite } from "/snippets/integration-icons.mdx"
|
||||
|
||||
## Start with a Framework
|
||||
bknd seamlessly integrates with popular frameworks, allowing you to use what you're already familar with. The following guides will help you get started with your framework of choice.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card
|
||||
title="Next.js"
|
||||
icon={<div className="text-primary-light">{nextjs}</div>}
|
||||
href="/integration/nextjs"
|
||||
/>
|
||||
<Card
|
||||
title="Remix"
|
||||
icon={<div className="text-primary-light">{remix}</div>}
|
||||
href="/integration/remix"
|
||||
/>
|
||||
<Card
|
||||
title="Astro"
|
||||
icon={<div className="text-primary-light">{astro}</div>}
|
||||
href="/integration/astro"
|
||||
/>
|
||||
<Card
|
||||
horizontal
|
||||
title="Yours missing?"
|
||||
href="https://github.com/bknd-io/bknd/issues/new"
|
||||
>
|
||||
Create a new issue to request a guide for your framework.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Start with a Runtime
|
||||
If you prefer to use a runtime instead of a framework, you can choose from the following options. These runtimes allow you to serve the API and UI in the runtime's native server and serve the UI assets statically from `node_modules`.
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card
|
||||
title="Node"
|
||||
icon={<div className="text-primary-light">{node}</div>}
|
||||
href="/integration/node"
|
||||
/>
|
||||
<Card
|
||||
title="Bun"
|
||||
icon={<div className="text-primary-light">{bun}</div>}
|
||||
href="/integration/bun"
|
||||
/>
|
||||
<Card
|
||||
title="Cloudflare"
|
||||
icon={<div className="text-primary-light">{cloudflare}</div>}
|
||||
href="/integration/cloudflare"
|
||||
/>
|
||||
<Card
|
||||
title="Vite"
|
||||
icon={<div className="text-primary-light">{vite}</div>}
|
||||
href="/integration/vite"
|
||||
/>
|
||||
<Card
|
||||
title="Docker"
|
||||
icon={<div className="text-primary-light">{docker}</div>}
|
||||
href="/integration/docker"
|
||||
/>
|
||||
<Card
|
||||
horizontal
|
||||
title="Yours missing?"
|
||||
href="https://github.com/bknd-io/bknd/issues/new"
|
||||
>
|
||||
Create a new issue to request a guide for your runtime.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Overview
|
||||
|
||||
### Serving the backend (API)
|
||||
Serve the backend as an API for any JS runtime or framework. The latter is especially handy, as it allows you to deploy your frontend and backend bundled together. Furthermore it allows adding additional logic in a way you're already familar with. Just add another route and you're good to go.
|
||||
|
||||
Here is an example of serving the API using node:
|
||||
```js index.js
|
||||
import { serve } from "bknd/adapter/node"
|
||||
serve();
|
||||
```
|
||||
|
||||
### Serving the Admin UI
|
||||
The admin UI allows to manage your data including full configuration of your backend using a graphical user interface. Using `vite`, your admin route looks like this:
|
||||
```tsx admin.tsx
|
||||
import { Admin } from "bknd/ui"
|
||||
import "bknd/dist/styles.css";
|
||||
|
||||
export default function AdminPage() {
|
||||
return <Admin withProvider />
|
||||
}
|
||||
```
|
||||
@@ -28,7 +28,7 @@ export default serve({
|
||||
}
|
||||
});
|
||||
```
|
||||
For more information about the connection object, refer to the [Setup](/setup/introduction) guide.
|
||||
For more information about the connection object, refer to the [Database](/usage/database) guide.
|
||||
|
||||
## Enabling the Admin UI
|
||||
Create a file `[[...admin]].tsx` inside the `pages/admin` folder:
|
||||
|
||||
@@ -29,7 +29,7 @@ const config = {
|
||||
|
||||
serve(config);
|
||||
```
|
||||
For more information about the connection object, refer to the [Setup](/setup/introduction) guide.
|
||||
For more information about the connection object, refer to the [Database](/usage/database) guide.
|
||||
|
||||
Run the application using node by executing:
|
||||
```bash
|
||||
|
||||
@@ -26,7 +26,7 @@ const handler = serve({
|
||||
export const loader = handler;
|
||||
export const action = handler;
|
||||
```
|
||||
For more information about the connection object, refer to the [Setup](/setup/introduction) guide.
|
||||
For more information about the connection object, refer to the [Database](/usage/database) guide.
|
||||
|
||||
Now make sure that you wrap your root layout with the `ClientProvider` so that all components
|
||||
share the same context:
|
||||
|
||||
@@ -33,7 +33,7 @@ export default serve({
|
||||
}
|
||||
})
|
||||
```
|
||||
For more information about the connection object, refer to the [Setup](/setup/introduction) guide.
|
||||
For more information about the connection object, refer to the [Database](/usage/database) guide.
|
||||
|
||||
You can also run your vite server in `mode: "fresh"`, this will re-create the app on every fetch.
|
||||
This is only useful for when working on the `bknd` repository directly.
|
||||
|
||||
@@ -2,13 +2,26 @@
|
||||
title: Introduction
|
||||
---
|
||||
|
||||
import { cloudflare, nextjs, remix, astro, bun, node, docker, vite } from "/snippets/integration-icons.mdx"
|
||||
import { Stackblitz, examples } from "/snippets/stackblitz.mdx"
|
||||
|
||||
Glad you're here! This is about **bknd**, a feature-rich backend that is so lightweight it could
|
||||
run on your toaster (probably).
|
||||
|
||||
<Note>
|
||||
The documentation is currently a work in progress and not complete. Updates will be made soon.
|
||||
The documentation is currently a work in progress and not complete. Updates will be made regularily.
|
||||
</Note>
|
||||
|
||||
## Preview
|
||||
**bknd** is so lightweight that it fully runs inside StackBlitz. Take a look at the preview below:
|
||||
<Stackblitz {...examples.adminRich} />
|
||||
|
||||
<Accordion title="What's going on?" icon="lightbulb">
|
||||
The example shown is starting a [node server](/integration/node) using an [in-memory database](/usage/database#sqlite-in-memory). To ensure there are a few entities defined, it is using an [initial structure](/usage/database#initial-structure) using the prototype methods. Furthermore it uses the [seed option](/usage/database#seeding-the-database) to seed some data in the structure created.
|
||||
|
||||
To ensure there are users defined on first boot, it hooks into the `App.Events.AppFirstBoot` event to create them (documentation pending).
|
||||
</Accordion>
|
||||
|
||||
## Quickstart
|
||||
Enter the following command to spin up an instance:
|
||||
<CodeGroup>
|
||||
@@ -20,7 +33,8 @@ Enter the following command to spin up an instance:
|
||||
bunx bknd run
|
||||
```
|
||||
</CodeGroup>
|
||||
To learn more about the CLI, check out the [Using the CLI](/cli) guide.
|
||||
|
||||
To learn more about the CLI, check out the [Using the CLI](/usage/cli) guide.
|
||||
|
||||
|
||||
## Start with a Framework/Runtime
|
||||
@@ -30,73 +44,42 @@ in the future, so stay tuned!
|
||||
<CardGroup cols={2}>
|
||||
<Card
|
||||
title="Next.js"
|
||||
icon={<div className="text-primary-light">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="28px" height="28px"
|
||||
viewBox="0 0 24 24"><path fill="none" stroke="currentColor"
|
||||
stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="M9 15V9l7.745 10.65A9 9 0 1 1 19 17.657M15 12V9"/></svg></div>}
|
||||
icon={<div className="text-primary-light">{nextjs}</div>}
|
||||
href="/integration/nextjs"
|
||||
/>
|
||||
<Card
|
||||
title="Remix"
|
||||
icon={<div className="text-primary-light">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px"
|
||||
viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M19.932
|
||||
17.424c.18 2.31.18 3.394.18 4.576h-5.35c0-.258.004-.493.009-.732c.014-.743.03-1.517-.09-3.081c-.16-2.29-1.147-2.799-2.961-2.799H3.305v-4.166h8.67c2.291 0 3.437-.696 3.437-2.54c0-1.623-1.146-2.605-3.437-2.605h-8.67V2h9.624c5.189 0 7.767 2.449 7.767 6.36c0 2.926-1.814 4.834-4.265 5.152c2.069.413 3.278 1.59 3.501 3.912" clip-rule="evenodd"/><path fill="currentColor" d="M3.305 22v-3.106h5.657c.945 0 1.15.7 1.15 1.118V22z"/></svg>
|
||||
</div>}
|
||||
icon={<div className="text-primary-light">{remix}</div>}
|
||||
href="/integration/remix"
|
||||
/>
|
||||
<Card
|
||||
title="Astro"
|
||||
icon={<div className="text-primary-light">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||
<rect width="24" height="24" fill="none"/><path fill="currentColor" d="M9.24 19.035c-.901-.826-1.164-2.561-.789-3.819c.65.793 1.552 1.044 2.486 1.186c1.44.218 2.856.137 4.195-.524c.153-.076.295-.177.462-.278c.126.365.159.734.115 1.11c-.107.915-.56 1.622-1.283 2.158c-.289.215-.594.406-.892.608c-.916.622-1.164 1.35-.82 2.41l.034.114a2.4 2.4 0 0 1-1.07-.918a2.6 2.6 0 0 1-.412-1.401c-.003-.248-.003-.497-.036-.74c-.081-.595-.36-.86-.883-.876a1.034 1.034 0 0 0-1.075.843q-.013.058-.033.126M4.1 15.007s2.666-1.303 5.34-1.303l2.016-6.26c.075-.304.296-.51.544-.51c.25 0 .47.206.545.51l2.016 6.26c3.167 0 5.34 1.303 5.34 1.303L15.363 2.602c-.13-.366-.35-.602-.645-.602H9.283c-.296 0-.506.236-.645.602c-.01.024-4.538 12.405-4.538 12.405"/>
|
||||
</svg>
|
||||
</div>}
|
||||
icon={<div className="text-primary-light">{astro}</div>}
|
||||
href="/integration/astro"
|
||||
/>
|
||||
<Card
|
||||
title="Node"
|
||||
icon={<div className="text-primary-light">{node}</div>}
|
||||
href="/integration/node"
|
||||
/>
|
||||
<Card
|
||||
title="Cloudflare"
|
||||
icon={<div className="text-primary-light">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 128 128">
|
||||
<path fill="currentColor" d="M30.743 116.257a15.5 15.5 0 0 1-3.42-4.107L4.068 71.752a15.56 15.56 0 0 1 0-15.503L27.323 15.85a15.5 15.5 0 0 1 3.417-4.084l15.601 28.166l-11.266 20.282a7.75 7.75 0 0 0 0 7.543l11.277 20.349zM100.665 15.85l23.255 40.398a15.49 15.49 0 0 1 0 15.503l-23.255 40.398a15.5 15.5 0 0 1-13.416 7.752H68.994l28.92-52.145a7.75 7.75 0 0 0 0-7.513L68.994 8.099h18.255a15.5 15.5 0 0 1 13.416 7.751M36.119 9.139a15.5 15.5 0 0 1 5.562-1.041h21.255l28.92 52.145a7.75 7.75 0 0 1 0 7.513l-28.92 52.145H41.682c-2.062 0-4.124-.423-5.993-1.193L63.406 67.29c.894-1.61 1.002-4.738.107-6.348z"/>
|
||||
</svg>
|
||||
</div>}
|
||||
icon={<div className="text-primary-light">{cloudflare}</div>}
|
||||
href="/integration/cloudflare"
|
||||
/>
|
||||
<Card
|
||||
title="Bun"
|
||||
icon={<div className="text-primary-light">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path fill="currentColor" d="M12 22.596c6.628 0 12-4.338 12-9.688c0-3.318-2.057-6.248-5.219-7.986c-1.286-.715-2.297-1.357-3.139-1.89C14.058 2.025 13.08 1.404 12 1.404c-1.097 0-2.334.785-3.966 1.821a50 50 0 0 1-2.816 1.697C2.057 6.66 0 9.59 0 12.908c0 5.35 5.372 9.687 12 9.687zM10.599 4.715c.334-.759.503-1.58.498-2.409c0-.145.202-.187.23-.029c.658 2.783-.902 4.162-2.057 4.624c-.124.048-.199-.121-.103-.209a5.8 5.8 0 0 0 1.432-1.977m2.058-.102a5.8 5.8 0 0 0-.782-2.306v-.016c-.069-.123.086-.263.185-.172c1.962 2.111 1.307 4.067.556 5.051c-.082.103-.23-.003-.189-.126a5.85 5.85 0 0 0 .23-2.431m1.776-.561a5.7 5.7 0 0 0-1.612-1.806v-.014c-.112-.085-.024-.274.114-.218c2.595 1.087 2.774 3.18 2.459 4.407a.12.12 0 0 1-.049.071a.11.11 0 0 1-.153-.026a.12.12 0 0 1-.022-.083a5.9 5.9 0 0 0-.737-2.331m-5.087.561c-.617.546-1.282.76-2.063 1c-.117 0-.195-.078-.156-.181c1.752-.909 2.376-1.649 2.999-2.778c0 0 .155-.118.188.085c0 .304-.349 1.329-.968 1.874m4.945 11.237a2.96 2.96 0 0 1-.937 1.553c-.346.346-.8.565-1.286.62a2.18 2.18 0 0 1-1.327-.62a2.96 2.96 0 0 1-.925-1.553a.24.24 0 0 1 .064-.198a.23.23 0 0 1 .193-.069h3.965a.23.23 0 0 1 .19.07c.05.053.073.125.063.197m-5.458-2.176a1.86 1.86 0 0 1-2.384-.245a1.98 1.98 0 0 1-.233-2.447c.207-.319.503-.566.848-.713a1.84 1.84 0 0 1 1.092-.11c.366.075.703.261.967.531a1.98 1.98 0 0 1 .408 2.114a1.93 1.93 0 0 1-.698.869zm8.495.005a1.86 1.86 0 0 1-2.381-.253a1.96 1.96 0 0 1-.547-1.366c0-.384.11-.76.32-1.079c.207-.319.503-.567.849-.713a1.84 1.84 0 0 1 1.093-.108c.367.076.704.262.968.534a1.98 1.98 0 0 1 .4 2.117a1.93 1.93 0 0 1-.702.868"/>
|
||||
</svg>
|
||||
</div>}
|
||||
icon={<div className="text-primary-light">{bun}</div>}
|
||||
href="/integration/bun"
|
||||
/>
|
||||
<Card
|
||||
title="Node"
|
||||
icon={<div className="text-primary-light">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width={24} height={24} viewBox="0 0 24 24">
|
||||
<path fill="currentColor" d="M12 23.956c-.342 0-.66-.089-.957-.243l-3.029-1.738c-.455-.242-.227-.33-.09-.374c.614-.198.728-.242 1.366-.595c.068-.044.16-.022.228.022l2.323 1.343c.09.044.205.044.273 0l9.087-5.084c.09-.044.136-.132.136-.242V6.899c0-.11-.045-.198-.136-.242l-9.087-5.061c-.091-.044-.205-.044-.273 0L2.754 6.657c-.091.044-.137.154-.137.242v10.146c0 .088.046.198.137.242l2.482 1.387c1.344.66 2.186-.11 2.186-.88V7.78c0-.132.114-.264.274-.264h1.161c.137 0 .273.11.273.264v10.013c0 1.739-.979 2.751-2.687 2.751c-.524 0-.934 0-2.095-.55l-2.391-1.32A1.85 1.85 0 0 1 1 17.067V6.921c0-.66.364-1.276.957-1.606L11.044.23a2.1 2.1 0 0 1 1.912 0l9.088 5.084c.592.33.956.946.956 1.606v10.146c0 .66-.364 1.276-.956 1.607l-9.087 5.083a2.4 2.4 0 0 1-.957.198m2.801-6.977c-3.985 0-4.805-1.76-4.805-3.257c0-.132.114-.264.273-.264h1.184c.137 0 .25.088.25.22c.183 1.166.707 1.738 3.121 1.738c1.913 0 2.733-.418 2.733-1.408c0-.572-.228-.99-3.211-1.276c-2.483-.243-4.031-.77-4.031-2.685c0-1.783 1.548-2.84 4.145-2.84c2.915 0 4.35.969 4.532 3.082a.35.35 0 0 1-.069.198c-.045.044-.113.088-.182.088h-1.184a.265.265 0 0 1-.25-.198c-.274-1.21-.98-1.607-2.847-1.607c-2.096 0-2.346.704-2.346 1.233c0 .638.296.836 3.12 1.188c2.801.352 4.122.858 4.122 2.75c-.023 1.938-1.662 3.038-4.555 3.038"></path>
|
||||
</svg>
|
||||
</div>}
|
||||
href="/integration/node"
|
||||
/>
|
||||
<Card
|
||||
title="Vite"
|
||||
icon={<div className="text-primary-light">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24">
|
||||
<rect width="24" height="24" fill="none"/><path fill="currentColor" d="m8.525 4.63l-5.132-.915a1.17 1.17 0 0 0-1.164.468a1.16 1.16 0 0 0-.07 1.28l8.901 15.58a1.182 1.182 0 0 0 2.057-.008l8.729-15.578c.49-.875-.262-1.917-1.242-1.739l-4.574.813l-.206.754l4.906-.871a.474.474 0 0 1 .498.697L12.5 20.689a.47.47 0 0 1-.5.234a.47.47 0 0 1-.326-.231L2.772 5.112a.474.474 0 0 1 .496-.7l5.133.916l.074.013z"/><path fill="currentColor" d="m15.097 5.26l.162-.593l-.6.107zm-5.88-.506l.513.09l-.542.427z"/><path fill="currentColor" d="m15.549 2.367l-6.1 1.26a.22.22 0 0 0-.126.077a.25.25 0 0 0-.055.142l-.375 6.685a.24.24 0 0 0 .079.194a.21.21 0 0 0 .195.05l1.698-.414c.16-.038.302.11.27.278l-.505 2.606c-.034.176.122.326.285.274l1.049-.336c.162-.052.319.098.284.274l-.801 4.093c-.05.257.272.396.407.177l.09-.147l4.97-10.464c.084-.175-.06-.375-.242-.338l-1.748.356c-.165.034-.304-.128-.258-.297l1.14-4.173c.047-.17-.093-.331-.257-.297"/>
|
||||
</svg>
|
||||
</div>}
|
||||
icon={<div className="text-primary-light">{vite}</div>}
|
||||
href="/integration/vite"
|
||||
/>
|
||||
<Card
|
||||
title="Docker"
|
||||
icon={<div className="text-primary-light">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width={30} height={30} viewBox="0 0 24 24"><path
|
||||
fill="currentColor" d="M21.81 10.25c-.06-.04-.56-.43-1.64-.43c-.28 0-.56.03-.84.08c-.21-1.4-1.38-2.11-1.43-2.14l-.29-.17l-.18.27c-.24.36-.43.77-.51 1.19c-.2.8-.08 1.56.33 2.21c-.49.28-1.29.35-1.46.35H2.62c-.34 0-.62.28-.62.63c0 1.15.18 2.3.58 3.38c.45 1.19 1.13 2.07 2 2.61c.98.6 2.59.94 4.42.94c.79 0 1.61-.07 2.42-.22c1.12-.2 2.2-.59 3.19-1.16A8.3 8.3 0 0 0 16.78 16c1.05-1.17 1.67-2.5 2.12-3.65h.19c1.14 0 1.85-.46 2.24-.85c.26-.24.45-.53.59-.87l.08-.24zm-17.96.99h1.76c.08 0 .16-.07.16-.16V9.5c0-.08-.07-.16-.16-.16H3.85c-.09 0-.16.07-.16.16v1.58c.01.09.07.16.16.16m2.43 0h1.76c.08 0 .16-.07.16-.16V9.5c0-.08-.07-.16-.16-.16H6.28c-.09 0-.16.07-.16.16v1.58c.01.09.07.16.16.16m2.47 0h1.75c.1 0 .17-.07.17-.16V9.5c0-.08-.06-.16-.17-.16H8.75c-.08 0-.15.07-.15.16v1.58c0 .09.06.16.15.16m2.44 0h1.77c.08 0 .15-.07.15-.16V9.5c0-.08-.06-.16-.15-.16h-1.77c-.08 0-.15.07-.15.16v1.58c0 .09.07.16.15.16M6.28 9h1.76c.08 0 .16-.09.16-.18V7.25c0-.09-.07-.16-.16-.16H6.28c-.09 0-.16.06-.16.16v1.57c.01.09.07.18.16.18m2.47 0h1.75c.1 0 .17-.09.17-.18V7.25c0-.09-.06-.16-.17-.16H8.75c-.08 0-.15.06-.15.16v1.57c0 .09.06.18.15.18m2.44 0h1.77c.08 0 .15-.09.15-.18V7.25c0-.09-.07-.16-.15-.16h-1.77c-.08 0-.15.06-.15.16v1.57c0 .09.07.18.15.18m0-2.28h1.77c.08 0 .15-.07.15-.16V5c0-.1-.07-.17-.15-.17h-1.77c-.08 0-.15.06-.15.17v1.56c0 .08.07.16.15.16m2.46 4.52h1.76c.09 0 .16-.07.16-.16V9.5c0-.08-.07-.16-.16-.16h-1.76c-.08 0-.15.07-.15.16v1.58c0 .09.07.16.15.16"></path></svg>
|
||||
</div>}
|
||||
icon={<div className="text-primary-light">{docker}</div>}
|
||||
href="/integration/docker"
|
||||
/>
|
||||
</CardGroup>
|
||||
|
||||
@@ -61,11 +61,43 @@
|
||||
"navigation": [
|
||||
{
|
||||
"group": "Getting Started",
|
||||
"pages": ["introduction", "sdk", "react", "cli"]
|
||||
"pages": ["introduction", "motivation"]
|
||||
},
|
||||
{
|
||||
"group": "Setup",
|
||||
"pages": ["setup/introduction", "setup/database"]
|
||||
"group": "Usage",
|
||||
"pages": [
|
||||
"usage/introduction",
|
||||
"usage/database",
|
||||
"usage/cli",
|
||||
"usage/sdk",
|
||||
"usage/react",
|
||||
"usage/elements"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Integration",
|
||||
"pages": [
|
||||
"integration/introduction",
|
||||
{
|
||||
"group": "Frameworks",
|
||||
"pages": [
|
||||
"integration/nextjs",
|
||||
"integration/remix",
|
||||
"integration/astro",
|
||||
"integration/vite"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Runtimes",
|
||||
"pages": [
|
||||
"integration/node",
|
||||
"integration/bun",
|
||||
"integration/cloudflare",
|
||||
"integration/deno",
|
||||
"integration/docker"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Modules",
|
||||
@@ -78,21 +110,6 @@
|
||||
"modules/flows"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Integration",
|
||||
"pages": [
|
||||
"integration/extending",
|
||||
"integration/nextjs",
|
||||
"integration/remix",
|
||||
"integration/cloudflare",
|
||||
"integration/bun",
|
||||
"integration/astro",
|
||||
"integration/node",
|
||||
"integration/deno",
|
||||
"integration/vite",
|
||||
"integration/docker"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Deployment",
|
||||
"pages": [
|
||||
|
||||
71
docs/motivation.mdx
Normal file
71
docs/motivation.mdx
Normal file
@@ -0,0 +1,71 @@
|
||||
---
|
||||
title: "Motivation"
|
||||
description: "Why another backend system?"
|
||||
---
|
||||
|
||||
Creating digital products always requires developing both the backend (the logic) and the frontend (the appearance). Building a backend from scratch demands deep knowledge in areas such as authentication and database management. Using a backend framework can speed up initial development, but it still requires ongoing effort to work within its constraints (e.g., *"how to do X with Y?"*), which can quickly slow you down. Choosing a backend system is a tough decision, as you might not be aware of its limitations until you encounter them.
|
||||
|
||||
<Check>
|
||||
**The solution:** A backend system that only assumes and implements primitive details, integrates into multiple environments, and adheres to industry standards.
|
||||
</Check>
|
||||
|
||||
For the sake of brevity, let's assume you are looking for a "backend system" rather than dealing with custom implementations yourself. Let's identify the most common challenges:
|
||||
|
||||
1. Database lock-in
|
||||
2. Environment and framework lock-in
|
||||
3. Deviation from standards (such as `X-Auth` headers for authentication)
|
||||
4. *Wrong-for-your-use-case* implementations
|
||||
5. Complex self-hosting
|
||||
|
||||
## Database lock-in
|
||||
As the developer of a backend system, you must make tough decisions, one of which is choosing which database(s) to support. To simplify development, many systems lock you into a single database, leveraging its advanced features.
|
||||
|
||||
But isn't the database known to be the hardest part to scale? Isn't more logic moving to the application layer? Haven't NoSQL databases proven this? If you're like me, you may have dipped your toes into the NoSQL world only to quickly return to SQL. SQL is known, predictable, and safe. But what if we could have both? NoSQL offers flexibility and scalability, yet querying it is tedious due to vendor-specific implementations.
|
||||
|
||||
To get the best of both worlds, bknd focuses on the weakest SQL database (SQLite), treating it as a data store and query interface. Schema details and enforcement are moved to the application layer, making it easy to adjust a default value or property length. The added benefit is that any SQL database could theoretically work the same way, and since it's all TypeScript, the same validation logic can be used on both the client and server sides–you can validate your data before it even reaches your server. It even works without database-enforced referential integrity, as the integrity checks occur on the application layer. This opens the door to NewSQL systems like PlanetScale.
|
||||
|
||||
## Environment and framework lock-in
|
||||
There are backend systems that embed themselves into a specific React framework. This works well until you realize it doesn't support your preferred framework or the new hyped one you're considering switching to. Just like database choices, decisions must be made. The easiest path is to select a single option and let people live with it.
|
||||
|
||||
Alternatively, you could develop for the weakest environment (workerd) by strictly using Web APIs, avoiding shortcuts, and implementing certain logic manually because the go-to package is using Node APIs. This isn't always fun, but it's essential. The benefit? It works anywhere JavaScript does.
|
||||
|
||||
bknd is the only backend system that not only works with any JavaScript framework but also integrates directly into it. It runs within the framework, enabling a single deployment for your entire app.
|
||||
|
||||
*"But isn't it ironic that it forces a JavaScript environment?"* you might ask. And you're right, but it also allows running standalone via CLI or Docker.
|
||||
|
||||
|
||||
## Deviation from standards
|
||||
One of the biggest frustrations I've encountered is when software vendors choose custom headers for authentication or implement query parameters in a format they find more suitable—such as unencoded JSON for simplicity. When you are in full control, it's tempting to use a more suitable format, or just use an auth-ish name for the header property–after all, it's just a header, right?
|
||||
|
||||
The issue is that users may rely on HTTP clients that offer built-in authentication methods, which won't include your custom solution. Custom `SearchParams` implementations might be convenient, but translating them across different environments and languages can be challenging without trial and error.
|
||||
|
||||
bknd strives to adhere to web standards as much as possible while offering handy alternatives. Here's an example of the `select` search parameter for retrieving a list of entities:
|
||||
```bash
|
||||
/api/data/todos?select=id&select=name # web standard
|
||||
/api/data/todos?select=id,name # handy alternative
|
||||
```
|
||||
|
||||
If you ever find an instance where bknd isn't adhering to standards or could be improved, please feel free to [file an issue](https://github.com/bknd-io/bknd/issues/new). Your feedback is greatly appreciated!
|
||||
|
||||
|
||||
## Wrong-for-your-use-case implementations
|
||||
If you've ever developed a social chat application, you likely discovered the extensive feature depth required—features we often take for granted. Things like socket connections for single and group chats, partial loading, asset attachments, and emoji reactions. Even more frustrating, these features make the app being considered incomplete until delivered.
|
||||
|
||||
The same applies to backend systems. Features such as email sending, password resets, and image transformations are expected. Worse still, you'll receive feedback requesting different email verification methods—PIN codes instead of links, 4-digit codes versus 6-digit ones, or UUIDs like Axiom uses.
|
||||
|
||||
Since it's impossible to satisfy all requirements, why implement them at all? *"Because people expect it."* That's fair. But technically, email verification is not a core backend feature—it's business logic. Setting it up involves:
|
||||
1. Adding a `code` and `verified` field to the users' entity and generating a random code on creation.
|
||||
2. Creating an endpoint to accept the code, retrieve the authenticated user, check the code, clear it, and mark the user as verified.
|
||||
|
||||
Additional security measures, such as short-lived tokens, can be added, but the concept remains simple.
|
||||
|
||||
Instead of hardcoding such features, bknd offers a powerful event system that supports asynchronous (like webhooks) and synchronous execution, blocking further actions if needed. With integrated workflows (UI coming soon), you can listen to and react to system events, and even map them to endpoints. Since workflows, like everything else in bknd, are JSON-serializable, they're easy to export and import.
|
||||
|
||||
## Complex self-hosting
|
||||
Finally, hosting. It's a business advantage if your system is highly sought after but difficult to self-host, forcing users to opt for your cloud service. The truth is, if it's hard for users, it's also hard for the vendor, which drives up costs.
|
||||
|
||||
If you know how to deploy your Next.js, Remix, or Astro application, you can deploy bknd. It's straightforward to deploy using Cloudflare Workers/Pages or with just 28 lines of a Dockerfile. No PhD required.
|
||||
|
||||
|
||||
|
||||
|
||||
31
docs/snippets/integration-icons.mdx
Normal file
31
docs/snippets/integration-icons.mdx
Normal file
@@ -0,0 +1,31 @@
|
||||
export const nextjs = <svg xmlns="http://www.w3.org/2000/svg" width="28px" height="28px"
|
||||
viewBox="0 0 24 24"><path fill="none" stroke="currentColor"
|
||||
stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="2" d="M9 15V9l7.745 10.65A9 9 0 1 1 19 17.657M15 12V9"/></svg>
|
||||
|
||||
export const remix = <svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px"
|
||||
viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" d="M19.932
|
||||
17.424c.18 2.31.18 3.394.18 4.576h-5.35c0-.258.004-.493.009-.732c.014-.743.03-1.517-.09-3.081c-.16-2.29-1.147-2.799-2.961-2.799H3.305v-4.166h8.67c2.291 0 3.437-.696 3.437-2.54c0-1.623-1.146-2.605-3.437-2.605h-8.67V2h9.624c5.189 0 7.767 2.449 7.767 6.36c0 2.926-1.814 4.834-4.265 5.152c2.069.413 3.278 1.59 3.501 3.912" clip-rule="evenodd"/><path fill="currentColor" d="M3.305 22v-3.106h5.657c.945 0 1.15.7 1.15 1.118V22z"/></svg>;
|
||||
|
||||
export const astro = <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
|
||||
<rect width="24" height="24" fill="none"/><path fill="currentColor" d="M9.24 19.035c-.901-.826-1.164-2.561-.789-3.819c.65.793 1.552 1.044 2.486 1.186c1.44.218 2.856.137 4.195-.524c.153-.076.295-.177.462-.278c.126.365.159.734.115 1.11c-.107.915-.56 1.622-1.283 2.158c-.289.215-.594.406-.892.608c-.916.622-1.164 1.35-.82 2.41l.034.114a2.4 2.4 0 0 1-1.07-.918a2.6 2.6 0 0 1-.412-1.401c-.003-.248-.003-.497-.036-.74c-.081-.595-.36-.86-.883-.876a1.034 1.034 0 0 0-1.075.843q-.013.058-.033.126M4.1 15.007s2.666-1.303 5.34-1.303l2.016-6.26c.075-.304.296-.51.544-.51c.25 0 .47.206.545.51l2.016 6.26c3.167 0 5.34 1.303 5.34 1.303L15.363 2.602c-.13-.366-.35-.602-.645-.602H9.283c-.296 0-.506.236-.645.602c-.01.024-4.538 12.405-4.538 12.405"/>
|
||||
</svg>
|
||||
|
||||
export const cloudflare = <svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 128 128">
|
||||
<path fill="currentColor" d="M30.743 116.257a15.5 15.5 0 0 1-3.42-4.107L4.068 71.752a15.56 15.56 0 0 1 0-15.503L27.323 15.85a15.5 15.5 0 0 1 3.417-4.084l15.601 28.166l-11.266 20.282a7.75 7.75 0 0 0 0 7.543l11.277 20.349zM100.665 15.85l23.255 40.398a15.49 15.49 0 0 1 0 15.503l-23.255 40.398a15.5 15.5 0 0 1-13.416 7.752H68.994l28.92-52.145a7.75 7.75 0 0 0 0-7.513L68.994 8.099h18.255a15.5 15.5 0 0 1 13.416 7.751M36.119 9.139a15.5 15.5 0 0 1 5.562-1.041h21.255l28.92 52.145a7.75 7.75 0 0 1 0 7.513l-28.92 52.145H41.682c-2.062 0-4.124-.423-5.993-1.193L63.406 67.29c.894-1.61 1.002-4.738.107-6.348z"/>
|
||||
</svg>
|
||||
|
||||
export const bun = <svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24">
|
||||
<path fill="currentColor" d="M12 22.596c6.628 0 12-4.338 12-9.688c0-3.318-2.057-6.248-5.219-7.986c-1.286-.715-2.297-1.357-3.139-1.89C14.058 2.025 13.08 1.404 12 1.404c-1.097 0-2.334.785-3.966 1.821a50 50 0 0 1-2.816 1.697C2.057 6.66 0 9.59 0 12.908c0 5.35 5.372 9.687 12 9.687zM10.599 4.715c.334-.759.503-1.58.498-2.409c0-.145.202-.187.23-.029c.658 2.783-.902 4.162-2.057 4.624c-.124.048-.199-.121-.103-.209a5.8 5.8 0 0 0 1.432-1.977m2.058-.102a5.8 5.8 0 0 0-.782-2.306v-.016c-.069-.123.086-.263.185-.172c1.962 2.111 1.307 4.067.556 5.051c-.082.103-.23-.003-.189-.126a5.85 5.85 0 0 0 .23-2.431m1.776-.561a5.7 5.7 0 0 0-1.612-1.806v-.014c-.112-.085-.024-.274.114-.218c2.595 1.087 2.774 3.18 2.459 4.407a.12.12 0 0 1-.049.071a.11.11 0 0 1-.153-.026a.12.12 0 0 1-.022-.083a5.9 5.9 0 0 0-.737-2.331m-5.087.561c-.617.546-1.282.76-2.063 1c-.117 0-.195-.078-.156-.181c1.752-.909 2.376-1.649 2.999-2.778c0 0 .155-.118.188.085c0 .304-.349 1.329-.968 1.874m4.945 11.237a2.96 2.96 0 0 1-.937 1.553c-.346.346-.8.565-1.286.62a2.18 2.18 0 0 1-1.327-.62a2.96 2.96 0 0 1-.925-1.553a.24.24 0 0 1 .064-.198a.23.23 0 0 1 .193-.069h3.965a.23.23 0 0 1 .19.07c.05.053.073.125.063.197m-5.458-2.176a1.86 1.86 0 0 1-2.384-.245a1.98 1.98 0 0 1-.233-2.447c.207-.319.503-.566.848-.713a1.84 1.84 0 0 1 1.092-.11c.366.075.703.261.967.531a1.98 1.98 0 0 1 .408 2.114a1.93 1.93 0 0 1-.698.869zm8.495.005a1.86 1.86 0 0 1-2.381-.253a1.96 1.96 0 0 1-.547-1.366c0-.384.11-.76.32-1.079c.207-.319.503-.567.849-.713a1.84 1.84 0 0 1 1.093-.108c.367.076.704.262.968.534a1.98 1.98 0 0 1 .4 2.117a1.93 1.93 0 0 1-.702.868"/>
|
||||
</svg>
|
||||
|
||||
export const node = <svg xmlns="http://www.w3.org/2000/svg" width={24} height={24} viewBox="0 0 24 24">
|
||||
<path fill="currentColor" d="M12 23.956c-.342 0-.66-.089-.957-.243l-3.029-1.738c-.455-.242-.227-.33-.09-.374c.614-.198.728-.242 1.366-.595c.068-.044.16-.022.228.022l2.323 1.343c.09.044.205.044.273 0l9.087-5.084c.09-.044.136-.132.136-.242V6.899c0-.11-.045-.198-.136-.242l-9.087-5.061c-.091-.044-.205-.044-.273 0L2.754 6.657c-.091.044-.137.154-.137.242v10.146c0 .088.046.198.137.242l2.482 1.387c1.344.66 2.186-.11 2.186-.88V7.78c0-.132.114-.264.274-.264h1.161c.137 0 .273.11.273.264v10.013c0 1.739-.979 2.751-2.687 2.751c-.524 0-.934 0-2.095-.55l-2.391-1.32A1.85 1.85 0 0 1 1 17.067V6.921c0-.66.364-1.276.957-1.606L11.044.23a2.1 2.1 0 0 1 1.912 0l9.088 5.084c.592.33.956.946.956 1.606v10.146c0 .66-.364 1.276-.956 1.607l-9.087 5.083a2.4 2.4 0 0 1-.957.198m2.801-6.977c-3.985 0-4.805-1.76-4.805-3.257c0-.132.114-.264.273-.264h1.184c.137 0 .25.088.25.22c.183 1.166.707 1.738 3.121 1.738c1.913 0 2.733-.418 2.733-1.408c0-.572-.228-.99-3.211-1.276c-2.483-.243-4.031-.77-4.031-2.685c0-1.783 1.548-2.84 4.145-2.84c2.915 0 4.35.969 4.532 3.082a.35.35 0 0 1-.069.198c-.045.044-.113.088-.182.088h-1.184a.265.265 0 0 1-.25-.198c-.274-1.21-.98-1.607-2.847-1.607c-2.096 0-2.346.704-2.346 1.233c0 .638.296.836 3.12 1.188c2.801.352 4.122.858 4.122 2.75c-.023 1.938-1.662 3.038-4.555 3.038"></path>
|
||||
</svg>
|
||||
|
||||
export const vite = <svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24">
|
||||
<rect width="24" height="24" fill="none"/><path fill="currentColor" d="m8.525 4.63l-5.132-.915a1.17 1.17 0 0 0-1.164.468a1.16 1.16 0 0 0-.07 1.28l8.901 15.58a1.182 1.182 0 0 0 2.057-.008l8.729-15.578c.49-.875-.262-1.917-1.242-1.739l-4.574.813l-.206.754l4.906-.871a.474.474 0 0 1 .498.697L12.5 20.689a.47.47 0 0 1-.5.234a.47.47 0 0 1-.326-.231L2.772 5.112a.474.474 0 0 1 .496-.7l5.133.916l.074.013z"/><path fill="currentColor" d="m15.097 5.26l.162-.593l-.6.107zm-5.88-.506l.513.09l-.542.427z"/><path fill="currentColor" d="m15.549 2.367l-6.1 1.26a.22.22 0 0 0-.126.077a.25.25 0 0 0-.055.142l-.375 6.685a.24.24 0 0 0 .079.194a.21.21 0 0 0 .195.05l1.698-.414c.16-.038.302.11.27.278l-.505 2.606c-.034.176.122.326.285.274l1.049-.336c.162-.052.319.098.284.274l-.801 4.093c-.05.257.272.396.407.177l.09-.147l4.97-10.464c.084-.175-.06-.375-.242-.338l-1.748.356c-.165.034-.304-.128-.258-.297l1.14-4.173c.047-.17-.093-.331-.257-.297"/>
|
||||
</svg>
|
||||
|
||||
export const docker = <svg xmlns="http://www.w3.org/2000/svg" width={30} height={30} viewBox="0 0 24 24"><path
|
||||
fill="currentColor" d="M21.81 10.25c-.06-.04-.56-.43-1.64-.43c-.28 0-.56.03-.84.08c-.21-1.4-1.38-2.11-1.43-2.14l-.29-.17l-.18.27c-.24.36-.43.77-.51 1.19c-.2.8-.08 1.56.33 2.21c-.49.28-1.29.35-1.46.35H2.62c-.34 0-.62.28-.62.63c0 1.15.18 2.3.58 3.38c.45 1.19 1.13 2.07 2 2.61c.98.6 2.59.94 4.42.94c.79 0 1.61-.07 2.42-.22c1.12-.2 2.2-.59 3.19-1.16A8.3 8.3 0 0 0 16.78 16c1.05-1.17 1.67-2.5 2.12-3.65h.19c1.14 0 1.85-.46 2.24-.85c.26-.24.45-.53.59-.87l.08-.24zm-17.96.99h1.76c.08 0 .16-.07.16-.16V9.5c0-.08-.07-.16-.16-.16H3.85c-.09 0-.16.07-.16.16v1.58c.01.09.07.16.16.16m2.43 0h1.76c.08 0 .16-.07.16-.16V9.5c0-.08-.07-.16-.16-.16H6.28c-.09 0-.16.07-.16.16v1.58c.01.09.07.16.16.16m2.47 0h1.75c.1 0 .17-.07.17-.16V9.5c0-.08-.06-.16-.17-.16H8.75c-.08 0-.15.07-.15.16v1.58c0 .09.06.16.15.16m2.44 0h1.77c.08 0 .15-.07.15-.16V9.5c0-.08-.06-.16-.15-.16h-1.77c-.08 0-.15.07-.15.16v1.58c0 .09.07.16.15.16M6.28 9h1.76c.08 0 .16-.09.16-.18V7.25c0-.09-.07-.16-.16-.16H6.28c-.09 0-.16.06-.16.16v1.57c.01.09.07.18.16.18m2.47 0h1.75c.1 0 .17-.09.17-.18V7.25c0-.09-.06-.16-.17-.16H8.75c-.08 0-.15.06-.15.16v1.57c0 .09.06.18.15.18m2.44 0h1.77c.08 0 .15-.09.15-.18V7.25c0-.09-.07-.16-.15-.16h-1.77c-.08 0-.15.06-.15.16v1.57c0 .09.07.18.15.18m0-2.28h1.77c.08 0 .15-.07.15-.16V5c0-.1-.07-.17-.15-.17h-1.77c-.08 0-.15.06-.15.17v1.56c0 .08.07.16.15.16m2.46 4.52h1.76c.09 0 .16-.07.16-.16V9.5c0-.08-.07-.16-.16-.16h-1.76c-.08 0-.15.07-.15.16v1.58c0 .09.07.16.15.16"></path></svg>
|
||||
45
docs/snippets/stackblitz.mdx
Normal file
45
docs/snippets/stackblitz.mdx
Normal file
@@ -0,0 +1,45 @@
|
||||
export const examples = {
|
||||
adminRich: {
|
||||
path: "github/bknd-io/bknd-examples",
|
||||
startScript: "example-admin-rich",
|
||||
initialPath: "/data/schema"
|
||||
}
|
||||
}
|
||||
|
||||
export const Stackblitz = ({
|
||||
path = "github/bknd-io/bknd-examples",
|
||||
ratio = 9/16,
|
||||
...props
|
||||
}) => {
|
||||
const params = new URLSearchParams({
|
||||
ctl: 1,
|
||||
hideExplorer: 1,
|
||||
embed: 1,
|
||||
view: "preview",
|
||||
...props
|
||||
})
|
||||
const url = new URL(`https://stackblitz.com/${path}?${params.toString()}`)
|
||||
|
||||
return (
|
||||
<>
|
||||
<div style={{
|
||||
position: "relative",
|
||||
overflow: "hidden",
|
||||
width: '100%',
|
||||
paddingTop: `${ratio*100}%`
|
||||
}}>
|
||||
<iframe width="100%" height="100%" src={url.toString()}
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
border: "none"
|
||||
}}
|
||||
></iframe>
|
||||
</div>
|
||||
<div style={{ fontSize: "80%", opacity: 0.7, marginTop: "0.2rem", marginBottom: "1rem", textAlign: "center" }}>If you're having issues viewing it inline, <a href={url.toString()} target="_blank">try in a new tab</a>.</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -12,9 +12,21 @@ the dependencies.
|
||||
</Note>
|
||||
|
||||
## Database
|
||||
### SQLite in-memory
|
||||
The easiest to get started is using SQLite in-memory. When serving the API in the "Integrations",
|
||||
the function accepts an object with connection details. To use an in-memory database, you can either omit the object completely or explicitly use it as follows:
|
||||
```json
|
||||
{
|
||||
"type": "libsql",
|
||||
"config": {
|
||||
"url": ":memory:"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### SQLite as file
|
||||
The easiest to get started is using SQLite as a file. When serving the API in the "Integrations",
|
||||
the function accepts an object with connection details. To use a file, use the following:
|
||||
Just like the in-memory option, using a file is just as easy:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "libsql",
|
||||
@@ -156,11 +168,11 @@ const { data: posts } = await api.data.readMany("posts", {})
|
||||
// `posts` is now typed as Database["posts"]
|
||||
```
|
||||
|
||||
The type completion is available for the API as well as all provided [React hooks](/react).
|
||||
The type completion is available for the API as well as all provided [React hooks](/usage/react).
|
||||
|
||||
### Seeding the database
|
||||
To seed your database with initial data, you can pass a `seed` function to the configuration. It
|
||||
provides the `ModuleBuildContext` ([reference](/setup/introduction#modulebuildcontext)) as the first argument.
|
||||
provides the `ModuleBuildContext` ([reference](/usage/introduction#modulebuildcontext)) as the first argument.
|
||||
|
||||
Note that the seed function will only be executed on app's first boot. If a configuration
|
||||
already exists in the database, it will not be executed.
|
||||
25
docs/usage/elements.mdx
Normal file
25
docs/usage/elements.mdx
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
title: "React Elements"
|
||||
description: "Speed up your frontend development"
|
||||
---
|
||||
|
||||
<Note>
|
||||
The documentation is currently a work in progress and not complete.
|
||||
</Note>
|
||||
|
||||
|
||||
Not only creating and maintaing a backend is time-consuming, but also integrating it into your frontend can be a hassle. With `bknd/elements`, you can easily add media uploads and authentication forms to your app without having to figure out API details.
|
||||
|
||||
## Media uploads
|
||||
|
||||
```tsx
|
||||
import { Media } from "bknd/elements"
|
||||
|
||||
export function UserAvatar() {
|
||||
return <Media.Dropzone
|
||||
entity={{ name: "users", id: 1, field: "avatar" }}
|
||||
maxItems={1}
|
||||
overwrite
|
||||
/>
|
||||
}
|
||||
```
|
||||
@@ -4,7 +4,7 @@ description: 'Setting up bknd'
|
||||
---
|
||||
|
||||
There are several methods to get **bknd** up and running. You can choose between these options:
|
||||
1. [Run it using the CLI](/cli): That's the easiest and fastest way to get started.
|
||||
1. [Run it using the CLI](/usage/cli): That's the easiest and fastest way to get started.
|
||||
2. Use a runtime like [Node](/integration/node), [Bun](/integration/bun) or
|
||||
[Cloudflare](/integration/cloudflare) (workerd). This will run the API and UI in the runtime's
|
||||
native server and serves the UI assets statically from `node_modules`.
|
||||
@@ -78,7 +78,7 @@ const connection = {
|
||||
```
|
||||
|
||||
Alternatively, you can pass an instance of a `Connection` class directly,
|
||||
see [Custom Connection](/setup/database#custom-connection) as a reference.
|
||||
see [Custom Connection](/usage/database#custom-connection) as a reference.
|
||||
|
||||
If the connection object is omitted, the app will try to use an in-memory database.
|
||||
|
||||
@@ -160,7 +160,7 @@ To validate your configuration against a JSON schema, you can also dump the sche
|
||||
npx bknd schema
|
||||
```
|
||||
|
||||
To create an initial data structure, you can use helpers [described here](/setup/database#initial-structure).
|
||||
To create an initial data structure, you can use helpers [described here](/usage/database#initial-structure).
|
||||
|
||||
### `plugins`
|
||||
The `plugins` property is an array of functions that are called after the app has been built,
|
||||
@@ -3,10 +3,15 @@ title: 'SDK (React)'
|
||||
description: 'Use the bknd SDK for React'
|
||||
---
|
||||
|
||||
For all SDK options targeting React, you always have 2 options:
|
||||
1. use simple hooks which are solely based on the [API](/sdk)
|
||||
2. use the query hook that makes wraps the API in [SWR](https://swr.vercel.app/)
|
||||
bknd exports 4 useful hooks to work with your backend:
|
||||
1. simple hooks which are solely based on the [API](/usage/sdk):
|
||||
- [`useApi`](#useapi)
|
||||
- [`useEntity`](#useentity)
|
||||
2. query hooks that wraps the API in [SWR](https://swr.vercel.app/):
|
||||
- [`useApiQuery`](#useapiquery)
|
||||
- [`useEntityQuery`](#useentityquery)
|
||||
|
||||
## `useApi()`
|
||||
To use the simple hook that returns the Api, you can use:
|
||||
```tsx
|
||||
import { useApi } from "bknd/client";
|
||||
@@ -17,7 +22,7 @@ export default function App() {
|
||||
}
|
||||
```
|
||||
|
||||
## `useApiQuery([selector], [options])`
|
||||
## `useApiQuery()`
|
||||
This hook wraps the API class in an SWR hook for convenience. You can use any API endpoint
|
||||
supported, like so:
|
||||
```tsx
|
||||
@@ -41,12 +46,12 @@ export default function App() {
|
||||
|
||||
* `options`: optional object that inherits from `SWRConfiguration`
|
||||
|
||||
```ts
|
||||
type Options<Data> = SWRConfiguration & {
|
||||
enabled?: boolean;
|
||||
refine?: (data: Data) => Data | any;
|
||||
}
|
||||
```
|
||||
```ts
|
||||
type Options <Data> = import("swr").SWRConfiguration & {
|
||||
enabled? : boolean;
|
||||
refine? : (data: Data) => Data | any;
|
||||
}
|
||||
```
|
||||
|
||||
* `enabled`: Determines whether this hook should trigger a fetch of the data or not.
|
||||
* `refine`: Optional refinement that is called after a response from the API has been
|
||||
@@ -58,7 +63,7 @@ following example we'll also use a `refine` function as well as `revalidateOnFoc
|
||||
`SWRConfiguration`) so that our data keeps updating on window focus change.
|
||||
|
||||
```tsx
|
||||
import { useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useApiQuery } from "bknd/client";
|
||||
|
||||
export default function App() {
|
||||
@@ -108,7 +113,7 @@ export default function App() {
|
||||
## `useEntity()`
|
||||
This hook wraps the endpoints of `DataApi` and returns CRUD options as parameters:
|
||||
```tsx
|
||||
import { useState } from "react",
|
||||
import { useState, useEffect } from "react";
|
||||
import { useEntity } from "bknd/client";
|
||||
|
||||
export default function App() {
|
||||
@@ -144,7 +149,6 @@ optional. Deletes the given entry.
|
||||
This hook wraps the actions from `useEntity` around `SWR`. The previous example would look like
|
||||
this:
|
||||
```tsx
|
||||
import { useState } from "react",
|
||||
import { useEntityQuery } from "bknd/client";
|
||||
|
||||
export default function App() {
|
||||
@@ -158,7 +162,7 @@ export default function App() {
|
||||
All actions returned from `useEntityQuery` are conveniently wrapped around the `mutate` function,
|
||||
so you don't have think about this:
|
||||
```tsx
|
||||
import { useState } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useEntityQuery } from "bknd/client";
|
||||
|
||||
export default function App() {
|
||||
@@ -10,6 +10,9 @@ import { Api } from "bknd";
|
||||
const api = new Api({
|
||||
host: "..." // point to your bknd instance
|
||||
});
|
||||
|
||||
// make sure to verify auth
|
||||
await api.verifyAuth();
|
||||
```
|
||||
|
||||
The `Api` class is the main entry point for interacting with the bknd API. It provides methods
|
||||
Reference in New Issue
Block a user