Struttura del progetto
Un progetto iniziale Rebase presenta tre pacchetti interconnessi:
my-app/├── .env # Generated for you: JWT_SECRET, a database password, a free port├── rebase.json # Which apps this repository contains, and how each is built├── package.json # Root workspace config├── tsconfig.json # Typechecks scripts/; each workspace typechecks on its own├── docker-compose.yml # Self-hosting: Postgres + the published runtime image├── scripts/│ └── example.ts # The SDK end to end against the running backend: `pnpm example`│├── config/ # Shared by the backend and the admin panel│ ├── index.ts # Re-exports `collections`; the runtime reads `storageAuthorize` from here│ ├── collections/ # Your data model│ │ ├── index.ts # Sort order (`collections`) and `defaultSecurityRules` — not a registry│ │ ├── posts.ts # Example collections│ │ └── users.ts # The auth collection│ ├── resources.ts # What this project needs from wherever it runs│ ├── storage.ts # Who may read, write and list files│ └── cms.d.ts # One line that makes the `admin` block legal here│├── backend/│ ├── functions/ # Custom API routes, auto-mounted at /api/functions/<name>│ │ └── hello.ts│ └── src/│ └── schema.generated.ts # Drizzle schema, regenerated from your collections│└── frontend/ # The admin panel (React + Vite) ├── src/App.tsx ├── src/main.tsx └── vite.config.tstsc --noEmit alla radice controlla scripts/; in config/, backend/ o frontend/
controlla quel workspace. Da 0.25
Su 0.24 la radice non ha un tsconfig.json, e tsc lì stampa il proprio aiuto e non
controlla nulla.
Frontend (frontend/)
Sezione intitolata “Frontend (frontend/)”Il frontend è una tipica applicazione Vite + React + TypeScript. Il file principale è App.tsx, che collega tra loro tutti i controller Rebase:
import React from "react";
import "@fontsource/jetbrains-mono";import "@fontsource-variable/inter";import "@fontsource-variable/instrument-sans";
import { Rebase, RebaseAuth, useRebaseAuthController } from "@rebasepro/app";import { RebaseCMS, RebaseShell } from "@rebasepro/cms";import { ErrorBoundary } from "@rebasepro/ui";import { RebaseStudio } from "@rebasepro/studio";import { createRebaseClient } from "@rebasepro/client";import { collections } from "virtual:rebase-collections";
// `rebase dev` injects VITE_API_URL with the port it actually bound, and that// port is derived from this project's path rather than fixed — so a// `http://localhost:3001` fallback here names a port nothing is listening on.// A deployed build serves the admin from the same origin as the API, where an// empty value is exactly what you want.const API_URL = import.meta.env.VITE_API_URL;const GOOGLE_CLIENT_ID = import.meta.env.VITE_GOOGLE_CLIENT_ID;
export function App() { const rebaseClient = React.useMemo(() => createRebaseClient({ baseUrl: API_URL, // Store the refresh token in an httpOnly cookie (XSS-safe) rather than // localStorage. The backend issues it via `auth.cookieAuth`. auth: { authFlowMode: "cookie" } }), []);
const authController = useRebaseAuthController({ client: rebaseClient, googleClientId: GOOGLE_CLIENT_ID });
return ( <ErrorBoundary fullPage> <Rebase client={rebaseClient} authController={authController} > {/* The sign-in screen. On its own this changes nothing — it is where you pass `loginView` to replace it. */} <RebaseAuth /> <RebaseCMS collections={collections} /> <RebaseStudio/> <RebaseShell title="Rebase"/> </Rebase> </ErrorBoundary> );}main.tsx lo monta sotto un basename di react-router ricavato da import.meta.env.BASE_URL, che rebase build imposta a partire dal path dichiarato da questa app in rebase.json — in questo modo gli asset, il router e il server concordano su un unico valore senza doverlo scrivere tre volte.
Concetti chiave
Sezione intitolata “Concetti chiave”createRebaseClient— Crea il client SDK che gestisce le richieste HTTP, le connessioni WebSocket e la gestione dei token di autenticazionevirtual:rebase-collections— Un plugin Vite che importa automaticamente le collection condivise al momento della compilazioneuseRebaseAuthController— Mantiene l’utente autenticato e il ciclo di vita del token, ed è ciò che<Rebase>distribuisce a tutto ciò che si trova al suo interno
Backend (backend/)
Sezione intitolata “Backend (backend/)”Non c’è alcun file server da leggere, ed è proprio così che è stato progettato: un progetto creato tramite scaffold dichiara runtime: "managed", quindi l’immagine pubblicata rebasepro/server avvia il tuo progetto. Ciò che contiene backend/ è il codice rilevato dal runtime:
| Percorso | Cos’è |
|---|---|
backend/functions/ |
Route personalizzate, montate automaticamente su /api/functions/<filename> |
backend/crons/ |
Job pianificati, individuati allo stesso modo (crea la cartella quando ne hai bisogno) |
backend/src/schema.generated.ts |
Lo schema Drizzle delle tue collection: scritto da rebase init e rigenerato a ogni rebase dev e rebase build |
Il runtime configura:
- REST API su
/api/data/*— CRUD generato per ogni collection - Autenticazione su
/api/auth/*— registrazione, login, refresh, OAuth - Storage su
/api/storage/*— upload e download - WebSocket — sincronizzazione in tempo reale tramite LISTEN/NOTIFY di Postgres
- Funzioni e cron, dalle directory sopra indicate
La configurazione proviene da rebase.json, dalla directory config/ e dalle variabili d’ambiente. Consulta Ambiente e configurazione.
rebase build trasforma tutto questo in un bundle — le collection compilate, le funzioni e i cron oltre a un manifest — che il runtime gestito avvia. Nessuna parte del bundle viene scritta a mano; se vuoi vederne uno, Runtime e bundle ne descrive il contenuto.
Il pannello fornito dal frontend ha due parti. Studio è quella per gli sviluppatori — l’editor di schemi, la console SQL, il browser delle policy RLS — ed è accessibile tramite il selettore nel drawer, non come deployment separato. Consulta Studio.
Se desideri invece prendere il controllo del processo — con middleware, route e logica di autenticazione personalizzati — esegui rebase eject. Tutto ciò che segue questo paragrafo si applica solo dopo un eject: un progetto generato tramite scaffold non possiede nessuno di questi file e nulla al suo interno chiama initializeRebaseBackend. Il comando genera un entry point che chiama direttamente initializeRebaseBackend, oltre a un Dockerfile e a un file compose per la compilazione; da quel momento in poi sarai tu a gestire il server e gli aggiornamenti del runtime della piattaforma non interesseranno più il progetto. Quest’area è documentata in Integrazione server personalizzato.
Collection (config/collections/)
Sezione intitolata “Collection (config/collections/)”Le collection rappresentano l’unica fonte di verità per il tuo modello di dati. Sono definite in TypeScript e utilizzate sia dal frontend (per la generazione dell’interfaccia utente) che dal backend (per la generazione dello schema e il routing delle API).
import { defineCollection } from "@rebasepro/cms-types";
const productsCollection = defineCollection({ slug: "products", name: "Products", properties: { name: { type: "string", name: "Name" }, price: { type: "number", name: "Price" } }});
// The default export is what the loader picks up — every file in this directory// is loaded, listed in index.ts or not, and every collection in the scaffold is// written this way.export default productsCollection;Lo slug diventa il percorso URL nell’interfaccia di amministrazione e l’endpoint dell’API REST (/api/data/products), e il nome della tabella PostgreSQL corrisponde ad esso per impostazione predefinita. Aggiungi table solo se differiscono.
Come si collegano tra loro
Sezione intitolata “Come si collegano tra loro”- Tu definisci le collection in
config/collections/ - Il backend le legge per generare gli schemi Drizzle e registrare le route REST
- Il frontend le legge (tramite il plugin Vite) per renderizzare tabelle, moduli e navigazione
- La CLI le legge per generare lo schema Drizzle (
rebase schema generate), i tipi dell’SDK (rebase generate-sdk) e, a partire da quello schema, i file di migrazione (rebase db generate)
Mentre rebase dev è in esecuzione, il salvataggio di un file all’interno di config/collections/ rigenera backend/src/schema.generated.ts e i tipi dell’SDK in generated/sdk/ e riavvia il backend; all’avvio vengono create le tabelle e le colonne mancanti. Al di fuori di rebase dev, gli stessi passaggi corrispondono a rebase schema generate e rebase generate-sdk.
Sulla 0.23, rebase dev rigenera solo lo schema, e rebase generate-sdk
resta un passaggio separato.
Prossimi passi
Sezione intitolata “Prossimi passi”- Avvio rapido — Inizia con un nuovo progetto Rebase
- Configurazione — Tutte le variabili d’ambiente e le opzioni