Chapter 1: Getting Started
April 13, 2026 ยท View on GitHub
Welcome to Chapter 1: Getting Started. In this part of Fireproof Tutorial: Local-First Document Database for AI-Native Apps, you will build an intuitive mental model first, then move into concrete implementation details and practical production tradeoffs.
This chapter gets Fireproof running with both React-hook and core API entry points.
Quick Start
npm install use-fireproof
Or core API only:
npm install @fireproof/core
Minimal Core Example
import { fireproof } from "@fireproof/core";
const db = fireproof("music-app");
await db.put({ _id: "beyonce", name: "Beyonce", hitSingles: 29 });
const doc = await db.get("beyonce");
Learning Goals
- initialize a Fireproof database
- write and read documents
- confirm local-first behavior in your runtime
Source References
Summary
You now have Fireproof running with a minimal document lifecycle.
Next: Chapter 2: Core Document API and Query Lifecycle
Source Code Walkthrough
cli/cmd-evento.ts
The isCmdTSMsg function in cli/cmd-evento.ts handles a key part of this chapter's functionality:
});
export type CmdTSMsg = typeof CmdTSMsg.infer;
export function isCmdTSMsg(u: unknown): u is CmdTSMsg {
return !(CmdTSMsg(u) instanceof type.errors);
}
export type WrapCmdTSMsg<T> = Omit<CmdTSMsg, "result"> & { result: T };
export const CmdProgress = type({
type: "'core-cli.progress'",
level: "'info'|'warn'|'error'",
message: "string",
});
export type CmdProgress = typeof CmdProgress.infer;
export function isCmdProgress(u: unknown): u is CmdProgress {
return !(CmdProgress(u) instanceof type.errors);
}
export async function sendMsg<Q, S>(
ctx: HandleTriggerCtx<WrapCmdTSMsg<unknown>, Q, S>,
result: S,
): Promise<Result<EventoResultType>> {
await ctx.send.send(ctx, {
...ctx.request,
result,
} satisfies WrapCmdTSMsg<S>);
return Result.Ok(EventoResult.Continue);
}
export async function sendProgress<Q, S>(
ctx: HandleTriggerCtx<WrapCmdTSMsg<unknown>, Q, S>,
level: CmdProgress["level"],
This function is important because it defines how Fireproof Tutorial: Local-First Document Database for AI-Native Apps implements the patterns covered in this chapter.
cli/cmd-evento.ts
The isCmdProgress function in cli/cmd-evento.ts handles a key part of this chapter's functionality:
export type CmdProgress = typeof CmdProgress.infer;
export function isCmdProgress(u: unknown): u is CmdProgress {
return !(CmdProgress(u) instanceof type.errors);
}
export async function sendMsg<Q, S>(
ctx: HandleTriggerCtx<WrapCmdTSMsg<unknown>, Q, S>,
result: S,
): Promise<Result<EventoResultType>> {
await ctx.send.send(ctx, {
...ctx.request,
result,
} satisfies WrapCmdTSMsg<S>);
return Result.Ok(EventoResult.Continue);
}
export async function sendProgress<Q, S>(
ctx: HandleTriggerCtx<WrapCmdTSMsg<unknown>, Q, S>,
level: CmdProgress["level"],
message: string,
): Promise<void> {
await ctx.send.send(ctx, {
...ctx.request,
result: {
type: "core-cli.progress",
level,
message,
} satisfies CmdProgress,
} satisfies WrapCmdTSMsg<CmdProgress>);
}
This function is important because it defines how Fireproof Tutorial: Local-First Document Database for AI-Native Apps implements the patterns covered in this chapter.
cli/cmd-evento.ts
The cmdTsEvento function in cli/cmd-evento.ts handles a key part of this chapter's functionality:
}
export function cmdTsEvento() {
const evento = new Evento({
encode: (i) => {
if (isCmdTSMsg(i)) {
return Promise.resolve(Result.Ok(i.result));
}
return Promise.resolve(Result.Err("not a cmd-ts-msg"));
},
decode: (i) => Promise.resolve(Result.Ok(i)),
});
evento.push([
wellKnownEvento,
writeEnvEvento,
keyEvento,
preSignedUrlEvento,
retryEvento,
dependabotEvento,
updateDepsEvento,
setScriptsEvento,
setDependenciesEvento,
tscEvento,
testContainerBuildEvento,
testContainerTemplateEvento,
testContainerPublishEvento,
deviceIdCreateEvento,
deviceIdCsrEvento,
deviceIdExportEvento,
deviceIdCertEvento,
deviceIdCaCertEvento,
deviceIdRegisterEvento,
This function is important because it defines how Fireproof Tutorial: Local-First Document Database for AI-Native Apps implements the patterns covered in this chapter.
cli/main.ts
The OutputSelector class in cli/main.ts handles a key part of this chapter's functionality:
import { updateDepsCmd, isResUpdateDeps } from "./cmds/update-deps-cmd.js";
class OutputSelector implements EventoSendProvider<unknown, unknown, unknown> {
readonly tstream = new TransformStream<unknown, WrapCmdTSMsg<unknown>>();
readonly outputStream: ReadableStream<WrapCmdTSMsg<unknown>> = this.tstream.readable;
readonly writer = this.tstream.writable.getWriter();
async send<IS, OS>(_trigger: HandleTriggerCtx<unknown, unknown, unknown>, data: IS): Promise<Result<OS, Error>> {
await this.writer.write(data);
return Promise.resolve(Result.Ok());
}
done(_trigger: HandleTriggerCtx<unknown, unknown, unknown>): Promise<Result<void>> {
this.writer.releaseLock();
this.tstream.writable.close();
return Promise.resolve(Result.Ok());
}
}
async function main() {
dotenv.config(process.env.FP_ENV ?? ".env");
const sthis = ensureSuperThis();
// tsc bypass: called directly before cmd-ts runs
if (process.argv[2] === "tsc") {
return handleTsc(process.argv.slice(3), sthis);
}
const ctx: CliCtx = {
sthis,
cliStream: createCliStream(),
};
const rs = await runSafely(
This class is important because it defines how Fireproof Tutorial: Local-First Document Database for AI-Native Apps implements the patterns covered in this chapter.
How These Components Connect
flowchart TD
A[isCmdTSMsg]
B[isCmdProgress]
C[cmdTsEvento]
D[OutputSelector]
E[main]
A --> B
B --> C
C --> D
D --> E