Quick Start
Boot a real Lux engine on your machine, build against it with the SDK, then ship to Lux Cloud by swapping a single URL. The same code runs in both places.
1. Install the CLI
curl -fsSL https://luxdb.dev/install.sh | sh2. Start a local engine
lux start boots the open-source Lux engine in Docker, applies your
migrations, seeds a fresh database, and writes .env.local with the local LUX_URL and keys. Requires Docker.
lux init
lux startLocal Lux engine
LUX_URL http://localhost:5890
LUX_DIRECT_URL lux://:lux_sec_local_…@localhost:6379
LUX_PUBLISHABLE_KEY lux_pub_local_…
LUX_SECRET_KEY lux_sec_local_…
Data volume lux-local-data
Written to .env.local. Point the SDK at LUX_URL.3. Add schema and a grant
Migrations are .lux files. Lux is deny-by-default for end users, so a GRANT defines which rows a signed-in user can read and write. The grant's
predicate is applied automatically as a row filter.
lux migrate new create_messages
# edit lux/migrations/<timestamp>_create_messages.lux:
TCREATE messages id UUID PRIMARY KEY DEFAULT uuid(), body STR, owner STR, created_at INT DEFAULT now()
GRANT read, write ON messages WHERE owner = auth.uid()
# apply it (lux start also runs pending migrations on boot)
lux migrate run4. Use the SDK
Point any client at LUX_URL. On the server, the secret key has full access:
import { createClient } from "@luxdb/sdk";
// The secret key has full access (like a service role). Server-side only.
const lux = createClient(process.env.LUX_URL, process.env.LUX_SECRET_KEY);
const { data, error } = await lux
.table("messages")
.insert({ body: "hello", owner: "00000000-0000-0000-0000-000000000000" });
if (error) throw error;
console.log(data); // the inserted row, incl. generated id + created_atIn the browser, the publishable key exposes nothing until a user signs in
and a grant matches them:
import { createBrowserClient } from "@luxdb/sdk";
// The publishable key is safe for the browser. It has NO data access until a
// user signs in and a grant matches them (deny-by-default).
const lux = createBrowserClient(import.meta.env.VITE_LUX_URL, import.meta.env.VITE_LUX_PUBLISHABLE_KEY);
await lux.auth.signInWithPassword({ email: "user@example.com", password: "…" });
// With the grant above, this returns only the signed-in user's rows.
const { data, error } = await lux.table("messages").select().order("created_at", { ascending: false });5. Ship to Lux Cloud
When you're ready for a hosted, backed-up, four-nines database, create a Cloud project and pull
its env. Your app code doesn't change. Only LUX_URL and the keys do.
lux login
lux create my-app --accept-charges
lux link my-app
lux env pull # writes .env with the prod LUX_URL + keysStop the local engine any time with lux stop (add --clear to wipe local data).
Next
Read the SDK guide, CLI guide, Auth guide, and Tables guide.