Gitapp
Gitapp is a layered stack that lets an app store its data in a real git repository — every write is a commit, conflicts are exposed as conflicts, and any provider that speaks git over HTTPS (GitHub, Gitea, GitLab, self-hosted) is a valid backend.
The stack is split across four packages so apps can opt in to only what they need. The boundaries are stable: each layer below is implementable without knowledge of the layer above.
| Package | Layer | Role |
|---|---|---|
@dev-bench/docstore | interface | DocStore contract + Zod schemas. No git knowledge. |
@dev-bench/git-fs | 1 | Git/FS primitives. Browser/Node/in-memory adapters; GitHub/Gitea/GitLab REST. |
@dev-bench/gitapp | 2 | Wires git-fs into a DocStore implementation: transactions, conflict policies, watch. |
@dev-bench/gitapp-ui | 3 | RN + react-native-web theme, primitives, and full-fledged components driven by view-models. |
Install
pnpm add @dev-bench/docstore @dev-bench/git-fs @dev-bench/gitapp
# UI is optional — peer-deps on react / react-native / react-native-svg
pnpm add @dev-bench/gitapp-uiConceptual model
A DocStore is a transactional document store. Every mutation goes
through runTransaction, which is atomic — all mutations apply or none
do — and returns a discriminated union you branch on with
ts-pattern.match(...).exhaustive().
import { match } from "ts-pattern";
const result = await docStore.runTransaction({
mutations: [
{ kind: "put", path: "todos/1.md", content: "buy milk\n", ifMatch: { kind: "any" } },
],
message: "todo: add buy milk",
onConflict: { kind: "rebase-mutations", maxAttempts: 3 },
});
match(result)
.with({ kind: "ok" }, ({ commitOid }) => console.log("committed", commitOid))
.with({ kind: "conflict" }, (e) => console.warn("conflict", e.paths))
.with({ kind: "rejected" }, (e) => console.warn("validation", e.reason))
.with({ kind: "network" }, (e) => console.warn("network", e.message))
.exhaustive();The ifMatch token implements optimistic concurrency. The onConflict
policy decides what happens when a remote changed since the last sync —
fail loud, retry after pull, or rebase the mutations onto the new HEAD.
Choose your storage
@dev-bench/git-fs ships three adapters out of the box:
createBrowserGitFs— LightningFS (IndexedDB) + isomorphic-git web http. Web app + Hermes (React Native).createInMemoryGitFs— pure-memory fs. Tests, sandboxes, fixtures.createNodeGitFs— node fs + isomorphic-git node http. CLI tools, servers.
And three management providers:
githubManagement— GitHub REST.giteaManagement— Gitea REST.gitlabManagement— GitLab REST.
Pick whichever pair fits the host environment; the DocStore you build
on top is identical.
Next
- Getting Started — wire it together end-to-end.
- API — public exports, package by package.