/ astro-integrations / How to Integrate Xata with Astro: Complete Guide
astro-integrations 5 min read

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 your XATA_API_KEY and XATA_BRANCH
  • src/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.

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.