# Getting started

Source: https://dabadata.com/docs/getting-started/ (HTML) - https://dabadata.com/docs/getting-started/index.md (this page as markdown)

Sign up for hosted dabadata, the realtime app backend, and you have a live row in a page of your own in a few minutes, with nothing to install. Everything on this page uses the hosted service at `https://dabadata.com`. Running dabadata on a server of your own is on [Self-hosting](https://dabadata.com/docs/self-hosting/index.md); it speaks the same API, so what you build moves from one to the other.

## Sign up

Open [https://dabadata.com/console/auth/register](https://dabadata.com/console/auth/register) and create an account with your email and a password. We mail you a confirmation link; open it **in the same browser**. Prefer no password? Use "Email me a link" on the sign-in page, or "Continue with Google" when it is offered. Free, no card. [Ways to sign in](https://dabadata.com/docs/accounts/index.md#sign-in) has the details.

## Your workspace and my-first-app

The confirmation signs you in to the [console](https://dabadata.com/docs/console/index.md), where two things are waiting:

- A **workspace** named after your email, on the Free plan, with you as its owner. It is where your team, your plan and your projects live.
- A project called **`my-first-app`** with a `tasks` table and the rules of the [demo](https://dabadata.com/demo/): anyone signed in reads tasks, admins and editors create them, an admin or the task's owner updates one, only admins delete.

Every project has a **live** and a **test** environment with their own data and keys. Flip the switch in the top bar to **test**: that is where you try things.

## Copy the keys

Open **Keys**. The environment the top bar is on comes first (the other one is folded below it). Each environment has two keys:

- The **publishable key** (`pk_test_...`) names the project from a browser. It grants nothing by itself and is safe in your page. Copy it.
- The **secret key** (`sk_test_...`) bypasses every rule and belongs on a server. It is shown once, when it is made, and the keys of `my-first-app` were made for you without being shown. Press **Rotate secret key** under the test keys, confirm, and copy the new one from the dialog. Rotating makes a new secret key and shows it once; the one it replaces keeps working for 24 hours, then stops.

Keep the secret key in your shell for the next step, not in any page:

```bash
export DABADATA_SECRET_KEY=sk_test_...   # the test secret key you just copied
```

## Get a user token

The `tasks` table is for signed-in people only, so the page needs someone to be. Your backend normally mints a token for each person after its own sign-in; for now, mint one by hand:

```bash
curl -X POST https://dabadata.com/v1/users/token \
  -H "Authorization: Bearer $DABADATA_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{"id":"alice","name":"Alice","role":"editor"}'
```

```json
{ "token": "<user token>", "expiresAt": "...", "refreshToken": "<refresh token>", "refreshExpiresAt": "..." }
```

Alice is an `editor`, so she may create tasks. The token lives an hour; mint another when it runs out. Later you can let people sign up and sign in by themselves instead: [Sign-in for your app's users](https://dabadata.com/docs/end-user-auth/index.md).

## Paste the snippet

**Keys -> Snippets -> Plain HTML** gives you a page built from your real values. Here it is with Alice's token and a form to add a task. Save it as `index.html`, put in your publishable key and the token, and open it in a browser:

```html
<!doctype html>
<meta charset="utf-8">
<title>my-first-app</title>
<form id="add"><input name="title" placeholder="New task" required> <button>Add</button></form>
<ul id="rows"></ul>

<script src="https://dabadata.com/client/dist/dabadata.iife.js"></script>
<script>
  const db = dabadata.createClient({
    url: "https://dabadata.com",
    key: "pk_test_EXAMPLEexample0000000000", // identifies the project (test); safe in a browser
    token: "<user token>",                    // Alice, from the curl above
  });

  const rows = new Map();
  const list = document.getElementById("rows");
  const render = () => list.replaceChildren(...[...rows.values()].map((r) =>
    Object.assign(document.createElement("li"), { textContent: r.title })));

  db.subscribe("tasks", {}, {
    onRows(all) { rows.clear(); for (const r of all) rows.set(r.id, r); render(); },
    onChange({ op, row }) { if (op === "delete") rows.delete(row.id); else rows.set(row.id, row); render(); },
    onError(err) { console.warn(err.explanation ?? err.message); },
  });

  document.getElementById("add").onsubmit = async (e) => {
    e.preventDefault();
    await db.insert("tasks", { title: new FormData(e.target).get("title") });
    e.target.reset();
  };
</script>
```

## Your first live row

Open the page in two tabs and add a task in one: it appears in both at once. dabadata filled in `owner` with Alice's id and `done` with its default, and sent the new row to every subscription allowed to read it. Back in the console, the **Overview** of the test environment now says **Your app is live**, and the call is in the trace with the rule that allowed it.

Now try a role that may not create: mint a token for `{"id":"carol","role":"viewer"}`, use it in the page and add a task. The insert is refused, and the browser console shows why: `create tasks: denied, role "viewer" not in ["admin","editor"]`.

Where to go from here:

- [Sign-in for your app's users](https://dabadata.com/docs/end-user-auth/index.md) - let people sign up, with hosted pages or `db.auth`, instead of minting tokens.
- [Tables](https://dabadata.com/docs/tables/index.md) and [Rules](https://dabadata.com/docs/rules/index.md) - your own tables and policy, applied as a definition ([Definitions on a hosted project](https://dabadata.com/docs/tables/index.md#hosted)).
- [Invite your team](https://dabadata.com/docs/accounts/index.md#invitations) and see [what each console page does](https://dabadata.com/docs/console/index.md).
- When it works on test, apply the same definition to live, switch the page to the live publishable key and [put it online](https://dabadata.com/docs/getting-started/index.md#hosting).

## Hosting your app

The quickest way to put a static app online - a plain HTML page, or the build output of Vite, React, Vue, Svelte or Solid - is a [site](https://dabadata.com/docs/sites/index.md) on dabadata itself: `dabadata sites deploy ./dist --site my-app` puts it at `https://my-app.dabadata.site`, next to its data, and adds that address to the environment's allowed origins for you. Your own domain can be connected from Starter.

Any other static host works too, such as [Cloudflare Pages](https://pages.cloudflare.com/), [Netlify](https://www.netlify.com/) or [GitHub Pages](https://pages.github.com/). The page talks to `https://dabadata.com` straight from the browser with the publishable key, so there is nothing else to deploy.

1. Put the site online and note its address, for example `https://my-app.pages.dev`.
2. In the console, open **Settings -> Project** on the environment the page uses and set its allowed origins (CORS) to that address. Then only your site can use the publishable key from a browser ([Allowed origins](https://dabadata.com/docs/projects/index.md#cors)). Keep `http://localhost:5173` or similar on test while you develop.
3. The page on live uses the live publishable key; a preview build can keep the test key.

Anything that needs the secret key - minting user tokens, scripts, applying definitions - runs on a server or a serverless function of your own, never in the page.

## From the terminal

The `dabadata` command-line tool does what the console does, from a terminal or a script: sign in once through the browser, then pull and push definitions, follow the trace and the logs, run SQL and export.

```bash
dabadata login                        # shows a code; approve it in the console
dabadata projects list
dabadata use prj_xxxxxxxxxxxx:test    # the project and environment later commands act on
dabadata pull                         # the definition in force -> dabadata.json
dabadata types                        # TypeScript types of it -> dabadata-types.ts (createClient<Database>)
dabadata push                         # dry run, then apply on confirm (.json, or a .ts evaluated locally)
dabadata migrate rename tasks.title name --definition dabadata.json   # keep the values; also drop-table, drop-column, retype
dabadata trace tail                   # every call as it happens, with the rule that decided it
dabadata sql "select count(*) from tasks"
dabadata mcp setup claude-code        # the one-line MCP setup for your coding agent
```

`dabadata login` opens a console page that asks "Approve sign-in for the dabadata CLI on <your computer>?" with the code the terminal shows; check that the two match and press **Approve**. It is a single file per platform (macOS and Linux, ARM and Intel) with nothing to install beside it; `dabadata --help` lists every command. Its sign-in is an account token that acts with your role in the workspace, listed with your sessions on the account page, where you can revoke it.
