How to Integrate Xata with Astro: Complete Guide
Step-by-step guide to integrating Xata with your Astro website. Setup, configuration, and best practices.
How to Integrate Xata with Astro: Complete Guide
Xata is a serverless database platform that combines the reliability of PostgreSQL with built-in full-text search, vector search, and file attachments. It provides a TypeScript SDK with automatic type generation from your schema, making it a natural fit for Astro projects that need a managed data layer without the complexity of setting up separate search and storage services.
This guide walks through connecting Xata to an Astro project, from account setup through querying data and deploying to production.
Prerequisites
Make sure you have the following before starting:
- Node.js 18+ installed
- An existing Astro project (v3.0+ recommended)
- A Xata account (free tier available at xata.io)
- The Xata CLI installed globally:
npm install -g @xata.io/cli - Astro configured with server-side rendering or hybrid mode
Installation
Install the Xata client SDK:
npm install @xata.io/client
Authenticate the Xata CLI with your account:
xata auth login
This opens a browser window where you sign in and generate an API key. The key is stored locally in your home directory.
If you have not created a database yet, do it through the CLI:
xata init
The init command walks you through selecting or creating a database, generates a .xatarc configuration file, and creates a type-safe client in your project.
Configuration
Generated Files
After running xata init, you will have these files in your project:
.xatarc- Points to your database and specifies where to generate types.env- Contains yourXATA_API_KEYandXATA_BRANCHsrc/xata.ts- Auto-generated type-safe client with your schema types
The .xatarc file looks like this:
{
"databaseURL": "https://your-workspace-abc123.us-east-1.xata.sh/db/your-database",
"codegen": {
"output": "src/xata.ts"
}
}
Environment Variables
Your .env file should contain:
XATA_API_KEY=xau_your_api_key_here
XATA_BRANCH=main
Setting Up the Client
The auto-generated src/xata.ts file exports a client class. Create a utility that initializes it with your credentials:
// src/lib/db.ts
import { XataClient } from '../xata';
let instance: XataClient | null = null;
export const getXataClient = () => {
if (instance) return instance;
instance = new XataClient({
apiKey: import.meta.env.XATA_API_KEY,
branch: import.meta.env.XATA_BRANCH || 'main',
});
return instance;
};
Astro Config
Make sure your Astro config uses hybrid or server output mode:
// astro.config.mjs
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
output: 'hybrid',
adapter: node({ mode: 'standalone' }),
});
Common Patterns
Fetching Records in Pages
Query your Xata database directly in Astro page frontmatter:
---
// src/pages/articles.astro
import { getXataClient } from '../lib/db';
const xata = getXataClient();
const articles = await xata.db.articles
.filter({ published: true })
.sort('created_at', 'desc')
.getMany({ pagination: { size: 20 } });
---
<html>
<body>
<h1>Articles</h1>
{articles.map((article) => (
<article>
<h2><a href={`/articles/${article.slug}`}>{article.title}</a></h2>
<p>{article.summary}</p>
</article>
))}
</body>
</html>
Every column name and filter option is fully typed based on your Xata schema.
Full-Text Search
One of Xata's standout features is built-in search. You do not need a separate service like Algolia or Meilisearch:
// src/pages/api/search.ts
import type { APIRoute } from 'astro';
import { getXataClient } from '../../lib/db';
export const GET: APIRoute = async ({ url }) => {
const query = url.searchParams.get('q') || '';
const xata = getXataClient();
const results = await xata.db.articles.search(query, {
fuzziness: 1,
prefix: 'phrase',
});
return new Response(JSON.stringify(results.records), {
headers: { 'Content-Type': 'application/json' },
});
};
Creating and Updating Records
// src/pages/api/articles.ts
import type { APIRoute } from 'astro';
import { getXataClient } from '../../lib/db';
export const POST: APIRoute = async ({ request }) => {
const body = await request.json();
const xata = getXataClient();
const article = await xata.db.articles.create({
title: body.title,
slug: body.slug,
content: body.content,
published: false,
});
return new Response(JSON.stringify(article), {
status: 201,
headers: { 'Content-Type': 'application/json' },
});
};
Regenerating Types After Schema Changes
Whenever you modify your schema in the Xata dashboard or through the CLI, regenerate your TypeScript types:
xata codegen
This updates src/xata.ts with the latest table definitions and column types.
Troubleshooting
"XataClient is not a constructor" error: This usually means the generated src/xata.ts file is outdated or corrupted. Run xata codegen to regenerate it. Also verify that your .xatarc file points to the correct database URL.
Empty results when data exists: Check that you are querying the correct branch. Xata supports database branching similar to Git. Your .env should specify XATA_BRANCH=main unless you are working on a feature branch.
API key not working: Make sure the XATA_API_KEY in your .env starts with xau_. If you regenerated the key in the dashboard, update your local .env file and restart the dev server.
Search returning unexpected results: Xata's search indexes update asynchronously. After inserting new records, there may be a brief delay before they appear in search results. For filtering by exact values, use .filter() instead of .search().
Type errors after schema changes: Run xata codegen every time you modify your database schema. The generated types must match the current schema for TypeScript to work correctly.
Conclusion
Xata simplifies the database layer for Astro projects by bundling PostgreSQL, full-text search, and file storage into a single managed service. The auto-generated TypeScript client eliminates the gap between your database schema and application code, catching errors at compile time. For Astro sites that need search functionality alongside traditional data queries, Xata removes the need to integrate and maintain separate services. Start with the free tier, use branching for safe schema iterations, and regenerate types whenever your schema evolves.
Related Articles
How to Use Algolia with Astro: Complete Guide
Step-by-step guide to integrating Algolia with your Astro website.
How to Integrate Auth0 with Astro: Complete Guide
Step-by-step guide to integrating Auth0 with your Astro website. Setup, configuration, and best practices.
How to Use AWS Amplify with Astro: Complete Guide
Step-by-step guide to integrating AWS Amplify with your Astro website.