Skip to content

Monorepo

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)
Section titled “Recommended tooling: Use Nix + direnv for a consistent development setup”

To make development as easy and consistent across systems and platforms, this project uses Nix to manage “system dependencies” such as Node.js, Bun etc. You can either use Direnv setup (recommended) to automatically load the Nix env or manually use the Nix env (e.g. via nix develop --command pnpm install).

You’ll need to have a recent version the following tools installed:

  • Node.js
  • Bun
  • pnpm
Terminal window
git clone git@github.com:livestorejs/livestore.git
cd livestore
# Loads env vars, installs deps and builds the project
./bootstrap.sh
  • TypeScript
    • 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.

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.

  • This project is primarily developed in VSCode and makes use of tasks to run commands.
  • Common tasks are:
    • dev:ts:watch to run the TypeScript compiler in watch mode for the entire monorepo
    • pnpm:install to install all dependencies (e.g. when changing a package.json)

Please run the following tasks before committing & pushing:

  • mono ts to build the TypeScript code
  • mono lint to run the linting checks
  • mono test to run the tests
  • Once you’ve set up the monorepo locally, you’ll find all examples in the /examples directory.
  • 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.
  1. Make your desired changes directly in /examples/<example-name>.
  2. Test your changes by running the example (e.g., pnpm dev in the example directory).
  3. Commit your changes.

As a local OpenTelemetry setup, we recommend the docker-otel-lgtm setup.

Add the following to your .envrc.local file:

Terminal window
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"
  • Each package has its own tsconfig.json file which extends the root tsconfig.base.json.
  • This project makes heavy use of TypeScript project references.
  • 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 resolutions field in the root package.json to force some packages to be the same across the monorepo (ideally not needed but for some packages it’s necessary currently).
  • We’re using syncpack to help maintain consistent dependency versions across the monorepo.
    • See syncpack.config.mjs for the configuration.
    • Common commands:
      • bunx syncpack format to format the package.json files
      • bunx syncpack lint to check all version ranges
      • bunx syncpack fix-mismatches to adjust versions across package.json files (check before with lint)
      • bunx syncpack update to update packages across the monorepo to the latest versions

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.

The following packages need to be updated with extra care:

  • react/react-dom as we need to move in lockstep with Expo / React Native (currently pinned to 19.0.0)
  • effect (currently pinned to 3.17.2)
  • 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).
  • Either update the versions manually in each package.json file or use bunx syncpack update.
  • The @livestore/utils package re-exports many common modules/functions (e.g. from effect) 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.