Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Quick Start

Build a complete application with Postbase in 10 minutes.

What We'll Build

A simple task management API with:

  • Users table with authentication fields
  • Tasks table with foreign key to users
  • Database migrations
  • Type-safe queries with the SDK

Step 1: Initialize Project

# Create project directory
mkdir my-task-app
cd my-task-app
 
# Initialize npm project
npm init -y
 
# Install dependencies
npm install @postbase/sdk pg dotenv
npm install -D typescript @types/node tsx

Step 2: Start Postbase

# Start the daemon (in another terminal)
postbase start
 
# Create database
postbase db create tasks
 
# Initialize Postbase config
postbase init

This creates a postbase.toml file:

[project]
name = "my-task-app"
 
[database]
name = "tasks"
 
[migrations]
directory = "./migrations"
schema = "public"

Step 3: Create Migrations

# Create users migration
postbase migrate new create_users

Edit migrations/YYYYMMDD_create_users.up.sql:

-- Create users table
CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  email VARCHAR(255) UNIQUE NOT NULL,
  name VARCHAR(255) NOT NULL,
  password_hash VARCHAR(255) NOT NULL,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
 
-- Create index for email lookups
CREATE INDEX idx_users_email ON users(email);

Edit migrations/YYYYMMDD_create_users.down.sql:

DROP TABLE IF EXISTS users;
# Create tasks migration
postbase migrate new create_tasks

Edit migrations/YYYYMMDD_create_tasks.up.sql:

-- Create tasks table
CREATE TABLE tasks (
  id SERIAL PRIMARY KEY,
  user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  title VARCHAR(255) NOT NULL,
  description TEXT,
  status VARCHAR(50) DEFAULT 'pending',
  due_date DATE,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
  updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
 
-- Create indexes
CREATE INDEX idx_tasks_user_id ON tasks(user_id);
CREATE INDEX idx_tasks_status ON tasks(status);

Step 4: Apply Migrations

# Apply all pending migrations
postbase migrate up
 
# Check status
postbase migrate status

Output:

Migration Status for tasks (public)
 
Applied:
  ✓ 20260125_create_users (applied: 2026-01-25 10:30:00)
  ✓ 20260125_create_tasks (applied: 2026-01-25 10:30:01)
 
Pending: 0

Step 5: Generate Types

# Generate TypeScript types
postbase types generate \
  --database tasks \
  --all \
  --output ./src/db/types.ts

This creates src/db/types.ts:

export interface Database {
  public: {
    Tables: {
      users: {
        Row: {
          id: number
          email: string
          name: string
          password_hash: string
          created_at: Date
          updated_at: Date
        }
        Insert: {
          email: string
          name: string
          password_hash: string
          created_at?: Date
          updated_at?: Date
        }
        Update: {
          email?: string
          name?: string
          password_hash?: string
          updated_at?: Date
        }
      }
      tasks: {
        Row: {
          id: number
          user_id: number
          title: string
          description: string | null
          status: string
          due_date: Date | null
          created_at: Date
          updated_at: Date
        }
        Insert: {
          user_id: number
          title: string
          description?: string | null
          status?: string
          due_date?: Date | null
        }
        Update: {
          title?: string
          description?: string | null
          status?: string
          due_date?: Date | null
          updated_at?: Date
        }
      }
    }
  }
}

Step 6: Create Database Client

Create src/db/client.ts:

import { createClient } from '@postbase/sdk'
import type { Database } from './types'
 
export const db = createClient<Database>({
  connectionString: process.env.DATABASE_URL || 
    'postgresql://postgres:postgres@localhost:5432/tasks',
})

Step 7: Build Your Application

Create src/index.ts:

import { db } from './db/client'
 
async function main() {
  // Create a user
  const user = await db
    .from('users')
    .insert({
      email: 'alice@example.com',
      name: 'Alice',
      password_hash: 'hashed_password_here',
    })
    .returning()
    .single()
 
  console.log('Created user:', user)
 
  // Create some tasks
  await db.from('tasks').insert([
    { user_id: user.id, title: 'Learn Postbase', status: 'in_progress' },
    { user_id: user.id, title: 'Build an app', status: 'pending' },
    { user_id: user.id, title: 'Deploy to cloud', status: 'pending' },
  ])
 
  // Query tasks
  const tasks = await db
    .from('tasks')
    .eq('user_id', user.id)
    .order('created_at', { ascending: false })
    .execute()
 
  console.log('Tasks:', tasks)
 
  // Update a task
  await db
    .from('tasks')
    .eq('title', 'Learn Postbase')
    .update({ status: 'completed' })
 
  // Get completed tasks
  const completed = await db
    .from('tasks')
    .eq('status', 'completed')
    .execute()
 
  console.log('Completed tasks:', completed)
}
 
main().catch(console.error)

Step 8: Run Your Application

# Run with tsx
npx tsx src/index.ts

Output:

Created user: { id: 1, email: 'alice@example.com', name: 'Alice', ... }
Tasks: [
  { id: 3, title: 'Deploy to cloud', status: 'pending', ... },
  { id: 2, title: 'Build an app', status: 'pending', ... },
  { id: 1, title: 'Learn Postbase', status: 'in_progress', ... },
]
Completed tasks: [
  { id: 1, title: 'Learn Postbase', status: 'completed', ... },
]

Step 9: Deploy to Cloud

# Login to Postbase Cloud
postbase cloud login
 
# Create a project
postbase cloud projects create my-task-app
 
# Provision staging database
postbase cloud provision staging
 
# Get connection string
postbase cloud url staging

Update your .env:

DATABASE_URL=postgresql://postgres:xxx@xxx.proxy.rlwy.net:12345/my_task_app_staging

Next Steps