Examples
PerSQL uses @persql/sdk
and nothing else fancy — no ORM, no API gateway, no edge tricks.
The same one-import shape works for Next.js, Hono, SvelteKit, or any
server-rendered framework.
Pattern: the SDK is the data layer
Section titled “Pattern: the SDK is the data layer”Every project follows the same shape:
import { PerSQL } from "@persql/sdk";
const persql = new PerSQL({ token: process.env.PERSQL_TOKEN! });export const db = persql.database(process.env.PERSQL_DATABASE!);
// Then, anywhere on the server:const { data } = await db.query<Row>("SELECT * FROM things WHERE id = ?", [id]);No connection pool, no driver to ship to the edge, no migrations framework to wire up. The SDK makes one HTTPS request per call.
Three concrete shapes
Section titled “Three concrete shapes”Next.js 15 — server action
Section titled “Next.js 15 — server action”"use server";import { db } from "@/lib/db";
export async function addTodo(title: string) { await db.query("INSERT INTO todos (title) VALUES (?)", [title]);}
export async function listTodos() { const { data } = await db.query<{ id: number; title: string }>( "SELECT id, title FROM todos ORDER BY id DESC", ); return data;}Hono — REST endpoint
Section titled “Hono — REST endpoint”import { Hono } from "hono";import { db } from "./db";
const app = new Hono();
app.post("/links", async (c) => { const { url } = await c.req.json(); const slug = crypto.randomUUID().slice(0, 7); await db.query("INSERT INTO links (slug, url) VALUES (?, ?)", [slug, url]); return c.json({ slug });});
app.get("/:slug", async (c) => { const { data } = await db.query<{ url: string }>( "SELECT url FROM links WHERE slug = ?", [c.req.param("slug")], ); return data[0] ? c.redirect(data[0].url) : c.notFound();});
export default app;SvelteKit — server load function
Section titled “SvelteKit — server load function”import { db } from "$lib/server/db";import type { PageServerLoad } from "./$types";
export const load: PageServerLoad = async ({ params }) => { const { data } = await db.query<{ id: number; title: string; body: string }>( "SELECT id, title, body FROM posts WHERE slug = ?", [params.slug], ); if (!data[0]) throw error(404, "post not found"); return { post: data[0] };};Setup, in one paragraph
Section titled “Setup, in one paragraph”Make a database in the console, create a
token (Tokens → New token), set PERSQL_TOKEN and PERSQL_DATABASE
(in the form namespace/db) in your .env, then apply your schema by
pasting CREATE TABLE… into the console SQL editor or piping it via the
CLI. That’s the whole setup — no migrations framework, no driver to
install.
Going further
Section titled “Going further”- Drizzle if you want types and a query
builder. The SDK exposes a
drizzle-orm/sqlite-proxydriver viadb.driver(). - Tool use to expose the same database as a callable tool to Claude or GPT.
- Local mode to run the SDK against
:memory:in tests.