@xano/supabase-compat
v0.2.0
Published
Supabase-compatible adapter for Xano - perfect for AI-generated frontends (Lovable, v0, Bolt, etc.)
Readme
@xano/supabase-compat
A Supabase-compatible adapter for Xano, designed specifically for AI-generated frontends (Lovable, v0, Bolt, etc.) that use Supabase. Swap Supabase for Xano with minimal code changes!
🎯 For Lovable Users
Built a project with Lovable but want to use Xano instead of Supabase? This adapter is for you!
Before (Lovable default):
import { supabase } from "@/integrations/supabase/client";
await supabase.auth.signInWithPassword({ email, password });After (with this adapter):
import { xano } from "@/integrations/xano/client";
await xano.auth.signInWithPassword({ email, password }); // Same API!📖 Read the complete Lovable migration guide →
Why This Adapter?
AI code generators like Lovable, v0, and Bolt typically generate Supabase-based backends. This adapter lets you:
- ✅ Keep your AI-generated frontend code - minimal changes needed
- ✅ Switch to Xano backend - use Xano's no-code backend builder
- ✅ Maintain familiar patterns - Supabase-compatible API
- ✅ Gradual migration - run both Supabase and Xano side-by-side
Features
- Supabase-compatible Auth -
signUp,signInWithPassword,signOutwork identically - Endpoint-based Data Access - Native support for Xano's API endpoints
- TypeScript First - Full type safety with TypeScript
- Zero Dependencies - Lightweight, no external dependencies
- React Ready - Drop-in replacement for React hooks
- Perfect for Lovable - Specifically tested with Lovable-generated projects
Installation
npm install @xano/supabase-compat
# or
yarn add @xano/supabase-compat
# or
pnpm add @xano/supabase-compatQuick Start
1. Create a Client
import { createClient } from "@xano/supabase-compat";
const xano = createClient(
"https://your-instance.xano.io",
"/api:YOUR_API_GROUP/auth", // Your auth API group endpoint
{
auth: {
storage: localStorage,
persistSession: true,
autoRefreshToken: true,
},
}
);Finding your API Group ID:
In Xano, your authentication endpoints will have a path like /api:qoUCtLER/auth/login. The qoUCtLER part is your unique API group ID - this is what you need to provide.
📖 Need help finding your API Group ID? Read the Xano Setup Guide →
2. Authentication
The authentication API is designed to be familiar to Supabase users:
// Sign up
const { data, error } = await xano.auth.signUp({
email: "[email protected]",
password: "password123",
options: {
data: {
name: "John Doe",
username: "johndoe",
},
},
});
// Sign in
const { data, error } = await xano.auth.signInWithPassword({
email: "[email protected]",
password: "password123",
});
// Sign out
await xano.auth.signOut();
// Listen to auth changes
xano.auth.onAuthStateChange((event, session) => {
console.log(event, session);
});3. Data Fetching
Xano uses endpoints rather than tables. The SDK provides a clean API for endpoint calls:
// GET request
const { data, error } = await xano
.endpoint("/api:w9xAAZ3Q/tweets/feed")
.get({ page: 1, per_page: 20 });
// POST request
const { data, error } = await xano
.endpoint("/api:w9xAAZ3Q/tweets")
.post({ content: "Hello World!" });
// PATCH request
const { data, error } = await xano
.endpoint("/api:pKDn0Rcs/users/me")
.patch({ name: "Updated Name" });
// DELETE request
const { data, error } = await xano
.endpoint("/api:w9xAAZ3Q/tweets/123")
.delete();React Integration
useAuth Hook
import { useAuth } from "./hooks/useAuth";
function App() {
const { user, loading, signOut } = useAuth();
if (loading) return <div>Loading...</div>;
if (!user) return <LoginForm />;
return (
<div>
<h1>Welcome {user.email}</h1>
<button onClick={signOut}>Sign Out</button>
</div>
);
}Custom Hook Example
import { useState, useEffect } from "react";
import { xano } from "./client";
export function useTweets() {
const [tweets, setTweets] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
async function loadTweets() {
const { data, error } = await xano
.endpoint("/api:w9xAAZ3Q/tweets/feed")
.get({ page: 1 });
if (!error) setTweets(data);
setLoading(false);
}
loadTweets();
}, []);
return { tweets, loading };
}Migration from Supabase
Authentication
The authentication API is nearly identical:
// Before (Supabase)
const { data, error } = await supabase.auth.signInWithPassword({
email: "[email protected]",
password: "password",
});
// After (Xano)
const { data, error } = await xano.auth.signInWithPassword({
email: "[email protected]",
password: "password",
});Data Fetching
The main difference is that Xano uses endpoints instead of tables:
// Before (Supabase)
const { data } = await supabase
.from("tweets")
.select("*")
.eq("user_id", userId);
// After (Xano)
const { data } = await xano
.endpoint("/api:w9xAAZ3Q/tweets/feed")
.get({ user_id: userId });API Reference
Client
createClient(baseUrl, apiKey?, options?)
Creates a new Xano client instance.
Parameters:
baseUrl(string): Your Xano instance URLapiKey(string, optional): API key if requiredoptions(object, optional): Configuration optionsauth.storage: Storage implementation (default: localStorage)auth.persistSession: Persist session (default: true)auth.autoRefreshToken: Auto-refresh tokens (default: true)
Authentication
auth.signUp(credentials)
Sign up a new user.
await xano.auth.signUp({
email: string,
password: string,
options: {
data: Record<string, any>,
},
});auth.signInWithPassword(credentials)
Sign in with email and password.
await xano.auth.signInWithPassword({
email: string,
password: string,
});auth.signOut()
Sign out the current user.
auth.getSession()
Get the current session.
auth.getUser()
Get the current user.
auth.onAuthStateChange(callback)
Listen to authentication state changes.
xano.auth.onAuthStateChange((event, session) => {
// Handle auth state change
});Endpoints
endpoint(path).get(params?)
Make a GET request to a Xano endpoint.
await xano.endpoint("/api:xxx/resource").get({ page: 1 });endpoint(path).post(body, params?)
Make a POST request to a Xano endpoint.
await xano.endpoint("/api:xxx/resource").post({ name: "New Item" });endpoint(path).patch(body, params?)
Make a PATCH request to a Xano endpoint.
await xano.endpoint("/api:xxx/resource/123").patch({ name: "Updated" });endpoint(path).delete(params?)
Make a DELETE request to a Xano endpoint.
await xano.endpoint("/api:xxx/resource/123").delete();TypeScript Support
The SDK is written in TypeScript and provides full type safety:
import { createClient } from "@xano/supabase-compat";
import type { Database } from "./types";
// Define your database schema
interface Database {
public: {
Tables: {
tweets: {
id: number;
content: string;
user_id: number;
created_at: string;
};
// ... other tables
};
};
}
const xano = createClient<Database>("https://your-instance.xano.io");Error Handling
All methods return a response object with data and error:
const { data, error } = await xano.auth.signIn({ ... });
if (error) {
console.error('Error:', error.message);
console.error('Status:', error.status);
return;
}
// Use data safely
console.log(data);Examples
Check out the examples/ directory for complete examples:
Key Differences from Supabase
- Endpoints vs Tables: Xano uses predefined API endpoints instead of direct table access
- No Real-time: Xano doesn't have built-in real-time subscriptions (yet)
- Authentication Flow: Xano returns
authTokeninstead of complex session objects - No Row Level Security: Authorization is handled in Xano's backend logic
Contributing
Contributions are welcome! Please open an issue or submit a pull request.
License
MIT
Support
For issues and questions:
- GitHub Issues: github.com/yourrepo/xano-sdk
- Xano Documentation: docs.xano.com
