Documentation

Get started with PreCheck

Self-hosted backend in one container. REST, Auth, Realtime, Functions, Storage, Cron, and AI.

Quick Start

Up and running in under 2 minutes.

1

Start the stack

git clone https://github.com/your-org/precheck
cd precheck
docker compose up -d

Starts PostgreSQL 17, NATS, MinIO, and the PreCheck gateway on http://localhost:8080.

2

Install the SDK

npm install @precheck/client

import { PreCheckClient } from '@precheck/client'

const client = new PreCheckClient({
  url: 'http://localhost:8080',
  anonKey: 'YOUR_ANON_KEY',
  tenantId: 'YOUR_TENANT_ID',
})

Get your anonKey and tenantId from the cloud dashboard after creating a project.

3

Query your database

const rows = await client.from('my_table').limit(10).select()
console.log(rows)

The Auto-REST layer automatically exposes every table in your project's schema. See the Database section for the full query API.

Authentication

Built-in user accounts with JWT access tokens. Sign up, sign in, and manage sessions with a single call.

// Sign up a new user
const { access_token, user } = await client.auth.signUp(
  '[email protected]',
  'password',
)

// Sign in an existing user
const { access_token } = await client.auth.signIn(
  '[email protected]',
  'password',
)

// Get the current user
const user = await client.auth.getUser(access_token)

// Sign out
await client.auth.signOut(access_token)
Service role: Admin operations (listing all users, bypassing RLS) require the service-role key — available in your project settings.

Database

Fluent query builder over your PostgreSQL tables. Supports filtering, ordering, pagination, and all four CRUD operations.

// Select with filters
const todos = await client.from('todos')
  .filter('done', 'eq', false)
  .order('created_at', false)
  .limit(50)
  .select()

// Insert a row
const todo = await client.from('todos').insert({
  content: 'Buy milk',
  done: false,
})

// Update
await client.from('todos').update(id, { done: true })

// Delete
await client.from('todos').delete(id)
filter(col, op, val)

eq · neq · gt · gte · lt · lte · like · ilike

order(col, asc?)

Sort ascending (true) or descending (false)

limit(n)

Max rows returned, default 100

offset(n)

Skip n rows for pagination

Realtime

Every INSERT, UPDATE, and DELETE streams to connected clients over WebSocket, backed by PostgreSQL logical replication. Subscribe to multiple topics on one connection using wildcard patterns — db:orders:* matches all order events.

const channel = client.realtime
  .channel('db:todos:*')
  .on('INSERT', (row) => console.log('Added:', row))
  .on('UPDATE', (row) => console.log('Updated:', row))
  .on('DELETE', (row) => console.log('Removed:', row))

channel.subscribe(access_token)

// Later — clean up
client.realtime.close()

Storage

S3-compatible object storage backed by MinIO. Upload files, list buckets, generate signed download URLs, and delete objects.

// Upload a file
await client.storage.upload(
  'avatars',
  'user-123.png',
  fileBlob,
  'image/png',
)

// List objects in a bucket
const files = await client.storage.list('avatars')
// [{ name: 'user-123.png', size: 42000, last_modified: '...' }]

// Get a time-limited signed URL
const url = await client.storage.signedUrl('user-123.png', 3600)

// Delete an object
await client.storage.delete('user-123.png')

Functions

Deploy serverless JavaScript functions via the dashboard or the Functions API, then invoke them with any JSON payload.

// Deploy a function via the dashboard or API, then invoke it:
const result = await client.functions.invoke<{ greeting: string }>(
  'hello',
  { name: 'World' },
)
console.log(result.greeting) // 'Hello, World!'

// Functions can return any JSON-serializable value
const stats = await client.functions.invoke<{ count: number }>('get-stats')

API Reference

All routes served on http://localhost:8080. Authenticated routes require:

Authorization: Bearer <access_token>
X-Precheck-Tenant: <tenantId>

Self-hosting

PreCheck runs anywhere Docker runs. All configuration is via environment variables.

HTTP_PORT

REST + API port — default: 8080

DB_HOST

PostgreSQL hostname — default: localhost

JWT_SECRET

Secret used to sign tokens — default: (auto-generated)

NATS_URL

NATS server for realtime — default: nats://localhost:4222

MINIO_ENDPOINT

S3-compatible storage — default: http://localhost:9000

ENABLE_AI

Load ONNX + llama.cpp models — default: false

CLOUD_ADMIN_EMAIL

Bootstrap admin account email — default: [email protected]

CLOUD_ADMIN_PASSWORD

Bootstrap admin account password — default: changeme123

Full configuration reference on GitHub →