📐 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.
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 anS3Client
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.