Architecture

Architecture overview

A high-level map of how Alaf Server fits together — the interfaces you drive, the API that runs everything, the platform adapters, and the shared packages.

Alaf Server is one codebase that plays several parts. Think of it like a restaurant: there's the counter where you place an order (the things you click and type), the kitchen that actually cooks (the API), and the appliances the kitchen uses to do the work (the platform layer). This page is the map. The other architecture pages zoom into one area each.

Here's the whole thing on one screen:

   You drive Alaf Server three ways
   ┌───────────┐   ┌───────────┐   ┌───────────┐
   │ Dashboard │   │    CLI    │   │  Desktop  │
   │ (Next.js) │   │ (alaf server)│   │ (Electron)│
   └─────┬─────┘   └─────┬─────┘   └─────┬─────┘
         └───────────────┼───────────────┘
                         │  HTTP, under /api/*
                   ┌─────▼─────┐
                   │    API    │   the control plane
                   │  (Hono)   │   projects · deployments · domains · env · auth
                   └─────┬─────┘
                         │  getPlatform()
                   ┌─────▼──────┐
                   │  Adapters  │   runtime · routing · SSL · system checks
                   └─────┬──────┘
              ┌──────────┼──────────┐
         ┌────▼───┐  ┌───▼────┐  ┌──▼──────┐
         │ local  │  │ server │  │  cloud  │   where your app ends up
         └────────┘  └────────┘  └─────────┘

The control plane: the API

The API is the brain. It's a Hono app (a small, fast web framework) that owns everything that matters — projects, deployments, domains, environment variables, backups, and the permission model — and it stores that data in a database (see Data ownership).

Everything else in the picture is a way to talk to this API, or a tool the API uses. Nothing writes to the database directly except the API, and every piece of the UI reaches it over plain HTTP under /api/*. That single front door is why the dashboard, the CLI, and the desktop app always agree with each other: they're all reading and writing the same source.

One door, many keys

The API accepts a browser session cookie (from the dashboard) or a bearer token (from the CLI and scripts). Same endpoints, same rules, whichever you use. See the API overview for the auth model.

The three ways you drive it

All three interfaces are thin — they render screens and send requests. The real work happens behind the API.

  • Dashboard — a Next.js web app. This is the full graphical UI, built for teams, and what you see in most screenshots in these docs.
  • CLI — the alaf server command you install from npm. It wears two hats: alaf server up can stand up a whole self-hosted instance on your machine — it bundles the API and fetches the dashboard for you — while everyday commands like alaf server deploy are a thin HTTP client that calls the same API endpoints the dashboard does. Great for self-hosting, scripting, and CI.
  • Desktop app — an Electron wrapper that shows the same dashboard and runs its own local copy of the API on your machine, so you can deploy from a laptop with no server at all.

Because they share the API, you can start a deploy in the dashboard and check on it from the CLI — it's one system, not three.

The platform layer: adapters

When the API needs to do something to the outside world — build an image, start a container, wire up a domain, get an SSL certificate — it doesn't do it directly. It asks the platform layer (the @repo/adapters package). This is the "appliances" in the kitchen analogy, and it has three parts behind a single entry point:

  • Runtime — builds and runs your app. There are three runtimes: Docker (your app runs in a container), Bare (your app runs as a plain process, lighter for small machines and the desktop), and Cloud (the work is handed off to Alaf Server Cloud).
  • Infra — routing and certificates. On self-hosted instances this is OpenResty (an nginx-based web server) for routing and certbot for automatic Let's Encrypt HTTPS. On cloud, the edge handles it.
  • System — prerequisite checks and setup (is Docker installed? is git present?). Self-hosted only.

At startup the API picks the right combination of these once, and the rest of the code just calls getPlatform(). For the full story of how a deploy resolves to a concrete runtime, see Runtime model.

Where an app ends up

A project deploys to one of three targets, and the platform layer above is what makes each one work:

  • local — the instance's own machine.
  • server — a server you've connected over SSH.
  • cloud — Alaf Server Cloud compute.

The target is chosen once per deploy and snapshotted, so the build, the routing, and any later rollback can never disagree about where the app lives.

Shared packages

Alaf Server is a monorepo. Common logic lives in @repo/* packages that every app reuses, so there's one implementation of each thing rather than four copies that drift apart.

PackageWhat it holds
@repo/corePure shared logic — types, stack detection, constants, error classes. No side effects.
@repo/dbAll database access, via Drizzle ORM over Postgres (or an embedded PGlite for zero-setup installs). Every query goes through typed repositories.
@repo/adaptersThe platform layer described above: runtime, infra, and system.
@repo/uiThe shared React component library used by the dashboard and the marketing/docs site.
@repo/onboardingThe setup and first-run flow shared by the CLI, dashboard, and desktop.

One codebase, three roles

The same code runs as Alaf Server Cloud (the managed SaaS), as a self-hosted instance on your own server, or as the desktop app. Configuration at startup decides which role an instance plays and which runtime it uses (for self-hosted, DEPLOY_MODE=docker or bare). Nothing is forked — the cloud and the version you self-host are literally the same source.

The one thing that changes with the role is where data is canonical. Local and server projects live entirely in your own instance's database; cloud projects are owned by Alaf Server Cloud and your instance acts as a gateway in front of them. That split is the subject of the next two pages.

What next?

On this page