insforge

Client-side SDK for database queries, authentication, file uploads, AI features, real-time messaging, and edge function invocation. Six core modules: Database (CRUD, filters, RPC), Auth (sign up/in, OAuth, sessions), Storage (upload/download/delete), Functions (edge function invoke), AI (chat, image generation, embeddings), and Real-time (WebSocket channels, publish/subscribe) All SDK methods return { data, error } objects; database inserts require array format and storage operations need both url and key saved to database Real-time channels use SQL triggers to auto-publish database changes; RLS policies control subscribe and publish access via realtime.channels and realtime.messages tables Includes RLS policy patterns for common scenarios (order access, chat membership) and best practices for channel pattern creation and trigger configuration

INSTALLATION
npx skills add https://github.com/insforge/agent-skills --skill insforge
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

InsForge SDK Skill

This skill covers client-side SDK integration using @insforge/sdk. For backend infrastructure operations (creating tables, inspecting schema, deploying functions, secrets, managing storage buckets, configuring Stripe keys/catalog, website deployments, cron job and schedules, logs, etc.), use the insforge-cli skill.

Quick Setup

1. Install the SDK

npm install @insforge/sdk@latest

2. Set up environment variables

Before using the SDK, create a .env file (or .env.local for Next.js) in your project root with your InsForge URL and anon key.

#### How to get your URL and anon key

-

Ensure the project is linked. Check for .insforge/project.json in the project root.

  • If it doesn't exist, run npx @insforge/cli link (existing project) or npx @insforge/cli create (new project) to generate it.

-

Get the anon key via the CLI:

npx @insforge/cli secrets get ANON_KEY

-

Get the URL from the oss_host field in .insforge/project.json (e.g., https://myapp.us-east.insforge.app).

-

Write both values to the .env file using the correct framework prefix (see table below).

Important: Use the anon key for SDK clients, including SSR. Use the API key only for privileged backend operations that need admin/service access; it is a full-access admin key, equivalent to a service role key on other platforms.

Use the correct environment variable prefix and access pattern for your framework:

Framework

.env file

Variables

Access Pattern

Next.js

.env.local

NEXT_PUBLIC_INSFORGE_URL, NEXT_PUBLIC_INSFORGE_ANON_KEY

process.env.NEXT_PUBLIC_*

Vite (React, Vue, Svelte)

.env

VITE_INSFORGE_URL, VITE_INSFORGE_ANON_KEY

import.meta.env.VITE_*

Astro

.env

PUBLIC_INSFORGE_URL, PUBLIC_INSFORGE_ANON_KEY

import.meta.env.PUBLIC_*

SvelteKit

.env

PUBLIC_INSFORGE_URL, PUBLIC_INSFORGE_ANON_KEY

import { env } from '$env/dynamic/public'

Create React App

.env

REACT_APP_INSFORGE_URL, REACT_APP_INSFORGE_ANON_KEY

process.env.REACT_APP_*

Node.js / Server

.env

INSFORGE_URL, INSFORGE_ANON_KEY

process.env.*

Example .env.local for Next.js:

NEXT_PUBLIC_INSFORGE_URL=https://your-appkey.us-east.insforge.app

NEXT_PUBLIC_INSFORGE_ANON_KEY=eyJhbGciOiJIUzI1NiIs...

Important: Never commit .env files to version control. Add .env, .env.local, and .env*.local to your .gitignore (keep .env.example for documenting required variables).

3. Initialize the client

import { createClient } from '@insforge/sdk'

// Next.js / CRA: use process.env

const insforge = createClient({

  baseUrl: process.env.NEXT_PUBLIC_INSFORGE_URL,

  anonKey: process.env.NEXT_PUBLIC_INSFORGE_ANON_KEY

})

// Vite / Astro: use import.meta.env

const insforge = createClient({

  baseUrl: import.meta.env.VITE_INSFORGE_URL,

  anonKey: import.meta.env.VITE_INSFORGE_ANON_KEY

})

Module Reference

Module

SDK Integration

Database

database/sdk-integration.md

Auth

auth/sdk-integration.md

Storage

storage/sdk-integration.md

Functions

functions/sdk-integration.md

AI

ai/sdk-integration.md

Real-time

realtime/sdk-integration.md

Email

email/sdk-integration.md

Payments

payments/sdk-integration.md

What Each Module Covers

Module

Content

Database

CRUD operations, filters, pagination, RPC calls

Auth

Sign up/in, OAuth, sessions, profiles, password reset

Storage

Upload, download, delete files; S3-compatible gateway for CI / backup tooling; write RLS policies for buckets

Functions

Invoke edge functions

AI

OpenRouter via OpenAI SDK, image/video generation, embeddings, deprecated InsForge SDK fallback

Email

Send custom transactional HTML emails (welcome, newsletter, notifications)

Payments

Stripe Checkout Sessions, subscriptions, and Billing Portal redirects

Real-time

Connect, subscribe, publish events, and track presence snapshots plus join/leave deltas

Guides

Guide

When to Use

database/postgres-rls.md

Writing or reviewing RLS policies — covers infinite recursion prevention, SECURITY DEFINER patterns, performance tips, and common InsForge RLS patterns

storage/s3-gateway.md

Fallback path when the consumer is existing S3 tooling (aws CLI, AWS SDKs, rclone, Terraform, boto3) and adopting @insforge/sdk is impractical — covers endpoint/region setup, access-key management, path-style addressing, and supported vs. not-supported S3 operations. Requires InsForge 2.0.9+. Prefer the SDK (storage/sdk-integration.md) for app code

storage/postgres-rls.md

Writing RLS policies for storage.objects — owner-only, public-read, path-scoped, team-shared, and the NULL uploaded_by caveat for mixed REST + S3 buckets

database/pgvector.md

Building semantic search, recommendations, or RAG — covers the vector extension, schema/dimensions, distance operators, HNSW/IVFFlat indexes, and RPC similarity search

ai/embeddings-and-rag.md

Generating embeddings through OpenRouter, storing them in pgvector, and wiring up a basic RAG pipeline with chat completions

payments/backend-configuration.md

Configuring Stripe keys, syncing catalog, creating products/prices, webhooks, and portal RLS before app integration

Building Checkout for a New App

Before integrating payments, make sure a Stripe key is configured. Run npx @insforge/cli payments status. If it shows unconfigured, ask the user for the Stripe key first. See payments/backend-configuration.md.

Real-time Configuration

For real-time channels and database triggers, use SQL migrations or database admin tooling to configure channels, triggers, and policies. The real-time SDK is for frontend event handling and messaging, not backend configuration.

#### Create Database Triggers

Automatically publish events when database records change.

-- Create trigger function

CREATE OR REPLACE FUNCTION notify_order_changes()

RETURNS TRIGGER AS $$

BEGIN

  PERFORM realtime.publish(

    'order:' || NEW.id::text,    -- channel

    TG_OP || '_order',           -- event: INSERT_order, UPDATE_order

    jsonb_build_object(

      'id', NEW.id,

      'status', NEW.status,

      'total', NEW.total

    )

  );

  RETURN NEW;

END;

$$ LANGUAGE plpgsql SECURITY DEFINER;

-- Attach to table

CREATE TRIGGER order_realtime

  AFTER INSERT OR UPDATE ON orders

  FOR EACH ROW

  EXECUTE FUNCTION notify_order_changes();

#### Conditional Trigger (Status Changes Only)

CREATE OR REPLACE FUNCTION notify_order_status()

RETURNS TRIGGER AS $$

BEGIN

  PERFORM realtime.publish(

    'order:' || NEW.id::text,

    'status_changed',

    jsonb_build_object('id', NEW.id, 'status', NEW.status)

  );

  RETURN NEW;

END;

$$ LANGUAGE plpgsql SECURITY DEFINER;

CREATE TRIGGER order_status_trigger

  AFTER UPDATE ON orders

  FOR EACH ROW

  WHEN (OLD.status IS DISTINCT FROM NEW.status)

  EXECUTE FUNCTION notify_order_status();

#### Access Control (RLS)

RLS is disabled by default. To restrict channel access:

  • Enable RLS
ALTER TABLE realtime.channels ENABLE ROW LEVEL SECURITY;

ALTER TABLE realtime.messages ENABLE ROW LEVEL SECURITY;
  • Restrict Subscribe (SELECT on channels)
CREATE POLICY "users_subscribe_own_orders"

ON realtime.channels FOR SELECT

TO authenticated

USING (

  pattern = 'order:%'

  AND EXISTS (

    SELECT 1 FROM orders

    WHERE id = NULLIF(split_part(realtime.channel_name(), ':', 2), '')::uuid

      AND user_id = auth.uid()

  )

);
  • Restrict Publish (INSERT on messages)
CREATE POLICY "members_publish_chat"

ON realtime.messages FOR INSERT

TO authenticated

WITH CHECK (

  channel_name LIKE 'chat:%'

  AND EXISTS (

    SELECT 1 FROM chat_members

    WHERE room_id = NULLIF(split_part(channel_name, ':', 2), '')::uuid

      AND user_id = auth.uid()

  )

);
  • Quick Reference

Task

SQL

Create channel

INSERT INTO realtime.channels (pattern, description, enabled) VALUES (...)

Create trigger

CREATE TRIGGER ... EXECUTE FUNCTION ...

Publish from SQL

PERFORM realtime.publish(channel, event, payload)

Enable RLS

ALTER TABLE realtime.channels ENABLE ROW LEVEL SECURITY

#### Best Practices

-

Create channel patterns first before subscribing from frontend

  • Insert channel patterns into realtime.channels table
  • Ensure enabled is set to true

-

Use specific channel patterns

  • Use wildcard % patterns for dynamic channels (e.g., order:% for order:123)
  • Use exact patterns for global channels (e.g., notifications)

#### Common Mistakes

Mistake

Solution

Subscribing to undefined channel pattern

Create channel pattern in realtime.channels first

Channel not receiving messages

Ensure channel enabled is true

Publishing without trigger

Create database trigger to auto-publish on changes

#### Recommended Workflow

1. Create channel patterns   → INSERT INTO realtime.channels

2. Ensure enabled = true     → Set enabled to true

3. Create triggers if needed → Auto-publish on database changes

4. Proceed with SDK subscribe → Use channel name matching pattern

Backend Configuration (Not Yet in CLI)

These modules still require HTTP API calls because the CLI does not yet support them:

Module

Backend Configuration

AI

ai/backend-configuration.md

Auth redirect URL allowlist is now managed via the CLI — use npx @insforge/cli config export/plan/apply. Other auth settings (password policy, OAuth providers, verification methods) still live on the dashboard. See the insforge-cli skill's Configuration section.

Risky backend changes? Use a branch first

When a code change in this skill depends on a schema migration, new RLS policy, OAuth provider config change, or any other backend change that could brick prod, create a backend branch first instead of editing the live project. Branches share JWT_SECRET (existing user JWTs keep working) but get a fresh database + EC2 + API_KEY / ANON_KEY, so you can test the SDK + backend change end-to-end in isolation.

The full branching workflow lives in the insforge-cli skill — see branch for the decision guide and lifecycle commands. Typical loop:

npx @insforge/cli branch create feat-x --mode schema-only

# ... apply migrations / change auth config / update RLS on the branch ...

# ... test the SDK against the branch backend ...

npx @insforge/cli branch merge feat-x --dry-run     # review SQL

npx @insforge/cli branch merge feat-x               # apply to parent

⚠ **After branch create or branch switch**, the SDK's INSFORGE_URL and INSFORGE_ANON_KEY change. Restart your dev server (or re-source .env) so the SDK starts talking to the branch backend. If you don't, the SDK will silently keep hitting parent — the #1 cause of "I switched but my changes aren't showing up".

SDK Quick Reference

All SDK methods return { data, error }.

Module

Methods

insforge.database

.from().select(), .insert(), .update(), .delete(), .rpc()

insforge.auth

.signUp(), .signInWithPassword(), .signInWithOAuth(), .signOut(), .getCurrentUser()

insforge.storage

.from().upload(), .uploadAuto(), .download(), .remove()

insforge.functions

.invoke()

insforge.ai

Deprecated fallback only: .chat.completions.create(), .images.generate(), .embeddings.create()

insforge.realtime

.connect(), .subscribe(), .publish(), .on(), .disconnect()

insforge.emails

.send({ to, subject, html, cc?, bcc?, from?, replyTo? })

insforge.payments

.createCheckoutSession(), .createCustomerPortalSession()

Important Notes

  • Database inserts require array format: insert([{...}]) not insert({...})
  • Next.js / SSR auth: Use createClient({ isServerMode: true }), keep tokens in httpOnly cookies, and perform auth flows on the server. See auth/sdk-integration.md
  • Storage: Save both url AND key to database for download/delete operations
  • Functions invoke URL: /functions/{slug} (without /api prefix)
  • Email — no SMTP, no third-party packages: Auth emails (signup verification, password reset, magic links, invites) ship on every plan. Custom email via insforge.emails.send() ships on every paid plan. **Never install nodemailer / resend / sendgrid / mailgun / postmark or ask for SMTP credentials** — the platform handles delivery. Custom sender domain is dashboard config, not package.json. See email/sdk-integration.md.
  • Payments: Configure Stripe keys/catalog with npx @insforge/cli payments ... first; frontend code only creates Checkout/Portal sessions.
  • Payment RLS: Before subscription checkout or Billing Portal UI, add app-specific RLS on payments.checkout_sessions and payments.customer_portal_sessions. Checkout creation needs INSERT; checkout requests with idempotencyKey also need matching SELECT on payments.checkout_sessions.
  • Use Tailwind CSS v3.4 (do not upgrade to v4)
  • Always local build before deploy: Prevents wasted build resources and faster debugging
  • Deprecated packages: @insforge/react, @insforge/nextjs, and @insforge/react-router are deprecated. Do NOT install or use them. Use @insforge/sdk directly for all features including authentication.
  • Deployment: Include a vercel.json in the project root for SPA routing (React, React Router apps). The download-template tool includes this automatically.
  • Branching for risky backend changes: If your SDK code depends on a new schema, RLS policy, or auth config change, create a branch via npx @insforge/cli branch create first — see the insforge-cli skill's branch reference. After branch create / branch switch, restart the dev server so the SDK picks up the new INSFORGE_URL / INSFORGE_ANON_KEY.
BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card