Skip to content

📐 Structure

To manage our monorepo, we use Turborepo.

Website

Our product website, which you are currenly reading, is created using Astro and the code is located in apps/website.

Packages

Shared Types

The shared-types package contains shared types and interfaces used across the monorepo. It is located in packages/shared-types.

UI Component Library

The ui package contains our shared UI components. It is located in packages/ui.

Icon Library

The icons package contains our shared icons. It is located in packages/icons.

Core application

Our core application is currently divided into two apps: the Dashboard and the Server.

Architecture Diagram

Dashboard

The dashboard is our frontend. It uses Vite with SolidJS as a framework and is the heart of our application. It communicates with the Server through our REST API and Hocuspocus. Code for the dashboard is located in apps/dashboard.

Server

Required Services

The WebEdit Server needs two services:

Valkey

Valkey is a fork of the popular key-value store Redis. We use it to store the following:

  • users
  • tokens
  • media metadata
  • Y.js documents

Valkey provides a single API using the REDIS protocol (defaults to port 6379). Inside the server, we use the iovalkey package to communicate with the service. The code related to initializing the connection is located in apps/server/src/valkey.ts, which exports the getValkey() function.

Garage

Garage is an S3-compatible blob storage similar to minio. Garage easily scales horizontally in clusters, but for our purposes (for now), we only use a single node. We use it for user content like pictures and videos. Garage provides two APIs:

  • Admin API: A REST-like API used to manage the cluster and set up S3 tokens (defaults to port 3903).
  • S3 API: Standard S3 API (defaults to port 3900).

The code related to initializing the connection is located in apps/server/src/garage.ts, which uses the Admin API to create an S3 token and exports the following functions:

  • requireBucket(bucketName): Creates a bucket with the given name if it does not already exist.
  • getS3Client(): Returns an S3Client instance from the @aws-sdk/client-s3 package, which we use to communicate with the S3 API.

Server components

The WebEdit Server is created using TypeScript and Bun as the runtime. The code of the server is located in apps/server and consists of two components:

Hocuspocus

Hocuspocus is used for syncing and merging changes to and from Y.js documents. It is connected to the Dashboard with a Websocket. The code for it is located in apps/server/src/hocuspocus.ts. The synced documents get stored in Garage. In our setup, Hocuspocus binds to port 3001 by default, but in our demo deployment we proxy requests to https://demo.webedit.site/hocuspocus to it.

REST API

Our REST API handles authentication and storage of media like videos or pictures. We use ElysiaJS as a framework for the API. Elysia has the following benefits:

  • great support for Bun
  • easily create tests using Eden
  • automatic creation of swagger documentation (reuses type definitions from validation)
  • easy validation of requests and responses
  • extensibility through plugins

The REST API binds to port 3000 by default, but in our demo deployment we proxy requests to https://demo.webedit.site/api to it.