Monorepo
Prerequisites
Section titled “Prerequisites”Personal experience
Section titled “Personal experience”Depending on the kind of contribution you’re interested in, the following experience is recommended:
- Deep experience with TypeScript (incl. type-level programming)
- Experience with TypeScript monorepo setups
- Experience with distributed systems
- Experience with Effect (or willingness to learn)
Recommended tooling: Use devenv + direnv for a consistent setup
Section titled “Recommended tooling: Use devenv + direnv for a consistent setup”To make development easy and consistent across systems and platforms, this
project uses Nix with devenv
to manage “system dependencies” such as Node.js, Bun, etc.
Use direnv (recommended) to automatically load the
environment, or run commands explicitly with devenv, for example:
devenv shell pnpm install.
Manual setup
Section titled “Manual setup”You’ll need to have a recent version the following tools installed:
- Node.js
- Bun
- pnpm
Initial setup
Section titled “Initial setup”git clone git@github.com:livestorejs/livestore.gitcd livestore# Loads env vars, installs deps and builds the project./bootstrap.shGeneral notes
Section titled “General notes”- TypeScript
- LiveStore tries to follow the strictest TypeScript rules possible to ensure
type safety and avoid subtle bugs.
- LiveStore also makes heavy use of TypeScript project references.
- LiveStore tries to follow the strictest TypeScript rules possible to ensure
type safety and avoid subtle bugs.
- Package management
- This project uses pnpm to manage the workspace.
- LiveStore is primarily developed in VSCode/Cursor.
- Testing
- LiveStore uses Vitest for most tests and Playwright for browser tests.
Notable used tools / technologies
Section titled “Notable used tools / technologies”- TypeScript
- Effect
- pnpm
- Bun
- Vitest
- Playwright
- OpenTelemetry
- wa-sqlite (included as git subtree) - see wa-sqlite management
- Nix
- Direnv
- devenv
Environment variables
Section titled “Environment variables”The .envrc file contains all necessary environment variables for the project.
You can create a .envrc.local file to override or add variables for your local
setup. You’ll need to run direnv allow to load the environment variables.
VSCode tasks
Section titled “VSCode tasks”- This project is primarily developed in VSCode and makes use of tasks to run commands.
- Common tasks are:
dev:ts:watchto run the TypeScript compiler in watch mode for the entire monorepopnpm:installto install all dependencies (e.g. when changing apackage.json)
Tasks to run before committing
Section titled “Tasks to run before committing”Please run the following tasks before committing & pushing:
mono tsto build the TypeScript codemono lintto run the linting checksmono testto run the tests
Examples
Section titled “Examples”- Once you’ve set up the monorepo locally, you’ll find all examples in the
/examplesdirectory. - All examples are self-contained and can be run independently.
- Examples use explicit version dependencies (e.g.,
0.3.2-dev.0) for LiveStore packages. - Examples are not part of the monorepo TypeScript build system to maintain independence.
- Each example has its own TypeScript configuration that’s independent of the monorepo build system.
Making changes to examples
Section titled “Making changes to examples”- Make your desired changes directly in
/examples/<example-name>. - Test your changes by running the example (e.g.,
pnpm devin the example directory). - Commit your changes.
OpenTelemetry setup
Section titled “OpenTelemetry setup”As a local OpenTelemetry setup, we recommend the docker-otel-lgtm setup.
Add the following to your .envrc.local file:
export VITE_GRAFANA_ENDPOINT="http://localhost:30003"export GRAFANA_ENDPOINT="http://localhost:30003"export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"export VITE_OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4318"TypeScript
Section titled “TypeScript”- Each package has its own
tsconfig.jsonfile which extends the roottsconfig.base.json. - This project makes heavy use of TypeScript project references.
Package management
Section titled “Package management”- This project uses pnpm to manage the workspace.
- We’re using the
workspace:*protocol to link packages together. - We should try to keep dependencies to an absolute minimum and only add them if we absolutely need them.
- We also need to manually add peer dependencies for each package.
- We should try to avoid duplicate dependencies across the monorepo as much as
possible as duplicate dependencies can lead to a lot of issues and pain.
- We’re also using the
resolutionsfield in the rootpackage.jsonto force some packages to be the same across the monorepo (ideally not needed but for some packages it’s necessary currently).
- We’re also using the
- We’re using syncpack to help
maintain consistent dependency versions across the monorepo.
- See
syncpack.config.mjsfor the configuration. - Common commands:
bunx syncpack formatto format thepackage.jsonfilesbunx syncpack lintto check all version rangesbunx syncpack fix-mismatchesto adjust versions acrosspackage.jsonfiles (check before withlint)bunx syncpack updateto update packages across the monorepo to the latest versions
- See
Notes on external dependencies
Section titled “Notes on external dependencies”LiveStore tries to use as few external dependencies as possible. Given LiveStore is built on top of Effect, which can be considered a standard library for TypeScript, it should handle most use cases.
Notes on some packages
Section titled “Notes on some packages”The following packages need to be updated with extra care:
react/react-domas we need to move in lockstep with Expo / React Native (currently pinned to 19.1.0)effect(currently pinned to 3.18.0)
Effect
Section titled “Effect”- LiveStore makes heavy use of the Effect library and ecosystem throughout the implementation of the various packages.
- Effect is not imposed on the app developers using LiveStore but where it makes
sense, LiveStore is also exposing a Effect-based API (e.g.
createStore).
Updating dependencies
Section titled “Updating dependencies”- Either update the versions manually in each
package.jsonfile or usebunx syncpack update.
Notes on monorepo structure
Section titled “Notes on monorepo structure”- The
@livestore/utilspackage re-exports many common modules/functions (e.g. fromeffect) in order to- Reduce the number of direct dependencies for other packages
- Allows for convenient extension of modules (e.g. adding methods to
Effect.___,Schema.___, …)
The LiveStore docs are built with Astro Starlight.
Related external repos
Section titled “Related external repos”- Fork of wa-sqlite with Nix build setup included as git subtree.
- The source code of the devtools is currently not part of this monorepo but in a separate private repo.