Lux Docs

Build on Lux without guessing.

Lux Cloud + OSS core

Product docs for the Lux runtime: tables, cache, vectors, realtime, time series, auth, HTTP, SDK, CLI, and self-hosting.

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

Install
curl -fsSL https://luxdb.dev/install.sh | sh

2. 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.

Local engine
lux init
lux start
Output
Local 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.

Migrations
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 run

4. Use the SDK

Point any client at LUX_URL. On the server, the secret key has full access:

Server (secret key)
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_at

In the browser, the publishable key exposes nothing until a user signs in and a grant matches them:

Browser (publishable key)
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.

Cloud
lux login
lux create my-app --accept-charges
lux link my-app
lux env pull            # writes .env with the prod LUX_URL + keys

Stop 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.