mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 04:27:21 +00:00
update cloudflare-vite-code readme to reflect code-only mode
The template documentation now emphasizes code-first approach with manual type management instead of automatic file generation. Includes updated configuration examples, deployment instructions, and a new comparison table between code and hybrid modes.
This commit is contained in:
@@ -1,18 +1,18 @@
|
|||||||
# bknd starter: Cloudflare Vite Hybrid
|
# bknd starter: Cloudflare Vite Code-Only
|
||||||
A fullstack React + Vite application with bknd integration, showcasing **hybrid mode** and Cloudflare Workers deployment.
|
A fullstack React + Vite application with bknd integration, showcasing **code-only mode** and Cloudflare Workers deployment.
|
||||||
|
|
||||||
## Key Features
|
## Key Features
|
||||||
|
|
||||||
This example demonstrates several advanced bknd features:
|
This example demonstrates a minimal, code-first approach to building with bknd:
|
||||||
|
|
||||||
### 🔄 Hybrid Mode
|
### 💻 Code-Only Mode
|
||||||
Configure your backend **visually in development** using the Admin UI, then automatically switch to **code-only mode in production** for maximum performance. Changes made in the Admin UI are automatically synced to `bknd-config.json` and type definitions are generated in `bknd-types.d.ts`.
|
Define your entire backend **programmatically** using a Drizzle-like API. Your data structure, authentication, and configuration live directly in code with zero build-time tooling required. Perfect for developers who prefer traditional code-first workflows.
|
||||||
|
|
||||||
### 📁 Filesystem Access with Vite Plugin
|
### 🎯 Minimal Boilerplate
|
||||||
Cloudflare's Vite plugin uses `unenv` which disables Node.js APIs like `fs`. This example uses bknd's `devFsVitePlugin` and `devFsWrite` to provide filesystem access during development, enabling automatic syncing of types and configuration.
|
Unlike the hybrid mode template, this example uses **no automatic type generation**, **no filesystem plugins**, and **no auto-synced configuration files**. This simulates a typical development environment where you manage types generation manually. If you prefer automatic type generation, you can easily add it using the [CLI](https://docs.bknd.io/usage/cli#generating-types-types) or [Vite plugin](https://docs.bknd.io/extending/plugins#synctypes).
|
||||||
|
|
||||||
### ⚡ Split Configuration Pattern
|
### ⚡ Split Configuration Pattern
|
||||||
- **`config.ts`**: Shared configuration that can be safely imported in your worker
|
- **`config.ts`**: Main configuration that defines your schema and can be safely imported in your worker
|
||||||
- **`bknd.config.ts`**: Wraps the configuration with `withPlatformProxy` for CLI usage with Cloudflare bindings (should NOT be imported in your worker)
|
- **`bknd.config.ts`**: Wraps the configuration with `withPlatformProxy` for CLI usage with Cloudflare bindings (should NOT be imported in your worker)
|
||||||
|
|
||||||
This pattern prevents bundling `wrangler` into your worker while still allowing CLI access to Cloudflare resources.
|
This pattern prevents bundling `wrangler` into your worker while still allowing CLI access to Cloudflare resources.
|
||||||
@@ -32,67 +32,84 @@ Inside of your project, you'll see the following folders and files:
|
|||||||
│ │ └── main.tsx
|
│ │ └── main.tsx
|
||||||
│ └── worker/
|
│ └── worker/
|
||||||
│ └── index.ts # Cloudflare Worker entry
|
│ └── index.ts # Cloudflare Worker entry
|
||||||
├── config.ts # Shared bknd configuration (hybrid mode)
|
├── config.ts # bknd configuration with schema definition
|
||||||
├── bknd.config.ts # CLI configuration with platform proxy
|
├── bknd.config.ts # CLI configuration with platform proxy
|
||||||
├── bknd-config.json # Auto-generated production config
|
├── seed.ts # Optional: seed data for development
|
||||||
├── bknd-types.d.ts # Auto-generated TypeScript types
|
├── vite.config.ts # Standard Vite config (no bknd plugins)
|
||||||
├── .env.example # Auto-generated secrets template
|
|
||||||
├── vite.config.ts # Includes devFsVitePlugin
|
|
||||||
├── package.json
|
├── package.json
|
||||||
└── wrangler.json # Cloudflare Workers configuration
|
└── wrangler.json # Cloudflare Workers configuration
|
||||||
```
|
```
|
||||||
|
|
||||||
## Cloudflare resources
|
## Cloudflare Resources
|
||||||
|
|
||||||
- **D1:** `wrangler.json` declares a `DB` binding. In production, replace `database_id` with your own (`wrangler d1 create <name>`).
|
- **D1:** `wrangler.json` declares a `DB` binding. In production, replace `database_id` with your own (`wrangler d1 create <name>`).
|
||||||
- **R2:** Optional `BUCKET` binding is pre-configured to show how to add additional services.
|
- **R2:** Optional `BUCKET` binding is pre-configured to show how to add additional services.
|
||||||
- **Environment awareness:** `ENVIRONMENT` switch toggles hybrid behavior: production makes the database read-only, while development keeps `mode: "db"` and auto-syncs schema.
|
- **Environment awareness:** `ENVIRONMENT` variable determines whether to sync the database schema automatically (development only).
|
||||||
- **Static assets:** The Assets binding points to `dist/client`. Run `npm run build` before `wrangler deploy` to upload the client bundle alongside the worker.
|
- **Static assets:** The Assets binding points to `dist/client`. Run `npm run build` before `wrangler deploy` to upload the client bundle alongside the worker.
|
||||||
|
|
||||||
## Admin UI & frontend
|
## Admin UI & Frontend
|
||||||
|
|
||||||
- `/admin` mounts `<Admin />` from `bknd/ui` with `withProvider={{ user }}` so it respects the authenticated user returned by `useAuth`.
|
- `/admin` mounts `<Admin />` from `bknd/ui` with `withProvider={{ user }}` so it respects the authenticated user returned by `useAuth`.
|
||||||
- `/` showcases `useEntityQuery("todos")`, mutation helpers, and authentication state — demonstrating how the generated client types (`bknd-types.d.ts`) flow into the React code.
|
- `/` showcases `useEntityQuery("todos")`, mutation helpers, and authentication state — demonstrating how manually declared types flow into the React code.
|
||||||
|
|
||||||
|
|
||||||
## Configuration Files
|
## Configuration Files
|
||||||
|
|
||||||
### `config.ts`
|
### `config.ts`
|
||||||
The main configuration file that uses the `hybrid()` mode helper:
|
The main configuration file that uses the `code()` mode helper:
|
||||||
|
|
||||||
- Loads the generated config via an ESM `reader` (importing `./bknd-config.json`).
|
|
||||||
- Uses `devFsWrite` as the `writer` so the CLI/plugin can persist files even though Node's `fs` API is unavailable in Miniflare.
|
|
||||||
- Sets `typesFilePath`, `configFilePath`, and `syncSecrets` (writes `.env.example`) so config, types, and secret placeholders stay aligned.
|
|
||||||
- Seeds example data/users in `options.seed` when the database is empty.
|
|
||||||
- Disables the built-in admin controller because the React app renders `/admin` via `bknd/ui`.
|
|
||||||
|
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { hybrid } from "bknd/modes";
|
import type { CloudflareBkndConfig } from "bknd/adapter/cloudflare";
|
||||||
import { devFsWrite, type CloudflareBkndConfig } from "bknd/adapter/cloudflare";
|
import { code } from "bknd/modes";
|
||||||
|
import { boolean, em, entity, text } from "bknd";
|
||||||
|
|
||||||
export default hybrid<CloudflareBkndConfig>({
|
// define your schema using a Drizzle-like API
|
||||||
// Special reader for Cloudflare Workers (no Node.js fs)
|
const schema = em({
|
||||||
reader: async () => (await import("./bknd-config.json")).default,
|
todos: entity("todos", {
|
||||||
// devFsWrite enables file writing via Vite plugin
|
title: text(),
|
||||||
writer: devFsWrite,
|
done: boolean(),
|
||||||
// Auto-sync these files in development
|
}),
|
||||||
typesFilePath: "./bknd-types.d.ts",
|
});
|
||||||
configFilePath: "./bknd-config.json",
|
|
||||||
syncSecrets: {
|
// register your schema for type completion (optional)
|
||||||
enabled: true,
|
// alternatively, you can use the CLI to auto-generate types
|
||||||
outFile: ".env.example",
|
type Database = (typeof schema)["DB"];
|
||||||
format: "env",
|
declare module "bknd" {
|
||||||
},
|
interface DB extends Database {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default code<CloudflareBkndConfig>({
|
||||||
app: (env) => ({
|
app: (env) => ({
|
||||||
adminOptions: false, // Disabled - we render React app instead
|
config: {
|
||||||
|
// convert schema to JSON format
|
||||||
|
data: schema.toJSON(),
|
||||||
|
auth: {
|
||||||
|
enabled: true,
|
||||||
|
jwt: {
|
||||||
|
// secrets are directly passed to the config
|
||||||
|
secret: env.JWT_SECRET,
|
||||||
|
issuer: "cloudflare-vite-code-example",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// disable the built-in admin controller (we render our own app)
|
||||||
|
adminOptions: false,
|
||||||
|
// determines whether the database should be automatically synced
|
||||||
isProduction: env.ENVIRONMENT === "production",
|
isProduction: env.ENVIRONMENT === "production",
|
||||||
secrets: env,
|
|
||||||
// ... your configuration
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Key differences from hybrid mode:
|
||||||
|
- **No auto-generated files**: No `bknd-config.json`, `bknd-types.d.ts`, or `.env.example`
|
||||||
|
- **Manual type declaration**: Types are declared inline using `declare module "bknd"`
|
||||||
|
- **Direct secret access**: Secrets come directly from `env` parameters
|
||||||
|
- **Simpler setup**: No filesystem plugins or readers/writers needed
|
||||||
|
|
||||||
|
If you prefer automatic type generation, you can add it later using:
|
||||||
|
- **CLI**: `npm run bknd -- types` (requires adding `typesFilePath` to config)
|
||||||
|
- **Plugin**: Import `syncTypes` plugin and configure it in your app
|
||||||
|
|
||||||
### `bknd.config.ts`
|
### `bknd.config.ts`
|
||||||
Wraps the configuration for CLI usage with Cloudflare bindings:
|
Wraps the configuration for CLI usage with Cloudflare bindings:
|
||||||
|
|
||||||
@@ -100,21 +117,24 @@ Wraps the configuration for CLI usage with Cloudflare bindings:
|
|||||||
import { withPlatformProxy } from "bknd/adapter/cloudflare/proxy";
|
import { withPlatformProxy } from "bknd/adapter/cloudflare/proxy";
|
||||||
import config from "./config.ts";
|
import config from "./config.ts";
|
||||||
|
|
||||||
export default withPlatformProxy(config);
|
export default withPlatformProxy(config, {
|
||||||
|
useProxy: true,
|
||||||
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Important**: Don't import this file in your worker, as it would bundle `wrangler` into your production code. This file is only used by the bknd CLI.
|
||||||
|
|
||||||
### `vite.config.ts`
|
### `vite.config.ts`
|
||||||
Includes the `devFsVitePlugin` for filesystem access:
|
Standard Vite configuration without bknd-specific plugins:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { devFsVitePlugin } from "bknd/adapter/cloudflare";
|
import { defineConfig } from "vite";
|
||||||
|
import react from "@vitejs/plugin-react";
|
||||||
|
import { cloudflare } from "@cloudflare/vite-plugin";
|
||||||
|
import tailwindcss from "@tailwindcss/vite";
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [
|
plugins: [react(), tailwindcss(), cloudflare()],
|
||||||
// ...
|
|
||||||
devFsVitePlugin({ configFile: "config.ts" }),
|
|
||||||
cloudflare(),
|
|
||||||
],
|
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -124,13 +144,13 @@ All commands are run from the root of the project, from a terminal:
|
|||||||
|
|
||||||
| Command | Action |
|
| Command | Action |
|
||||||
|:-------------------|:----------------------------------------------------------|
|
|:-------------------|:----------------------------------------------------------|
|
||||||
| `npm install` | Installs dependencies and generates wrangler types |
|
| `npm install` | Installs dependencies, generates types, and seeds database|
|
||||||
| `npm run dev` | Starts local dev server with Vite at `localhost:5173` |
|
| `npm run dev` | Starts local dev server with Vite at `localhost:5173` |
|
||||||
| `npm run build` | Builds the application for production |
|
| `npm run build` | Builds the application for production |
|
||||||
| `npm run preview` | Builds and previews the production build locally |
|
| `npm run preview` | Builds and previews the production build locally |
|
||||||
| `npm run deploy` | Builds, syncs the schema and deploys to Cloudflare Workers|
|
| `npm run deploy` | Builds, syncs the schema and deploys to Cloudflare Workers|
|
||||||
| `npm run bknd` | Runs bknd CLI commands |
|
| `npm run bknd` | Runs bknd CLI commands |
|
||||||
| `npm run bknd:types` | Generates TypeScript types from your schema |
|
| `npm run bknd:seed`| Seeds the database with example data |
|
||||||
| `npm run cf:types` | Generates Cloudflare Worker types from `wrangler.json` |
|
| `npm run cf:types` | Generates Cloudflare Worker types from `wrangler.json` |
|
||||||
| `npm run check` | Type checks and does a dry-run deployment |
|
| `npm run check` | Type checks and does a dry-run deployment |
|
||||||
|
|
||||||
@@ -140,41 +160,58 @@ All commands are run from the root of the project, from a terminal:
|
|||||||
```sh
|
```sh
|
||||||
npm install
|
npm install
|
||||||
```
|
```
|
||||||
|
This will install dependencies, generate Cloudflare types, and seed the database.
|
||||||
|
|
||||||
2. **Start development server:**
|
2. **Start development server:**
|
||||||
```sh
|
```sh
|
||||||
npm run dev
|
npm run dev
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **Visit the Admin UI** at `http://localhost:5173/admin` to configure your backend visually:
|
3. **Define your schema in code** (`config.ts`):
|
||||||
- Create entities and fields
|
```typescript
|
||||||
- Configure authentication
|
const schema = em({
|
||||||
- Set up relationships
|
todos: entity("todos", {
|
||||||
- Define permissions
|
title: text(),
|
||||||
|
done: boolean(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
4. **Watch for auto-generated files:**
|
4. **Manually declare types** (optional, but recommended for IDE support):
|
||||||
- `bknd-config.json` - Production configuration
|
```typescript
|
||||||
- `bknd-types.d.ts` - TypeScript types
|
type Database = (typeof schema)["DB"];
|
||||||
- `.env.example` - Required secrets
|
declare module "bknd" {
|
||||||
|
interface DB extends Database {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
5. **Use the CLI** for manual operations:
|
5. **Use the Admin UI** at `http://localhost:5173/admin` to:
|
||||||
```sh
|
- View and manage your data
|
||||||
# Generate types manually
|
- Monitor authentication
|
||||||
npm run bknd:types
|
- Access database tools
|
||||||
|
|
||||||
# Sync the production database schema (only safe operations are applied)
|
Note: In code mode, you cannot edit the schema through the UI. All schema changes must be done in `config.ts`.
|
||||||
|
|
||||||
|
6. **Sync schema changes** to your database:
|
||||||
|
```sh
|
||||||
|
# Local development (happens automatically on startup)
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# Production database (safe operations only)
|
||||||
CLOUDFLARE_ENV=production npm run bknd -- sync --force
|
CLOUDFLARE_ENV=production npm run bknd -- sync --force
|
||||||
```
|
```
|
||||||
|
|
||||||
## Before you deploy
|
## Before You Deploy
|
||||||
|
|
||||||
If you're using a D1 database, make sure to create a database in your Cloudflare account and replace the `database_id` accordingly in `wrangler.json`:
|
### 1. Create a D1 Database
|
||||||
|
|
||||||
|
Create a database in your Cloudflare account:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
npx wrangler d1 create my-database
|
npx wrangler d1 create my-database
|
||||||
```
|
```
|
||||||
|
|
||||||
Update `wrangler.json`:
|
Update `wrangler.json` with your database ID:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"d1_databases": [
|
"d1_databases": [
|
||||||
@@ -187,6 +224,21 @@ Update `wrangler.json`:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 2. Set Required Secrets
|
||||||
|
|
||||||
|
Set your secrets in Cloudflare Workers:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# JWT secret (required for authentication)
|
||||||
|
npx wrangler secret put JWT_SECRET
|
||||||
|
```
|
||||||
|
|
||||||
|
You can generate a secure secret using:
|
||||||
|
```sh
|
||||||
|
# Using openssl
|
||||||
|
openssl rand -base64 64
|
||||||
|
```
|
||||||
|
|
||||||
## Deployment
|
## Deployment
|
||||||
|
|
||||||
Deploy to Cloudflare Workers:
|
Deploy to Cloudflare Workers:
|
||||||
@@ -196,54 +248,101 @@ npm run deploy
|
|||||||
```
|
```
|
||||||
|
|
||||||
This will:
|
This will:
|
||||||
1. Set `ENVIRONMENT=production` to activate code-only mode
|
1. Set `ENVIRONMENT=production` to prevent automatic schema syncing
|
||||||
2. Build the Vite application
|
2. Build the Vite application
|
||||||
3. Deploy to Cloudflare Workers using Wrangler
|
3. Sync the database schema (safe operations only)
|
||||||
|
4. Deploy to Cloudflare Workers using Wrangler
|
||||||
|
|
||||||
In production, bknd will:
|
In production, bknd will:
|
||||||
- Use the configuration from `bknd-config.json` (read-only)
|
- Use the configuration defined in `config.ts`
|
||||||
- Skip config validation for better performance
|
- Skip config validation for better performance
|
||||||
- Expect secrets to be provided via environment variables
|
- Expect secrets to be provided via environment variables
|
||||||
|
|
||||||
## Environment Variables
|
## How Code Mode Works
|
||||||
|
|
||||||
Make sure to set your secrets in the Cloudflare Workers dashboard or via Wrangler:
|
1. **Define Schema:** Create entities and fields using the Drizzle-like API in `config.ts`
|
||||||
|
2. **Convert to JSON:** Use `schema.toJSON()` to convert your schema to bknd's configuration format
|
||||||
|
3. **Manual Types:** Optionally declare types inline for IDE support and type safety
|
||||||
|
4. **Deploy:** Same configuration runs in both development and production
|
||||||
|
|
||||||
|
### Code Mode vs Hybrid Mode
|
||||||
|
|
||||||
|
| Feature | Code Mode | Hybrid Mode |
|
||||||
|
|---------|-----------|-------------|
|
||||||
|
| Schema Definition | Code-only (`em`, `entity`, `text`) | Visual UI in dev, code in prod |
|
||||||
|
| Configuration Files | None (all in code) | Auto-generated `bknd-config.json` |
|
||||||
|
| Type Generation | Manual or opt-in | Automatic |
|
||||||
|
| Setup Complexity | Minimal | Requires plugins & filesystem access |
|
||||||
|
| Use Case | Traditional code-first workflows | Rapid prototyping, visual development |
|
||||||
|
|
||||||
|
## Type Generation (Optional)
|
||||||
|
|
||||||
|
This example intentionally **does not use automatic type generation** to simulate a typical development environment where types are managed manually. This approach:
|
||||||
|
- Reduces build complexity
|
||||||
|
- Eliminates dependency on build-time tooling
|
||||||
|
- Works in any environment without special plugins
|
||||||
|
|
||||||
|
However, if you prefer automatic type generation, you can easily add it:
|
||||||
|
|
||||||
|
### Option 1: Using the Vite Plugin and `code` helper presets
|
||||||
|
Add `typesFilePath` to your config:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export default code({
|
||||||
|
typesFilePath: "./bknd-types.d.ts",
|
||||||
|
// ... rest of config
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
For Cloudflare Workers, you'll need the `devFsVitePlugin`:
|
||||||
|
```typescript
|
||||||
|
// vite.config.ts
|
||||||
|
import { devFsVitePlugin } from "bknd/adapter/cloudflare";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [
|
||||||
|
// ...
|
||||||
|
devFsVitePlugin({ configFile: "config.ts" })
|
||||||
|
],
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, add the generated types to your `tsconfig.json`:
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"types": ["./bknd-types.d.ts"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This provides filesystem access for auto-syncing types despite Cloudflare's `unenv` restrictions.
|
||||||
|
|
||||||
|
### Option 2: Using the CLI
|
||||||
|
|
||||||
|
You may also use the CLI to generate types:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
# Example: Set JWT secret
|
npx bknd types --outfile ./bknd-types.d.ts
|
||||||
npx wrangler secret put auth.jwt.secret
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Check `.env.example` for all required secrets after running the app in development mode.
|
## Database Seeding
|
||||||
|
|
||||||
## How Hybrid Mode Works
|
Unlike UI-only and hybrid modes where bknd can automatically detect an empty database (by attempting to fetch the configuration. A "table not found" error indicates a fresh database), **code mode requires manual seeding**. This is because in code mode, the configuration is always provided from code, so bknd can't determine if the database is empty without additional queries, which would impact performance.
|
||||||
|
|
||||||
```mermaid
|
This example includes a [`seed.ts`](./seed.ts) file that you can run manually. For Cloudflare, it uses `bknd.config.ts` (with `withPlatformProxy`) to access Cloudflare resources like D1 during CLI execution:
|
||||||
graph LR
|
|
||||||
A[Development] -->|Visual Config| B[Admin UI]
|
```sh
|
||||||
B -->|Auto-sync| C[bknd-config.json]
|
npm run bknd:seed
|
||||||
B -->|Auto-sync| D[bknd-types.d.ts]
|
|
||||||
C -->|Deploy| E[Production]
|
|
||||||
E -->|Read-only| F[Code-only Mode]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
1. **In Development:** `mode: "db"` - Configuration stored in database, editable via Admin UI
|
The seed script manually checks if the database is empty before inserting data. See the [seed.ts](./seed.ts) file for implementation details.
|
||||||
2. **Auto-sync:** Changes automatically written to `bknd-config.json` and types to `bknd-types.d.ts`
|
|
||||||
3. **In Production:** `mode: "code"` - Configuration read from `bknd-config.json`, no database overhead
|
|
||||||
|
|
||||||
## Why devFsVitePlugin?
|
## Want to Learn More?
|
||||||
|
|
||||||
Cloudflare's Vite plugin removes Node.js APIs for Workers compatibility. This breaks filesystem operations needed for:
|
|
||||||
- Auto-syncing TypeScript types (`syncTypes` plugin)
|
|
||||||
- Auto-syncing configuration (`syncConfig` plugin)
|
|
||||||
- Auto-syncing secrets (`syncSecrets` plugin)
|
|
||||||
|
|
||||||
The `devFsVitePlugin` + `devFsWrite` combination provides a workaround by using Vite's module system to enable file writes during development.
|
|
||||||
|
|
||||||
## Want to learn more?
|
|
||||||
|
|
||||||
- [Cloudflare Integration Documentation](https://docs.bknd.io/integration/cloudflare)
|
- [Cloudflare Integration Documentation](https://docs.bknd.io/integration/cloudflare)
|
||||||
- [Hybrid Mode Guide](https://docs.bknd.io/usage/introduction#hybrid-mode)
|
- [Code Mode Guide](https://docs.bknd.io/usage/introduction#code-only-mode)
|
||||||
- [Mode Helpers Documentation](https://docs.bknd.io/usage/introduction#mode-helpers)
|
- [Mode Helpers Documentation](https://docs.bknd.io/usage/introduction#mode-helpers)
|
||||||
|
- [Data Structure & Schema API](https://docs.bknd.io/usage/database#data-structure)
|
||||||
- [Discord Community](https://discord.gg/952SFk8Tb8)
|
- [Discord Community](https://discord.gg/952SFk8Tb8)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user