Project Structure
A Rebase project generated by npx create-rebase-app has three interconnected packages:
my-app/├── .env # Environment variables (DATABASE_URL, JWT_SECRET, etc.)├── package.json # Root workspace config│├── frontend/ # React admin panel (Vite)│ ├── src/│ │ ├── App.tsx # Main application component│ │ ├── main.tsx # React entry point│ │ └── index.css # Global styles│ ├── package.json│ └── vite.config.ts│├── backend/ # Node.js API server (Hono)│ ├── src/│ │ ├── index.ts # Server entry — initializes Rebase backend│ │ └── schema.generated.ts # Auto-generated Drizzle schema│ ├── drizzle.config.ts # Drizzle ORM configuration│ ├── Dockerfile│ └── package.json│└── shared/ # Collection definitions └── collections/ ├── index.ts # Exports all collections └── products.ts # Example: products collectionFrontend (frontend/)
Section titled “Frontend (frontend/)”The frontend is a standard Vite + React + TypeScript application. The key file is App.tsx, which wires together all Rebase controllers:
import { Rebase, Scaffold, AppBar, Drawer, ... } from "@rebasepro/core";import { createRebaseClient } from "@rebasepro/client";import { collections } from "virtual:rebase-collections";
// The client connects to your backend API and WebSocketconst rebaseClient = createRebaseClient({ baseUrl: "http://localhost:3001", websocketUrl: "ws://localhost:3001"});
// Collections are imported via a Vite virtual module// that reads from the shared/ directoryKey Concepts
Section titled “Key Concepts”createRebaseClient— Creates the SDK client that handles HTTP requests, WebSocket connections, and auth token managementvirtual:rebase-collections— A Vite plugin that auto-imports your shared collections at build time- Controllers —
useBuildNavigationStateController,useBuildCollectionRegistryController, etc. — these configure routing, collection resolution, and UI configuration
Backend (backend/)
Section titled “Backend (backend/)”The backend is a Node.js server built on Hono (a fast, lightweight HTTP framework). The entry point index.ts initializes everything:
import { initializeRebaseBackend } from "@rebasepro/backend";import { Hono } from "hono";
const app = new Hono();
await initializeRebaseBackend({ app, server, collections, driver: { connection: db, schema: { tables, enums, relations } }, auth: { jwtSecret: process.env.JWT_SECRET!, google: { clientId: process.env.GOOGLE_CLIENT_ID }, }, storage: { type: "local", basePath: "./uploads" }, history: true});initializeRebaseBackend sets up:
- REST API routes at
/api/data/*— auto-generated CRUD for each collection - Auth routes at
/api/auth/*— signup, login, refresh, Google OAuth - Storage routes at
/api/storage/*— file upload/download - WebSocket server — real-time entity sync via Postgres LISTEN/NOTIFY
- History — audit trail recording on every entity change
Shared Collections (shared/)
Section titled “Shared Collections (shared/)”Collections are the single source of truth for your data model. They are defined as TypeScript and consumed by both the frontend (for UI generation) and the backend (for schema generation and API routing).
import { EntityCollection } from "@rebasepro/types";
export const productsCollection: EntityCollection = { slug: "products", name: "Products", dbPath: "products", properties: { name: { type: "string", name: "Name" }, price: { type: "number", name: "Price" } }};The slug becomes the URL path in the admin UI and the REST API endpoint (/api/data/products). The dbPath maps to the PostgreSQL table name.
How They Connect
Section titled “How They Connect”- You define collections in
shared/ - The backend reads them to generate Drizzle schemas and mount REST routes
- The frontend reads them (via Vite plugin) to render tables, forms, and navigation
- The CLI reads them to generate migration files with
rebase schema generate
Changes to collections propagate everywhere automatically.
Next Steps
Section titled “Next Steps”- Template Walkthrough — Line-by-line explanation of the generated code
- Configuration — All environment variables and options