Skip to content
Menu

Architecture

How it works

Architecture

A TypeScript monorepo with a protocol-neutral core. Simple to run, easy to read.

Principles

Protocol-neutral core

The domain knows posts and people, not protocols.

Privacy first

Visibility is data on every object, checked in one place.

Easy to host

Node, PostgreSQL, Redis. A small VPS is enough.

Portability

Export, import and account moves.

Moderation from day one

Reports, blocks, rate limits, audit log.

Typed end to end

Server and web app share types and schemas.

The stack

Server

  • Node.js 22 LTS
  • Fastify + Zod
  • Drizzle ORM + PostgreSQL 16+
  • Redis + BullMQ
  • Fedify (ActivityPub)
  • Our own diaspora* library

Web

  • React 19 + Vite
  • TanStack Router & Query
  • Tailwind CSS v4
  • i18next (en, it)
  • PWA + Web Push
  • Mastodon-compatible API for apps

Quality

  • TypeScript strict
  • Vitest: 450+ tests
  • diaspora* fixtures from the official gem
  • Biome
  • Turborepo
  • Continuous integration

The monorepo

apps/server      REST API, inbox/outbox, WebSocket
apps/worker BullMQ jobs: federated delivery
apps/web React single-page app
packages/core domain: posts, people, canView()
packages/db Drizzle schema and migrations
packages/activitypub ActivityPub adapter (Fedify)
packages/diaspora diaspora* protocol and bridge
packages/diaspora-import in-place pod migration
packages/shared shared types and Zod schemas
packages/config typed configuration

Every federable object has both an ActivityPub URI and a diaspora* GUID. Design decisions are recorded in docs/decisions.md.

Layers

Web & apps

The React app and Mastodon apps talk to the same /api/v1.

API

Fastify routes validate input with Zod and call the core.

Core

Social rules, visibility and events, with no protocol inside.

Adapters

ActivityPub and diaspora* translate events into messages, and back.