SemiLayerDocs

Quickstart

Get SemiLayer running in under 5 minutes. You'll connect a database, push a schema, and pick the integration path that fits your stack.

ℹ️

Prerequisites: Node.js 18+, a running database with data, and a SemiLayer account. No account yet? Sign up at console.semilayer.com.

Install the CLI

npm install -g @semilayer/cli
semilayer --version

Setup

1
Log in
semilayer login

A browser window opens. Sign in (or create an account) and authorize the CLI. The token is stored locally — all subsequent commands are authenticated.

2
Initialize your project

Run init in the root of your application:

semilayer init

You'll be prompted to select or create an Organization, Project, and Environment. The selection is stored in .semilayerrc.

✓ Organization: acme-corp
✓ Project:      my-app
✓ Environment:  development
3
Connect a database

Add a Source — a connection to your existing database. SemiLayer reads from it during ingest and never writes to it.

semilayer source add \
  --name main-db \
  --bridge @semilayer/bridge-postgres \
  --connection-string "postgresql://user:pass@host:5432/mydb"
💡

Other bridges: MySQL, MongoDB, CockroachDB, and more. See Bridge SDK for the full list.

4
Define a Lens

A Lens is a declaration of intelligence over a table. Open (or create) sl.config.ts:

import { defineConfig } from '@semilayer/core'

export default defineConfig({
  stack: 'my-app',

  sources: {
    'main-db': {
      bridge: '@semilayer/bridge-postgres',
    },
  },

  lenses: {
    products: {
      source: 'main-db',
      table: 'public.products',
      primaryKey: 'id',
      fields: {
        id:          { type: 'number' },
        name:        { type: 'text', searchable: true },
        description: { type: 'text', searchable: true },
        category:    { type: 'text' },
        price:       { type: 'number' },
      },
      facets: {
        search:  { fields: ['name', 'description'] },
        similar: { fields: ['name', 'description'] },
      },
    },
  },
})

Fields with searchable: true are concatenated and embedded for semantic search. All fields appear in results. See Schema (Config) for the full spec.

5
Push and ingest

Register the Lens (paused — no data yet):

semilayer push
# ✓ Lens "products" created (status: paused)

Start the ingest pipeline:

semilayer push --resume-ingest

Watch progress:

semilayer status
# products  indexing  1,247 / 3,500  35%  ~2m remaining

When status reaches ready, queries are live.


Choose your integration path

Pick the approach that fits your stack. All paths use the same API key and deliver the same results.

Path A — Generated Beam client

This is the recommended path for TypeScript apps. Generate a fully-typed client from your config:

semilayer generate

This creates a semilayer/ directory with typed classes for every Lens in your config. Re-run generate whenever you change sl.config.ts.

import { createBeam } from './semilayer'

const beam = createBeam({
  baseUrl: 'https://api.semilayer.com',
  apiKey: process.env.SEMILAYER_API_KEY!,
})

// Semantic search — SearchResponse<ProductsMetadata>
const { results } = await beam.products.search({
  query: 'eco-friendly water bottle',
  limit: 10,
})
// results[0].metadata.name    ← typed as string (from your config)
// results[0].metadata.price   ← typed as number
// results[0].score            ← number, 0-1 cosine similarity

// Find similar items by record ID
const { results: similar } = await beam.products.similar({ id: '42', limit: 5 })

// Direct query through your bridge — QueryResponse<ProductsMetadata>
const { rows } = await beam.products.query({
  where: { category: 'footwear' },
  limit: 20,
})
// rows[0].name, rows[0].price — typed directly as ProductsMetadata

// Stream results as they arrive (chunked)
for await (const result of beam.products.stream.search({
  query: 'eco-friendly water bottle',
})) {
  render(result) // SearchResult<ProductsMetadata>, arrives before full page loads
}

// Live tail — every insert / update / delete in real time
for await (const event of beam.products.stream.subscribe()) {
  console.log(event.kind, event.record) // 'insert' | 'update' | 'delete'
}

// Observe one record — current state + every subsequent change
for await (const snapshot of beam.products.observe('42')) {
  setState(snapshot) // ProductsMetadata
}

See Beam Client for the full API reference.

What's next?

  • Concepts — Mental model: Organizations, Projects, Lenses, Facets, Beam
  • Schema (Config) — Complete sl.config.ts reference
  • Querying — Filters, pagination, search modes, streaming
  • Auth & RBAC — API key types, access rules, row-level security
  • HTTP & WebSocket — Write a client in any language
  • Bridge SDK — Add your own database adapter