# Spacebar Server: a Node.js reimplementation of the Discord backend

> Spacebar is a self-hosted server that aims to be wire-compatible with Discord.com, split into separate API, gateway, CDN and WebRTC processes. The interesting engineering is in the service separation and the generated schemas, not in a marketing page.

**spacebarchat/server** — Spacebar server - A reimplementation of the Discord.com backend, built with Typescript and love

- Repository: https://github.com/spacebarchat/server
- Website: https://spacebar.chat
- Stars: 2,202 · Forks: 327
- Language: TypeScript
- License: AGPL-3.0
- Published: 2026-10-07 · Updated: 2026-10-07 · Language: en
- Canonical page: https://hysenlabs.com/projects/spacebarchat-server

## Compatibility with Discord clients is the whole premise

The project's own description calls it a reimplementation of the Discord.com backend, and the README is more specific about the goal: reverse engineer the Discord backend, add features beyond it, and stay completely backwards compatible with existing bots, applications and clients. That last clause is the design constraint that shapes every other decision in the codebase. It means the wire protocol, the request and response shapes, and the gateway semantics all have to match what thousands of existing clients already expect, because the clients were never modified to accommodate this server.

The README is also direct about the gap. It says you should be able to use any client designed for Discord.com, that some incompatibilities still exist, and that for that reason not every client will connect. It then recommends a specific client, Fermo, as a starting point, and points at a separate project called Spacebar Explorer for finding others. That is a materially weaker guarantee than a compatibility matrix, and anyone evaluating this for an existing Discord user base should treat client support as something to test per client rather than assume.

A hosted instance exists at spacebar.chat, which is also the repository's homepage, and the README carries badges for the project's Matrix room, its Fermi invite, a Discord server, and an OpenCollective tier. The status badge reads Development, which is a fair self-description for a reverse engineering project without tagged releases.

## Five services, five entry points

The repository is not one process. The README lists what the tree contains: API request and response types under `src/schemas`, the HTTP API server under `src/api`, a WebSocket gateway under `src/gateway`, an HTTP CDN server under `src/cdn`, a WebRTC server under `src/webrtc`, and shared utility and database models under `src/util`. The manifest then gives each one its own start script, which confirms the separation is real rather than aspirational.

```bash
npm run start
npm run start:api
npm run start:cdn
npm run start:gateway
npm run start:webrtc
```

Every one of those runs a bundled JavaScript file under `dist/` with source maps enabled, so `start:gateway` is `node --enable-source-maps dist/gateway/start.js`. Having a default `start` alongside four specific ones implies the single-process mode is a convenience that runs everything together, while a real deployment runs each service on its own. For a chat backend, that separation is the difference between being able to scale the gateway (many persistent connections) independently of the API (request traffic) and being able to restart one without dropping everyone's session.

The CDN being a separate service also tells you something about scope. Discord's CDN is where attachments live, so a Spacebar instance has to store and serve files itself rather than pointing at Discord's. The WebRTC service is the voice and video path, and having it as its own process means NAT traversal problems are isolated from the chat path.

## Schemas are generated, not hand-maintained

The build script is the clearest statement of how this project manages compatibility. It does not run a plain compile:

```bash
npm run build
npm run sync:db
```

`build` chains three steps: `build:src` runs `tsc -b -v` for the TypeScript, then `generate:schema`, then `generate:openapi`. Both generators execute scripts out of the `scripts/` directory, `schema.js` and `openapi.js`, and both are loaded with `dotenv/config` and `module-alias/register`, which means the project's own import aliases are resolved at runtime rather than only at compile time. Any change to an endpoint therefore has to survive a regeneration pass, and an endpoint that is not described by the generated schemas is not part of the compatible surface.

The database follows the same discipline. Migrations are generated by TypeORM's CLI against the compiled database module, using `migration:generate -d dist/database/Database.js`, and there is a separate `sync:db` script that runs a file called `syncronise.js` to bring an existing database up to date. The misspelling in that filename is genuine and still in the tree, which is the kind of detail that only shows up when you read the manifest closely.

Two more generators are worth knowing about. `generate:rights` produces the permissions table, and `add:license` stamps licence headers into files, which pairs with the `COPYING` file and the AGPL-3.0 licence this project is released under. Tests run through `scripts/test.js` rather than a test framework entry point, so `npm test` is a bespoke harness.

## A C# admin API alongside the TypeScript server

The one genuinely surprising thing about the repository is that it is not single-language. The README lists a Spacebar Admin API in C# at `extra/admin-api/Spacebar.AdminApi`, a C# HTTP CDN server at `extra/admin-api/Spacebar.Cdn`, and a collection of other C# utilities under the same directory. So the operational tooling around the server is .NET while the server itself is Node.js.

This is not an accident of file layout. An admin API is a separate surface from the client-facing API: it is what you use to provision users, moderate and inspect a running instance, and it has different authentication and exposure requirements. Keeping it in a different language under `extra/` means the core server stays dependency-light and the management surface can be built with whatever the team found most productive. The cost is that you now need two toolchains to build everything, and `extra/` is easy to overlook when scanning the tree because it is not under `src/`.

The operational tooling around that is more conventional. An `nginx.conf` sits at the repository root, so a reverse proxy configuration is provided rather than left to the reader. Nix support is thorough: `flake.nix`, `flake.lock`, `default.nix`, a `nix/` directory and a generated `node-modules.nix` for pinning Node packages. A `patches/` directory plus a `postinstall` script running `patch-package` shows that upstream dependency problems are patched locally rather than by forking packages. Translations run through Crowdin, configured by `crowdin.yml` and served from translate.spacebar.chat. Code style is enforced by prettier through `.prettierrc.json`, lint-staged through `.lintstagedrc.mjs`, eslint, and husky git hooks installed by the `prepare` script.

## No releases means no version to pin

The repository has no GitHub releases. There are no tags to install from, no changelog, and no artifacts page. The only currency is the commit history, and the last push was on 2026-09-28.

That is a real operational constraint rather than a documentation gap. Every other project in this class of tooling gives you a version string and a set of build artifacts, so an operator can say precisely what is running. Here, a deployment is pinned to a commit, and an upgrade is a `git pull` followed by a rebuild, with the database sync step run afterwards. If you are running this in production, you need to keep your own record of which commit is deployed.

The manifest does declare `"version": "1.0.0"`, but with no tagged release behind it, that field does not correspond to anything a consumer can fetch, so treating it as a version would be a mistake. It is best read as a placeholder in a private package.

This is also why the README sends you to the documentation site rather than to a downloads page. Server setup, client setup and bot setup each have their own guide on docs.spacebar.chat, and contributing has its own page as well. The README is an index, not a manual, and for a project without releases that split is unavoidable.

## What it is a poor fit for

The clearest case against Spacebar is client compatibility. A Discord user with an unusual client, a heavily modified fork, or a bot framework that pokes at undocumented endpoints may simply fail to connect, and the repository offers a recommendation plus an explorer page rather than a guarantee. Any plan that depends on migrating an existing community without changing how its members connect carries real risk.

The second limitation is trust and protocol stability. Reverse engineering a proprietary service means the target can change without notice, and this project can only follow. The compatibility claim is directional: Spacebar tracks Discord, so a Discord change can break a Spacebar deployment without warning. Its own additions are the part you can rely on.

The third is operational effort. Five Node services, a CDN you host yourself, a C# admin API, a generated schema surface, a TypeORM migration step and a TURN-like concern for WebRTC in restricted networks together form a system with more moving parts than a hosted Discord or a conventional self-hosted Matrix stack. That is fine for an operator who wants this exact thing, and wrong for anyone who picked it because self-hosting sounds cheaper. Whether it actually is depends almost entirely on whether someone on your team is willing to own a media path, which the repository's inclusion of a dedicated WebRTC service quietly acknowledges.

## Conclusion

Spacebar earns adoption when you want Discord-shaped infrastructure on hardware you control, and it earns distrust the moment you need every third-party client to work. The README states the goal plainly, backwards compatibility with existing bots, applications and clients, and then admits in the next sentence that some incompatibilities remain, which is the honest version of the claim. Two facts should drive your decision. First, the repository publishes no GitHub releases at all, so there is no versioned artifact to pin and the last push on 2026-09-28 is your only freshness signal. Second, the build is a multi-process TypeScript project with generated schemas and an OpenAPI document, not a single container image. Start from the setup guide at docs.spacebar.chat, then run the `sync:db` script before starting any of the four service entry points, since the schema generation and database sync are separate steps that a first run will otherwise skip.

## FAQ

### Can I use my existing Discord client with a Spacebar server?

Usually, and not always. The README says you should be able to use any client designed for Discord.com but states that some incompatibilities still exist and that not every client will connect. It recommends Fermo as a starting point and points at Spacebar Explorer for other options.

### How do I run a Spacebar server locally?

The README does not include a quick start, and the repository publishes no GitHub releases, so there is no prebuilt artifact. Setup is documented on docs.spacebar.chat, where separate guides cover the server, clients and bots. Before starting any of the service entry points, run the database sync script so the generated schema matches your database.

### What are the separate services in the Spacebar server?

The manifest defines five start scripts: a default `start` plus `start:api`, `start:cdn`, `start:gateway` and `start:webrtc`, matching the README's description of an HTTP API server, an HTTP CDN server, a WebSocket gateway and a WebRTC server alongside shared utilities and database models.

### Do existing Discord bots work on Spacebar?

Backwards compatibility with existing bots, applications and clients is the stated design goal of the project. The README also notes that some incompatibilities remain, so individual bots would need to be checked rather than assumed to work.

### What licence is Spacebar Server released under?

The repository is licensed AGPL-3.0 and carries a COPYING file at the root. It also includes an `add:license` script for stamping licence headers into source files, which suggests the header convention is enforced rather than left to reviewers.

## Sources

- [Issues](https://github.com/spacebarchat/server/issues)
- [License: AGPL-3.0](https://github.com/spacebarchat/server/blob/master/LICENSE)
- [Project website](https://spacebar.chat)
- [README](https://github.com/spacebarchat/server/blob/master/README.md)
- [spacebarchat/server on GitHub](https://github.com/spacebarchat/server)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/spacebarchat-server
