Skip to content

Backend Overview

The Rebase backend is a Node.js server built on Hono that provides:

  • REST API — Auto-generated CRUD endpoints for each collection
  • Authentication — JWT tokens, Google OAuth, user/role management
  • Storage — File upload/download with local filesystem or S3
  • WebSocket — Real-time data sync via PostgreSQL LISTEN/NOTIFY
  • Entity History — Audit trail for every data change

Everything is initialized with a single function:

import { initializeRebaseBackend } from "@rebasepro/backend";
const instance = await initializeRebaseBackend({
app,
server,
collections,
driver: {
connection: db,
schema: { tables, enums, relations }
},
auth: {
jwtSecret: process.env.JWT_SECRET!,
},
storage: { type: "local", basePath: "./uploads" },
history: true,
enableSwagger: process.env.NODE_ENV !== "production"
});

After initialization, these routes are mounted:

PathPurpose
/api/auth/*Authentication (signup, login, refresh, Google OAuth)
/api/admin/*User and role management (admin-only)
/api/storage/*File upload, download, and deletion
/api/data/collectionsCollection metadata endpoint
/api/data/:slugCRUD operations per collection (GET, POST, PUT, DELETE)
/api/data/:slug/:id/historyEntity change history (when enabled)
/api/data/docsOpenAPI spec (when enableSwagger: true)
/api/data/swaggerSwagger UI (dev mode, when enableSwagger: true)
WebSocket on upgradeReal-time subscriptions
interface RebaseBackendConfig {
// HTTP framework
app: Hono; // Hono application instance
server: Server; // Node.js HTTP server (for WebSocket attachment)
basePath?: string; // Route prefix (default: "/api")
// Collections
collections?: EntityCollection[]; // Your collection definitions
collectionsDir?: string; // Auto-load collections from a directory
// Database driver (see Driver Configuration)
driver: DriverConfig | Record<string, DriverConfig>;
// Authentication
auth?: AuthConfig;
// File storage
storage?: BackendStorageConfig | Record<string, BackendStorageConfig>;
// Entity history
history?: boolean | HistoryConfig;
// OpenAPI/Swagger
enableSwagger?: boolean;
// Logging
logging?: { level?: "error" | "warn" | "info" | "debug" };
}

initializeRebaseBackend returns a RebaseBackendInstance with access to all services:

const instance = await initializeRebaseBackend(config);
// Access services
instance.driver // Default data driver
instance.driverRegistry // All drivers (for multi-database)
instance.realtimeService // Default realtime service
instance.userService // User management
instance.roleService // Role management
instance.storageController // Default storage
instance.storageRegistry // All storage backends
instance.collectionRegistry // Collection metadata
instance.historyService // Entity history

The REST API is auto-generated from your collections. Every collection gets these endpoints:

MethodPathDescription
GET/api/data/:slugList entities (with filter, sort, limit, search)
GET/api/data/:slug/:idGet a single entity
POST/api/data/:slugCreate a new entity
PUT/api/data/:slug/:idUpdate an entity
DELETE/api/data/:slug/:idDelete an entity
ParamDescriptionExample
filterJSON-encoded filter conditions?filter={"active":["==",true]}
orderBySort field?orderBy=created_at
orderSort direction?order=desc
limitPage size?limit=25
startAfterCursor for pagination?startAfter=encodedCursor
searchFull-text search?search=laptop

The WebSocket server attaches to the same HTTP server and provides real-time subscriptions:

  • Subscribe to collection changes — get notified when any entity in a collection is created, updated, or deleted
  • Subscribe to entity changes — get notified when a specific entity changes
  • Automatic reconnection handling in the client SDK

The backend uses PostgreSQL LISTEN/NOTIFY internally. For multi-instance deployments, provide a connectionString in your driver config to enable cross-instance broadcasting.

The backend includes an error handler that catches all exceptions and returns structured error responses:

{
"error": {
"message": "Entity not found",
"code": "not-found",
"status": 404
}
}

If initialization fails (e.g., database connection error), the server still starts but returns 503 for all API requests, with a descriptive error message in the logs.