Remote / foldkit-remote-server

Compose and validate the server

A complete server definition is just the collection of Sources:

ts
const Server = RemoteServer.make({
  entities: [ProjectSource, UserSource],
  queries: [ProjectsByOwnerSource],
  mutations: [RenameProjectSource],
  live: [ProjectLive],
})

When the client and server share the Remote domain declaration, validate the Source names at startup:

ts
const Data = Remote.define({
  entities: [Project, User],
  queries: [ProjectsByOwner],
  mutations: [RenameProject],
})

RemoteServer.validate(Data, Server)

That catches an Entity, Query, or Mutation Source whose name is not declared by the shared domain instead of letting it silently answer nothing at runtime.

Then compile it into handlers, once per principal, or once for every request with a Context key as the principal (see Authentication vs authorization):

ts
const handlers = RemoteServer.handlers(Server, principal, {
  maxIdsPerEntity: 1000,
  maxDepth: 8,
  live: hub,
})

handlers implements the RemoteRpc client shape directly. In-process — tests, SSR, a worker, or a single service — it can become a RemoteClient with:

ts
const clientLayer = Remote.clientLayer(handlers)

Across a process boundary, use:

ts
const rpcLayer = RemoteRpc.toLayer(handlers)

The application supplies the Effect RPC server/transport layer. RemoteServer does not choose HTTP, WebSocket, or another transport for you.

Runtime dependencies belong to Sources

Sources are Effects, so dependencies stay explicit:

Project Source
    requires Database

Billing Query Source
    requires BillingApi

RemoteServer
    requires Database | BillingApi

The server definition does not capture either service. Provide their Layers at the application boundary. This is also why foldkit-remote-drizzle provides Drizzle-backed Sources rather than putting a database inside RemoteServer.