Overview of the project

The app is built with only client-side libraries. The project is a vanilla TypeScript template of vite.

All the code is contained in a single src folder. Running build will generate a dist folder with the compiled code, that you can deploy to any static hosting service.

Routing is implemented using TanStack Router, that offers a simple and type-safe API for routing on the client.

The architecture is based on effect. The core logic is implemented as effect services, that are then wrapped inside Layer and composed to define each feature.

The local database is provided by Pglite. Pglite is a WASM build of postgres that runs in the browser. It is used to store and query the data locally with SQL.

Pglite also provides a live extension that unlocks reactive queries. Every change in the data is automatically reflected in the UI.

Queries are defined by integrating Pglite with drizzle-orm. Drizzle is a TypeScript ORM that allows to define the database schema and query the data using TypeScript types.

State management used xstate and the actor model. Each feature is implemented as a state machine composed by multiple smaller actors. This allows to easily handle asynchronous operations, loading states and error messages.

Finally, the UI is based on react-aria-components and tailwindcss (v4).

Folder structure of the project. All the code is contained in a single src folder. Each sub-folder defines a separate layer of the app (database, services, UI).
Folder structure of the project. All the code is contained in a single src folder. Each sub-folder defines a separate layer of the app (database, services, UI).

These are the core dependencies:

  • @tanstack/react-router
  • effect
  • @electric-sql/pglite
  • drizzle-orm
  • xstate
  • react-aria-components

The app then uses vite-plugin-pwa to generate a service worker and a manifest file, making the app available as a Progressive Web App (PWA).

This allows the app to be installed on the user's device and work completely offline.

Let's dive into the project. First step is setting up the database structure 🚀