Master Turso edge database patterns for Google Antigravity IDE distributed applications
# Turso Edge Database Patterns for Google Antigravity IDE
Build globally distributed applications with Turso edge databases using Google Antigravity IDE. This guide covers LibSQL integration, embedded replicas, multi-tenant architectures, and sync strategies for offline-first applications.
## Core Turso Setup
```typescript
// src/db/client.ts
import { createClient } from "@libsql/client";
import { drizzle } from "drizzle-orm/libsql";
import * as schema from "./schema";
// Primary database client
export const turso = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!,
});
export const db = drizzle(turso, { schema });
// Embedded replica for edge/local development
export function createEdgeClient(options?: {
syncUrl?: string;
syncInterval?: number;
}) {
return createClient({
url: "file:local-replica.db",
syncUrl: options?.syncUrl ?? process.env.TURSO_DATABASE_URL,
authToken: process.env.TURSO_AUTH_TOKEN,
syncInterval: options?.syncInterval ?? 60, // Sync every 60 seconds
});
}
// Multi-tenant database factory
export async function getTenantDb(tenantId: string) {
const tenantDbUrl = `libsql://${tenantId}-${process.env.TURSO_ORG}.turso.io`;
const client = createClient({
url: tenantDbUrl,
authToken: process.env.TURSO_AUTH_TOKEN!,
});
return drizzle(client, { schema });
}
```
## Schema with Vector Support
```typescript
// src/db/schema/documents.ts
import { sqliteTable, text, integer, blob, real } from "drizzle-orm/sqlite-core";
import { sql } from "drizzle-orm";
export const documents = sqliteTable("documents", {
id: integer("id").primaryKey({ autoIncrement: true }),
title: text("title").notNull(),
content: text("content").notNull(),
embedding: blob("embedding", { mode: "buffer" }), // Store vector as blob
metadata: text("metadata", { mode: "json" }).$type<{
author: string;
tags: string[];
createdAt: string;
}>(),
createdAt: integer("created_at", { mode: "timestamp" })
.default(sql`(strftime('%s', 'now'))`)
.notNull(),
});
export const chunks = sqliteTable("chunks", {
id: integer("id").primaryKey({ autoIncrement: true }),
documentId: integer("document_id")
.notNull()
.references(() => documents.id, { onDelete: "cascade" }),
content: text("content").notNull(),
embedding: blob("embedding", { mode: "buffer" }),
chunkIndex: integer("chunk_index").notNull(),
});
```
## Vector Search Implementation
```typescript
// src/services/vector-search.ts
import { db } from "../db/client";
import { documents, chunks } from "../db/schema";
import { sql, desc, cosineDistance } from "drizzle-orm";
interface SearchResult {
id: number;
title: string;
content: string;
similarity: number;
}
export async function vectorSearch(
queryEmbedding: number[],
options: {
limit?: number;
threshold?: number;
filter?: { tags?: string[] };
} = {}
): Promise<SearchResult[]> {
const { limit = 10, threshold = 0.7, filter } = options;
// Convert embedding to buffer
const embeddingBuffer = Buffer.from(new Float32Array(queryEmbedding).buffer);
const results = await db
.select({
id: documents.id,
title: documents.title,
content: documents.content,
similarity: sql<number>`1 - (
vector_distance_cos(${documents.embedding}, ${embeddingBuffer})
)`.as("similarity"),
})
.from(documents)
.where(sql`${documents.embedding} IS NOT NULL`)
.orderBy(desc(sql`similarity`))
.limit(limit);
return results.filter((r) => r.similarity >= threshold);
}
// Batch insert with embeddings
export async function indexDocuments(
docs: Array<{ title: string; content: string; embedding: number[] }>
) {
const values = docs.map((doc) => ({
title: doc.title,
content: doc.content,
embedding: Buffer.from(new Float32Array(doc.embedding).buffer),
metadata: { author: "system", tags: [], createdAt: new Date().toISOString() },
}));
await db.insert(documents).values(values);
}
```
## Sync and Replication
```typescript
// src/db/sync.ts
import { createClient, type Client } from "@libsql/client";
class SyncManager {
private client: Client;
private syncInterval: NodeJS.Timer | null = null;
constructor(private config: {
localPath: string;
remoteUrl: string;
authToken: string;
}) {
this.client = createClient({
url: `file:${config.localPath}`,
syncUrl: config.remoteUrl,
authToken: config.authToken,
});
}
async startSync(intervalMs: number = 30000) {
// Initial sync
await this.sync();
// Periodic sync
this.syncInterval = setInterval(() => {
this.sync().catch(console.error);
}, intervalMs);
}
async sync() {
const result = await this.client.sync();
console.log(`Synced ${result.frames_synced} frames`);
return result;
}
stopSync() {
if (this.syncInterval) {
clearInterval(this.syncInterval);
this.syncInterval = null;
}
}
}
export const syncManager = new SyncManager({
localPath: "./data/local.db",
remoteUrl: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!,
});
```
## Best Practices for Google Antigravity IDE
When using Turso with Google Antigravity, leverage embedded replicas for edge deployments. Use vector extensions for semantic search. Implement multi-tenant isolation with separate databases. Configure sync intervals based on data freshness needs. Use transactions for consistent writes. Let Gemini 3 optimize your SQL queries for SQLite compatibility.
Google Antigravity excels at generating LibSQL-compatible schemas and migration scripts.This Turso prompt is ideal for developers working on:
By using this prompt, you can save hours of manual coding and ensure best practices are followed from the start. It's particularly valuable for teams looking to maintain consistency across their turso implementations.
Yes! All prompts on Antigravity AI Directory are free to use for both personal and commercial projects. No attribution required, though it's always appreciated.
This prompt works excellently with Claude, ChatGPT, Cursor, GitHub Copilot, and other modern AI coding assistants. For best results, use models with large context windows.
You can modify the prompt by adding specific requirements, constraints, or preferences. For Turso projects, consider mentioning your framework version, coding style, and any specific libraries you're using.