Library / SDK
fireproof-storage/fireproof avatar
fireproof-storage/fireproof

Fireproof keeps the whole ledger in the browser and syncs later

The vibe coding database runs in the browser, fits in the context window, and syncs anywhere.

979 stars58 forksTypeScriptApache-2.0

At a glance

What is it?
Fireproof is a TypeScript embedded document database with encrypted live sync, where the data, the query logic and the interface can all live in one file and run in the browser, with the same API in Deno, Bun, Node and React. Underneath it is a CRDT with a hash history, which gives it git-like versioning and a form of cryptographic verification without a server.
Who is it for?
Fireproof fits a team building a browser first application, especially a prototype generated by a coding model, where the same code has to run locally, on an edge runtime and in a browser, and where shipping a backend is the thing you want to postpone. It does not fit a workload that needs a server side authority for queries, and it does not fit a project that wants a relational model, since the unit of storage is a document.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 168 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The database is a library, not a service

Fireproof is described as a lightweight embedded document database with encrypted live sync, designed to make browser apps easy, and it is used in any JavaScript environment with a unified API that works both in React with hooks and as a standalone core API. The key feature list starts with the one that changes the architecture of an application. Apps run anywhere, because you bundle UI, data and logic in one file. Real-time and offline-first come next, with automatic persistence and live queries, running in the browser with no loading or error states to handle. The unified API point is that the TypeScript works with Deno, Bun, Node.js and the browser. The React hooks then give you useLiveQuery and useDocument for live collaboration. Put together, that is a description of a database you embed rather than a database you connect to, and the use cases listed make the intent explicit, from AI-generated apps and rapid prototypes to collaborative editing, offline and local-first apps, personalization, and AI copilot safety.

Two packages, depending on whether you want hooks

Installation splits into two packages depending on how you intend to use it. The use-fireproof package provides both the core API and the React hooks, and it is installed from npm in one step:

sh
npm install use-fireproof

There is also a note that it works with ESM.sh, which matters for a tool that is aimed at generated code running in a browser without a build step:

js
import { useFireproof } from "https://esm.sh/use-fireproof";

If you want only the ledger, with no React dependency, the core package is installed separately:

sh
npm install @fireproof/core

And for a plain web page with no bundler at all, the core build is available as a global script, where the global name is Fireproof:

html
<script src="https://cdn.jsdelivr.net/npm/@fireproof/core/dist/browser/fireproof.global.js"></script>

Three installation routes for three levels of build complexity is a deliberate choice for a project whose stated context is code generation, and the README also points at runnable micro applications delivered through ChatGPT Canvas, v0, bolt.new or Claude Artifacts, with a React and Tailwind single page app template on CodePen.

The core API is put, query, subscribe and get

The document database API is deliberately familiar to anyone who has used another document database, and it is short enough to read in one go:

js
import { fireproof } from "@fireproof/core";

const db = fireproof("music-app");

await db.put({ _id: "beyonce", name: "Beyoncé", hitSingles: 29 });

db.subscribe(async () => {
  const topArtists = await db.query("hitSingles", { range: [30, Infinity] });
  // redraw the UI with the new topArtists
});

const beyonceDoc = await db.get("beyonce");
beyonceDoc.hitSingles += 1;
await db.put(beyonceDoc);

Four operations carry the model. A document is written with put, read with get, and the interesting one is query with a range on a field, which is how the subscription finds every artist with thirty or more hit singles. The subscribe call is the live part, since the callback fires whenever the data changes and re-runs the query so the interface can redraw. The read-modify-write on the document shows the concurrency model, because the document is read, mutated and written back, and the merge of concurrent edits is the job of the CRDT underneath rather than of the application.

React hooks for a document and a live query

React hooks are the recommended way to use Fireproof in code generation contexts, and the shape is a single hook that returns the pieces you need. The setup and the two hook calls fit in a few lines:

js
import { useFireproof } from "use-fireproof";

function App() {
  const { database, useLiveQuery, useDocument } = useFireproof("my-ledger");

  // Create a new document with useDocument
  const { doc, merge, submit } = useDocument({ text: "" });

  // Query documents by _id, most recent first
  const { docs } = useLiveQuery("_id", { descending: true, limit: 100 });

The ledger name is the argument to useFireproof, and it returns the database object alongside the hooks. The document hook takes an initial value and returns the document, a merge function and a submit function, so an input field onChange calls merge and the form submission calls submit, and the change is written when the user submits rather than on every keystroke. The live query hook takes a field name and options, here a descending order and a limit of a hundred, and returns the matching documents. The database object being returned alongside the hooks is what lets a component read or write outside the document it is bound to.

Images travel with the document

File storage is handled through a convention rather than a separate API, and the README explains that the _files property and the ImgFile component handle the complexities of file storage and retrieval. The upload side puts the file object into a document field alongside a timestamp:

js
// Store an image from a file input
function handleFileUpload(e) {
  if (e.target.files[0]) {
    merge({
      _files: { profilePic: e.target.files[0] },
      uploadedAt: new Date().toISOString(),
    });
  }
}

The display side reads it back with ImgFile, which automatically handles loading and displaying images from Fireproof's storage and takes the expected props of a standard image element, with an onLoad callback. The important thing about this arrangement is that the binary is not a separate service call. It is part of the document, so it is encrypted with the rest of the document, it is versioned with it, and it syncs with it, and the component hides the URL handling that would otherwise leak into the application code. The same document can therefore hold a profile picture and the fields describing it, which is what makes a personalisation or profile screen a single object rather than a join.

A hash history instead of a server

The reason section explains the integrity model in one dense paragraph, and it is the part to read before trusting the data. 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. The comparison list then gives the reasons to choose it over another embedded database, and each one is a design consequence rather than a slogan. Network aware, encrypted and multi-writer safe. Designed for real-time collaboration with CRDTs. Cryptographic causal integrity for all operations. Built for the web, with a small package size and no wasm. The last point is the interesting engineering constraint, since a wasm build would have been the easy way to reuse an existing database core, and the absence of it means the storage and sync logic is written in TypeScript. It also means the whole thing runs in a browser without a compiled binary to ship.

Tests are organised around storage gateways

The test story in the README is about breadth rather than depth. To run the full test suite across all projects, with the tested storage gateway configurations, the command is:

bash
pnpm run test

To narrow it down, you pass a name pattern and a file path, and the example given is a specific test for the CRDT module in a single project, with the debug output limited to two subsystems:

bash
FP_DEBUG='Loader,CRDTClock' pnpm run test --project file -t 'codec implict iv' crdt

The project selection is visible in the package scripts as well, with separate vitest configurations for file, indexeddb and deno targets, which is a good sign for a database that claims to run in the browser and on the server runtime. React components are tested with the same runner by pointing it at a test path. Debug output is controlled by the FP_DEBUG environment variable or by setting the debug level in code, with a module list or a wildcard, and in the browser the same thing can be done through a symbol key on the global object. The test suite runs against several storage backends, so the storage layer is the part of the codebase with the widest test surface.

Editorial conclusion

Fireproof fits a team building a browser first application, especially a prototype generated by a coding model, where the same code has to run locally, on an edge runtime and in a browser, and where shipping a backend is the thing you want to postpone. It does not fit a workload that needs a server side authority for queries, and it does not fit a project that wants a relational model, since the unit of storage is a document. Before you adopt it, read the architecture document linked from the documentation, because the sync and encryption story is where the design decisions live, try the core API in a plain script before wiring up React, and check the storage gateway you intend to use, since the test suite is organised around those configurations rather than around one backend.

Frequently asked questions

What is Fireproof?

It is a lightweight embedded document database with encrypted live sync, written in TypeScript, that runs in the browser, in Deno, in Bun and in Node, with React hooks for live queries and documents and a standalone core API.

How do I install Fireproof?

Use npm install use-fireproof for the package that includes the React hooks, or npm install @fireproof/core for the ledger alone, or load the core build from a CDN script tag where the global name is Fireproof.

How does Fireproof handle concurrent edits?

It uses CRDTs for real-time collaboration and enforces cryptographic causal consistency and ledger integrity with a hash history, giving git-like versioning, and the data is replicated as content-addressed encrypted blobs through ordinary object storage.

How do I store an image with Fireproof?

Put the file into the _files property of the document, for example as _files: { profilePic: file }, and display it with the ImgFile component, which handles loading from Fireproof's storage and takes the props of a normal image element.

How do I run the Fireproof tests?

Run pnpm run test for the full suite across the tested storage gateway configurations, and narrow it with a name pattern and a path, for example pnpm run test -t 'test name pattern' path/to/test/file, with FP_DEBUG enabling log output.

Official sources

  1. fireproof-storage/fireproof on GitHub
  2. Issues
  3. License: Apache-2.0
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/fireproof-storage-fireproof.svg)](https://hysenlabs.com/projects/fireproof-storage-fireproof)

Was this useful?