atelier-api — das Backend

atelier-api ist der Server hinter der App: Login, Team-Cloud, Storage und gemeinsames Bauen. Eine Instanz reicht fürs ganze Team. Diese Seite zeigt dir, wie du sie selbst hostest.

Überblick

atelier-api ist ein schlanker Bun-Service mit MongoDB als Datenbank. Assets liegen in einem Content-Addressed Store auf der Platte (per SHA-256 adressiert, dedupliziert). Standardmäßig lauscht der Server auf Port 3095.

  • Discord-Login mit Freigabe-Workflow (pending → approved).
  • Versionierte Pack-Revisionen, resumable Uploads, Team-Locks über WebSocket.
  • Registry-Lane mit Service-Token, damit Webseiten veröffentlichte Packs abfragen können.
  • Web-Admin-Dashboard unter /admin — Logs, Speicher, Build-Downloads und fxmanifest-Overrides.

Quellcode & Issues: atelier-api auf GitHub.

Voraussetzungen

  • Bun (1.x) — zum Starten des Servers.
  • MongoDB — eine eigene Instanz oder MongoDB Atlas.
  • Eine Discord-Anwendung für den Login (kostenlos im Discord Developer Portal).
  • Persistenter Speicher für die Assets — siehe Storage & Volume.

Lokal starten

Terminal
cd atelier-api
bun install
cp .env.example .env.local   # Werte ausfüllen
bun run dev                  # mit Auto-Reload

# Läuft? Health-Check:
curl http://127.0.0.1:3095/health

Environment-Variablen

Konfiguriert wird über .env.local (lokal) bzw. die Umgebung des Hosters. Die wichtigsten Variablen:

VariableBeschreibung
MONGODB_URIPflicht — Connection-String zu MongoDB (z. B. mongodb+srv://…).
MONGODB_DB_NAMEDatenbankname (frei wählbar), Standard atelier.
ATELIER_JWT_SECRETPflicht — Secret zum Signieren der Tokens (lang & zufällig).
ATELIER_SERVICE_TOKENPflicht — Token für die Service-Lane (Registry für Webseiten).
ATELIER_PUBLIC_ORIGINÖffentliche Basis-URL des Servers (in Produktion https://…).
ATELIER_DISCORD_CLIENT_IDClient-ID deiner Discord-Anwendung.
ATELIER_DISCORD_CLIENT_SECRETClient-Secret deiner Discord-Anwendung.
ATELIER_ADMIN_DISCORD_IDSKomma-Liste von Discord-IDs, die automatisch Admin sind.
ATELIER_STORAGE_ROOTPfad für die Assets — muss persistent sein (Default ./data).
PORTHTTP-Port, Standard 3095.
HOSTBind-Adresse — in Produktion 0.0.0.0.
ATELIER_BUILD_CONCURRENCYParallele Server-Builds, Standard 2.

Secrets nie committen

ATELIER_JWT_SECRET und ATELIER_SERVICE_TOKEN sollten lang und zufällig sein (z. B. openssl rand -hex 32) und gehören nur in die Umgebung — niemals ins Repo. Die vollständige Liste inkl. Defaults steht in .env.example.

Discord-OAuth & Freigabe

Discord-Anwendung anlegen

  1. 1
    Im Discord Developer Portal eine neue Application erstellen (Name z. B. „atelier").
  2. 2
    Unter OAuth2 Client-ID und Client-Secret in deine Env übernehmen (ATELIER_DISCORD_CLIENT_ID / ATELIER_DISCORD_CLIENT_SECRET).
  3. 3
    Als Redirects beide exakt eintragen — einen für die Desktop-App, einen fürs Web-Admin-Dashboard:
    {ATELIER_PUBLIC_ORIGIN}/api/v1/auth/discord/callback
    {ATELIER_PUBLIC_ORIGIN}/admin/callback
    Lokal also http://127.0.0.1:3095/api/v1/auth/discord/callback bzw. http://127.0.0.1:3095/admin/callback. Der Scope identify wird automatisch angefragt.

Freigabe-Workflow

Neue Mitglieder landen als pending und müssen einmalig freigeschaltet werden. Discord-IDs in ATELIER_ADMIN_DISCORD_IDS sind automatisch Admin und freigegeben — diese Admins schalten dann alle weiteren direkt in der App frei.

  • pending — angemeldet, aber für Cloud-Aktionen gesperrt.
  • approved — voller Zugriff auf Packs, Sync und Builds.
  • locked — gesperrt, alle Geräte-Anmeldungen werden widerrufen.

Storage & Volume

Alle hochgeladenen Dateien liegen unter ATELIER_STORAGE_ROOT in einem Content- Addressed Store. Die MongoDB speichert nur die Metadaten und Verweise (per SHA-256).

ATELIER_STORAGE_ROOT/
cas/      finalisierte Assets (unveränderlich, per Hash)
tmp/      laufende Uploads
builds/   zwischengespeicherte Build-Artefakte

Das Volume MUSS persistent sein

Wird dieses Verzeichnis bei einem Redeploy gelöscht (z. B. Container ohne Volume), bleiben die MongoDB-Verweise zwar bestehen, die Dateien sind aber weg — Downloads scheitern dann mit asset_not_found. Lege ATELIER_STORAGE_ROOT immer auf ein persistentes Volume und sichere es regelmäßig. Nach einem Wipe müssen Besitzer ihre Packs neu hochladen.

Deployment (Dokploy)

atelier-api bringt ein Dockerfile mit (oven/bun) und lässt sich so überall als Container betreiben. Mit Dokploy in Kürze:

  1. 1
    In Dokploy eine neue Application aus dem atelier-api-Repository (oder dem Docker-Image) anlegen.
  2. 2
    Die Environment-Variablen setzen — insbesondere MONGODB_URI, ATELIER_JWT_SECRET, ATELIER_SERVICE_TOKEN, die beiden Discord-Werte und HOST=0.0.0.0.
  3. 3
    Ein persistentes Volume an ATELIER_STORAGE_ROOT mounten (z. B. /data). Das ist der wichtigste Schritt — ohne ihn verlierst du beim nächsten Deploy alle Assets.
  4. 4
    Eine Domain zuweisen und Port 3095 freigeben. Trage dieselbe öffentliche HTTPS-URL als ATELIER_PUBLIC_ORIGIN ein und hinterlege sie als Discord-Redirect.
  5. 5
    Deployen und mit GET /health prüfen.
Alternativ: pur per Docker
docker run -d --name atelier-api \
  -p 3095:3095 \
  -v atelier-data:/data \
  --env-file .env \
  atelier-api

Admin-Dashboard (Web)

Der Server bringt unter /admin ein eigenes Web-Dashboard mit — Login nur für die Discord-IDs aus ATELIER_ADMIN_DISCORD_IDS. Die Anmeldung läuft über einen eigenen Discord-Web-Flow (getrennt von der Desktop-App), die Session steckt in einem HttpOnly-Cookie, und der Admin-Status wird bei jedem Request neu geprüft.

  • Übersicht — Speichergröße (CAS/Builds/tmp) und Kennzahlen (Assets, Packs, Revisionen, Builds, Nutzer).
  • Logs — Server-Logs live (SSE) plus Aktivitäts-Protokoll.
  • Packs & Builds — Server-Builds pro Revision erzeugen oder neu bauen und die fertigen Pakete als ZIP herunterladen.
  • fxmanifest — pro Pack den Resource-Namen und ein fxmanifest.lua-Template überschreiben. Greift beim nächsten Server-Build; ohne Override bleibt alles byte-identisch zum Desktop-Build.
  • Nutzer — freischalten und sperren.

Voraussetzung

Echte Discord-Credentials und die zweite Redirect-URI {ATELIER_PUBLIC_ORIGIN}/admin/callback (siehe Discord-OAuth). Danach erreichbar unter {ATELIER_PUBLIC_ORIGIN}/admin.

Endpoint-Übersicht

Alle Endpoints liegen unter /api/v1. Nutzer-Endpoints brauchen einen Bearer- Token (aus dem Login), die Registry-Lane einen Service-Token. Die wichtigsten Gruppen:

GruppeZweck
auth / deviceDiscord-Login, Token-Tausch und -Erneuerung, Logout.
me / devicesEigenes Profil und angemeldete Geräte verwalten.
adminMitglieder auflisten, freischalten, sperren, Rollen setzen.
/admin (Web)Browser-Dashboard: Übersicht, Logs, Build-Downloads, fxmanifest — Cookie-Login, nur Admins.
uploads / assetsResumable Chunk-Uploads und Asset-Download (mit Range/ETag).
packs / revisionsPacks, Mitglieder und versionierte Revisionen.
locksAdvisory-Locks pro Drawable (TTL, Heartbeat).
buildsServer-Builds in die Queue stellen und Artefakte abrufen.
registryService-Lane: veröffentlichte Packs für Webseiten (Service-Token).
wsWebSocket für Presence, Locks und Live-Status.

Health & Service-Token

Ein schneller Lebenszeichen-Check geht ohne Token über GET /health. Webseiten sprechen die Registry per Header x-fg-service-token an. Server-Builds enthalten keine binären YMTs (die entstehen im Desktop-Build) — sie dienen Vorschau und Verteilung.