Skip to content

Getting Started

Get up and running with Corpus in minutes. You’ll define a schema, create a corpus, and store your first versioned snapshot.

1
Install the package
Terminal window
bun add @f0rbit/corpus zod
2
Define a schema

Corpus uses Zod for type-safe serialization. Define a schema for your data:

import { z } from 'zod'
const PostSchema = z.object({
title: z.string(),
body: z.string(),
published: z.boolean(),
tags: z.array(z.string()).optional(),
})
type Post = z.infer<typeof PostSchema>
3
Create a corpus

Use the builder pattern to configure your corpus with a backend and stores:

import {
create_corpus,
create_memory_backend,
define_store,
json_codec
} from '@f0rbit/corpus'
const corpus = create_corpus()
.with_backend(create_memory_backend())
.with_store(define_store('posts', json_codec(PostSchema)))
.build()
4
Store and retrieve data

Use the typed store to save and load snapshots:

const post: Post = {
title: 'Hello World',
body: 'My first post using Corpus.',
published: true,
}
const result = await corpus.stores.posts.put(post)
if (result.ok) {
const { version, content_hash } = result.value
console.log(`Saved version ${version} with hash ${content_hash}`)
}
5
Handle errors with pattern matching

Corpus uses Result<T, E> types instead of throwing exceptions:

const snapshot = await corpus.stores.posts.get('nonexistent-version')
if (!snapshot.ok) {
switch (snapshot.error.kind) {
case 'not_found':
console.log(`Version ${snapshot.error.version} does not exist`)
break
case 'decode_error':
console.log('Data corruption detected:', snapshot.error.cause)
break
case 'storage_error':
console.log('Backend failed:', snapshot.error.operation)
break
}
return
}
console.log('Post title:', snapshot.value.data.title)

Package Exports

Corpus provides multiple entry points to minimize bundle size and keep platform-specific code separate.

Full Package

import { create_corpus, define_store, json_codec, ok, err } from '@f0rbit/corpus'

The main entry point includes all core utilities, the memory backend, Result types, and pipe utilities. Use this for most applications.

File Backend (Node.js)

import { create_file_backend } from '@f0rbit/corpus/file'

File system backend for Node.js and Bun environments. Stores snapshots as JSON files on disk.

Cloudflare Backend (Workers)

import { create_cloudflare_backend } from '@f0rbit/corpus/cloudflare'

Cloudflare Workers backend using D1 for metadata and R2 for blob storage. Import only in Worker environments.

Types Only

import type { Result, Snapshot, CorpusError } from '@f0rbit/corpus/types'

TypeScript type definitions with no runtime code. Use for type annotations in shared interfaces or when you only need types for dependency injection.

Drizzle Schemas

import { snapshots, observations, lineage } from '@f0rbit/corpus/schema'

Drizzle ORM table definitions for the Corpus data model. Use when you need to query Corpus tables directly or integrate with existing Drizzle schemas.

Next Steps