Version: closed alpha

Quick Start

Build a real full-stack app — an API, a database, and a website — and deploy the whole thing with one command. About five minutes.

We'll build a small guestbook: a page with a form, an API that stores and lists the messages, and a database behind it. Along the way you'll touch all three Drift services — Atomic for the API, Backbone for the data, and Canvas for the site — and never leave your terminal.

1. Install the CLI

Everything on Drift happens through the drift command-line tool. If you have Go installed, one command puts it on your PATH:

go install github.com/ondrift/cli/cmd/drift@latest

Confirm it's there:

drift --version

2. Log in to your account

Drift is in closed alpha, so accounts are handed out by the platform admin — you'll have been sent a username and password. Use them to sign in:

drift account login

You'll be prompted for your username and password. The CLI keeps you signed in afterwards, so this is a one-time step on each machine.

3. Create a slice

A slice is your project's own private corner of Drift — its own functions, data, site, and URL, fully isolated from everyone else's. Make one for the guestbook:

drift slice create guestbook

That opens the configurator in your browser, where you dial in how much memory, storage, and so on the slice gets and watch the price update live. For this guide the defaults — a free Hacker slice — are more than enough. To skip the browser and take the free slice straight away (handy in scripts and CI):

drift slice create guestbook --free        # --headless is an alias

Then set it as the active slice so the commands below know where to deploy:

drift slice use guestbook

4. Lay out the project

A Drift project is just folders and a Driftfile. Each Atomic function lives in its own folder under atomic/; your site lives under canvas/. Here's the shape we're about to build:

guestbook/
├── Driftfile
├── atomic/
│   ├── sign/         # POST: save a message
│   └── entries/      # GET:  list messages
└── canvas/
    └── index.html    # the page visitors see

5. Write the API

An Atomic function is a normal source file with a one-line directive on top. The directive — not a config file — declares how the function is reached: the HTTP method, the route, and whether it needs authentication. Here's the endpoint that saves a message, in Go (atomic/sign/sign.go):

// @atomic http=post:sign auth=none
package main

import drift "github.com/ondrift/sdk/go"

func PostSign(body map[string]any, _ drift.Request) (int, string, any, map[string]string) {
    id, _ := drift.NoSQL.Collection("guestbook").Insert(body)
    return 201, "Created", map[string]any{"id": id}, nil
}

And the one that lists messages back (atomic/entries/entries.go):

// @atomic http=get:entries auth=none
package main

import drift "github.com/ondrift/sdk/go"

func GetEntries(_ drift.Request) (int, string, any, map[string]string) {
    all, _ := drift.NoSQL.Collection("guestbook").List(nil)
    return 200, "OK", all, nil
}

Each function returns the HTTP status, a short status message, and the response body (the SDK serialises objects to JSON for you); in Go and Rust an optional headers map comes last — nil when you don't need one. The directive does the routing — http=post:sign means "POST, reachable at sign" — so there's no router to wire up.

Notice there's no database to set up: no connection string, no ORM, no migrations. drift.NoSQL.Collection("guestbook") is the data layer — the SDK talks to Backbone for you, and the collection springs into existence the first time you write to it.

6. Add the page

Canvas hosts your static site. Its best trick: a Canvas page can call its own functions on the same origin — the browser just fetches /api/sign and /api/entries, with no CORS to configure and no separate API domain. Save this as canvas/index.html:

<h1>Guestbook</h1>
<form id="form">
  <input name="name" placeholder="Your name" required>
  <input name="message" placeholder="Your message" required>
  <button>Sign</button>
</form>
<ul id="entries"></ul>
<script>
  fetch("/api/entries").then(r => r.json()).then(rows => {
    rows.forEach(e => entries.innerHTML += `<li><b>${e.name}</b>: ${e.message}</li>`);
  });
  form.onsubmit = async (ev) => {
    ev.preventDefault();
    await fetch("/api/sign", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(Object.fromEntries(new FormData(form)))
    });
    location.reload();
  };
</script>

7. Declare it in a Driftfile

The Driftfile ties the project together: it lists your functions by name, the collection they use, and your site — all at the top level (the file is the project). Save this as Driftfile at the project root:

name: guestbook
atomic:
  functions:
    - sign
    - entries
backbone:
  nosql:
    - guestbook
canvas:
  sites:
    - ./canvas

8. Deploy everything

One command reads the Driftfile, creates the collection, compiles and ships both functions, and publishes the site:

drift project deploy

Before changing anything, the CLI shows you exactly what it will create and whether your slice is free or what it costs — then asks you to confirm. (Deploys only ever create or grow a slice; to shrink one, use drift slice resize.)

9. See it live

Your slice answers at <username>-guestbook.ondrift.eu, with TLS already handled. Open that URL to use the guestbook in the browser, or hit the API directly:

# sign the guestbook
curl -X POST https://<username>-guestbook.ondrift.eu/api/sign \
  -H "Content-Type: application/json" \
  -d '{"name": "Alice", "message": "Hello from Drift!"}'

# read it back
curl https://<username>-guestbook.ondrift.eu/api/entries

10. Inspect it from the terminal

You can read and poke at your slice's data without leaving the shell:

# list what's in the guestbook collection
drift backbone nosql read --collection guestbook

# store a secret (injected into your functions on the next deploy)
drift backbone secret set API_KEY=sk-12345

# push a message onto a queue
drift backbone queue push notify '{"to": "alice", "text": "welcome!"}'

# cache a value for an hour
drift backbone cache set greeting "hello world" --ttl 3600

# check the slice's health and usage
drift backbone status

Write in your language

Functions can be written in Go, Python, Node.js, Ruby, PHP, or Rust — the CLI detects the language from your source files. The same "sign" endpoint looks like this in Python…

# @atomic http=post:sign auth=none
import drift

def post_sign(body, req):
    entry_id = drift.nosql.collection("guestbook").insert(body)
    return 201, "Created", {"id": entry_id}

…and in Node.js:

// @atomic http=post:sign auth=none
const drift = require("@ondrift/sdk");

async function postSign(body, req) {
    const id = await drift.nosql.collection("guestbook").insert(body);
    return [201, "Created", { id }];
}

module.exports = { postSign };

Deploy any of them the same way — with the Driftfile, or one at a time with drift atomic deploy ./atomic/sign.

Take your data and go

Drift has no lock-in. At any point you can snapshot a slice and download the whole thing — source code, database contents, secrets, and static sites, with no Drift-specific files in the archive:

drift slice snapshot create --name my-backup
drift slice snapshot download <snapshot-id>

Optional: use your own domain

Your slice already answers at <username>-guestbook.ondrift.eu, but you can point your own hostname at it — Drift verifies ownership and issues the TLS certificate for you. Add a domain to your active slice:

drift slice domain add guestbook.example.com

The CLI prints two DNS records to create at your registrar:

# 1. prove you own the domain
_drift-challenge.guestbook.example.com.  TXT    "drift-verify=<token>"

# 2. route the hostname to your slice
#    (or an A record to the platform's IP at a zone apex, where CNAMEs aren't allowed)
guestbook.example.com.                   CNAME  ingress.ondrift.eu.

Once DNS has propagated, verify — Drift checks the TXT record and starts issuing the certificate:

drift slice domain verify guestbook.example.com

Watch it go live (and see every domain on the slice) with:

drift slice domain list

When the status reads active, your guestbook is live on your own domain — HTTPS and all.