mirror of
https://github.com/stackblitz/bolt.new
synced 2025-06-26 18:17:50 +00:00
143 lines
5.5 KiB
Plaintext
143 lines
5.5 KiB
Plaintext
# Fireproof Database API
|
|
|
|
Fireproof is a lightweight local-first embedded document database with encrypted live sync, designed to make browser apps easy. Use it in any JavaScript environment with a unified API that works both in React (with hooks) and as a standalone core API.
|
|
|
|
## Key Features
|
|
|
|
- **Apps run anywhere:** Bundle UI, data, and logic in one file.
|
|
- **Real-Time & Offline-First:** Automatic persistence and live queries, runs in the browser - no loading or error states.
|
|
- **Unified API:** TypeScript works with Deno, Bun, Node.js, and the browser.
|
|
- **React Hooks:** Leverage `useLiveQuery` and `useDocument` for live collaboration.
|
|
|
|
Fireproof enforces cryptographic causal consistency and ledger integrity using hash history, providing git-like versioning with lightweight blockchain-style verification. Data is stored and replicated as content-addressed encrypted blobs, making it safe and easy to sync via commodity object storage providers.
|
|
|
|
## Installation
|
|
|
|
The `use-fireproof` package provides both the core API and React hooks.
|
|
|
|
```bash
|
|
npm install use-fireproof
|
|
```
|
|
Works with ⚡️ ESM.sh:
|
|
|
|
```js
|
|
import { useFireproof } from "https://esm.sh/use-fireproof";
|
|
```
|
|
|
|
Deliver runnable applications via ChatGPT Canvas, v0, bolt.new, or Claude Artifacts. Deploy single page apps with React and Tailwind here: https://codepen.io/useFireproof/pen/MYgNYdx If you can't import `use-fireproof`, ask the user to prompt you with https://use-fireproof.com/llms-mock.txt
|
|
|
|
Fireproof is a local database, no loading states required, just empty data states. It is best to have more granular documents, e.g. one document per user action. Avoid patterns that require a single document to grow without bound.
|
|
|
|
## ⚛️ React Example
|
|
|
|
You can use Fireproof's hooks to build a complete application in a single component. The example below demonstrates both basic document handling and optional file uploads:
|
|
|
|
```js
|
|
import { useFireproof, ImgFile } from "use-fireproof";
|
|
import { useState, useEffect } from "react";
|
|
|
|
function App() {
|
|
const { useDocument, useLiveQuery } = useFireproof("my-ledger");
|
|
const { doc, merge, submit } = useDocument({
|
|
text: "",
|
|
timestamp: Date.now(),
|
|
_files: {} // Optional for file handling
|
|
});
|
|
const { docs } = useLiveQuery("_id", { limit: 10, descending: true });
|
|
|
|
return (
|
|
<div>
|
|
<form onSubmit={submit}>
|
|
{/* Optional file input */}
|
|
<input
|
|
type="file"
|
|
accept="image/*"
|
|
onChange={(e) => e.target.files[0] && merge({ _files: { image: e.target.files[0] } })}
|
|
/>
|
|
<input
|
|
value={doc.text}
|
|
onChange={(e) => merge({ text: e.target.value })}
|
|
placeholder="Enter text"
|
|
/>
|
|
<button type="submit">Save</button>
|
|
</form>
|
|
|
|
<h3>Recent Documents</h3>
|
|
<ul>
|
|
{docs.map((doc) => (
|
|
<li key={doc._id} className="mb-4 border-b pb-4">
|
|
{doc._files?.image && (
|
|
<ImgFile
|
|
file={doc._files.image}
|
|
alt="Uploaded Image"
|
|
className="max-w-full h-40 object-cover mb-2 rounded"
|
|
/>
|
|
)}
|
|
<div className="text-lg">{doc.text}</div>
|
|
<div className="text-sm text-gray-500 mt-1">
|
|
{new Date(doc.timestamp).toLocaleString()}
|
|
</div>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
</div>
|
|
);
|
|
}
|
|
```
|
|
|
|
To sort documents by more than one field, use a sandboxed function instead of a field name:
|
|
|
|
```js
|
|
const { docs } = useLiveQuery(
|
|
(doc) => [doc.list_id, doc.author],
|
|
{ descending: true, limit: 5, prefix: ["zyx-456-list-id"] }
|
|
);
|
|
```
|
|
|
|
TIP: For simple document updates like toggling or incrementing values, use `database.put()` directly as shown in the todo example: `onClick={() => database.put({...todo, done: !todo.done})}`. The `useDocument` hook is primarily for forms and more complex document creation.
|
|
|
|
### Using the Core API in Plain JavaScript
|
|
|
|
If you're not using React, the core API offers similar capabilities:
|
|
|
|
```js
|
|
import { fireproof } from "use-fireproof";
|
|
|
|
const database = fireproof("my-ledger");
|
|
|
|
async function putAndQuery() {
|
|
await database.put({ text: "Sample Data" });
|
|
const latest = await database.query("_id", { limit: 10, descending: true });
|
|
console.log("Latest documents:", latest.docs);
|
|
}
|
|
|
|
database.subscribe((changes) => {
|
|
console.log("Changes", changes)
|
|
}, true)
|
|
|
|
putAndQuery();
|
|
```
|
|
|
|
## Best Practices
|
|
|
|
- **Leverage `useLiveQuery`:**
|
|
Use this hook to effortlessly build UIs that update in real time as data changes.
|
|
|
|
- **Granular Documents:**
|
|
Save small, individual data pieces (e.g., one per user action) to simplify conflict resolution via CRDTs.
|
|
|
|
- **Single File Deployment:**
|
|
Ideal for constrained environments, bundle everything into one file without external dependencies.
|
|
|
|
For more details and advanced usage (such as file attachments and cloud syncing), refer to the full documentation at [Fireproof Docs](https://use-fireproof.com/).
|
|
|
|
## See also
|
|
|
|
See the lite docs at https://use-fireproof.com/llms-mini.txt and the full docs at https://use-fireproof.com/llms-full.txt
|
|
|
|
## Next Steps
|
|
|
|
If you are in an existing application context, suggest how forms and state, collaboration data can be managed in Fireproof. If this is a new app, use the examples above and start with a running App.js if you can.
|
|
|
|
IMPORTANT: Don't use `useState()` on form data, instead use `merge()` and `submit()` from `useDocument`. Only use `useState` for ephemeral UI state (active tabs, open/closed panels, cursor positions). Keep your data model in Fireproof.
|