resync is an early alpha monorepo for building universal Reason React applications with synchronized store state, realtime delivery, and optional client persistence on top of a Dream server.
The repository currently ships with an ecommerce demo that exercises the shared packages.
This project is still a prototype.
- APIs, package boundaries, and schemas are still moving
- the ecommerce app is a demo, not a production-ready product
- expect refactors while the core abstractions settle
packages/
reason-realtime/
dream-middleware/ Dream websocket middleware with pluggable adapters
pgnotify-adapter/ PostgreSQL LISTEN/NOTIFY adapter
shared-types/ Shared domain types for native + Melange builds
universal-reason-react/
components/ Universal document components for SSR + hydration
lucide-icons/ Universal Lucide icon rendering for SSR + hydration
store/ Composable store layers: core, state, sync, persist
demos/
ecommerce/
server/ Dream server demo
ui/ Reason React / Melange frontend demo
packages/universal-reason-react/store is designed so stores do not have to use realtime sync.
Current layers:
StoreCore- schema-driven store construction, projections, and React contextStoreState- SSR serialization and hydrationStoreSync- realtime websocket sync for schema-backed storesStorePersist- client persistence adapters, currentlylocalStorage
The ecommerce demo uses these layers in two different ways:
- inventory store = core + state + sync
- cart store = core + persist
Realtime support is split into packages under packages/reason-realtime.
dream-middlewareexposes the Dream websocket middleware and adapter interfacepgnotify-adapteris the first adapter and uses PostgreSQLLISTEN/NOTIFY
The ecommerce demo uses this stack to stream inventory updates into the client store.
Current Dune public libraries publish under the resync.* namespace, including:
resync.reason_realtime_*resync.common_*resync.universal_reason_react_*
Universal document helpers live in packages/universal-reason-react/components.
Universal icon rendering lives in packages/universal-reason-react/lucide-icons.
These packages are used by the ecommerce demo for:
- server-rendered HTML shell generation
- client hydration
- matching Lucide SVG output on server and client
- injected scripts and serialized store state
- OCaml / Reason syntax
- Dream
- server-reason-react
- Melange
- React
- Tilia
- PostgreSQL
- pnpm
- esbuild
Install JavaScript dependencies from the repo root:
pnpm installStart PostgreSQL:
docker compose -f demos/ecommerce/server/docker-compose.yml up -dConfigure the database connection before starting the server. The server now
fails fast unless either DB_URL is set or ALLOW_DEV_DB=true is present:
export DB_URL=postgres://executor:executor-password@127.0.0.1:5432/executor_dbOr, to opt into the local development fallback explicitly:
export ALLOW_DEV_DB=trueRun the app from the repo root:
pnpm devOpen:
http://localhost:8899
You can also run the demo from its own directory:
cd demos/ecommerce
pnpm devBuild the demo app and server from the repo root:
dune build @app @serverThe ecommerce demo currently uses:
DOC_ROOT=./_build/default/demos/ecommerce/ui/src/app/DB_URLrequired unlessALLOW_DEV_DB=true- when
ALLOW_DEV_DB=true, the local development fallback ispostgres://executor:executor-password@127.0.0.1:5432/executor_db - server port
8899
- inventory is rendered on the server and hydrated in the browser
- inventory realtime updates come from PostgreSQL notifications over websockets
- the cart is client-side and persisted to
localStorage - the demo still uses
reason-react-day-pickerin the storefront UI
- the current build flow is Dune + Melange + esbuild
- the universal packages intentionally keep separate
js/andnative/layouts to preserve the existing build pipeline - the repo is mid-refactor, so README details should follow the code and scripts in the repo rather than older planning notes
The long-term goal is to make the Dream + universal Reason React + store stack reusable across multiple apps, with demos living beside the shared packages instead of inside one application tree.