Skip to content

Migrate blog data layer from Xata to Drizzle + Postgres (Railway)#3

Open
Sam-Apostel wants to merge 5 commits into
masterfrom
claude/project-portfolio-overview-dOS9q
Open

Migrate blog data layer from Xata to Drizzle + Postgres (Railway)#3
Sam-Apostel wants to merge 5 commits into
masterfrom
claude/project-portfolio-overview-dOS9q

Conversation

@Sam-Apostel

Copy link
Copy Markdown
Owner

Why

The blog read from a Xata database (controll-room) that has been deleted, which broke every page — the homepage queried xata.db.project and threw. This moves the data layer to Drizzle ORM over Postgres, intended to run on Railway alongside the other services.

What changed

  • Removed globals/xata.ts (generated client) and .xatarc.
  • Added globals/schema.ts — Drizzle schema for the two tables the blog actually uses (blogpost, project). The other Xata tables (feed, mail, thread, contact, update) belonged to other apps and were intentionally left out.
  • globals/db.ts now exports a Drizzle db (postgres-js driver) + Blogpost/Project row types, so existing component imports keep working.
  • Rewrote every query site to Drizzle: app/page.tsx, app/a/[slug]/page.tsx, app/p/[slug]/page.tsx, app/p/generateProjectMetadata.ts, app/rss.xml/route.tsx.
  • DB-backed routes are now dynamic = 'force-dynamic' with no generateStaticParams, so next build no longer needs a reachable database (Railway's private DB host isn't reachable at build). The MDX dedicated pages (/a/communication-between-components, /p/polar-printer) are unaffected.
  • package.json: dropped @xata.io/*, added drizzle-orm, postgres, drizzle-kit, tsx; added db:push/db:generate/db:migrate/db:seed/db:studio scripts.
  • Added scripts/seed.ts + seed/README.md to load your Xata JSON exports, and MIGRATION.md with the full runbook. .env.dist now documents DATABASE_URL.

Remaining manual steps (need your input / Railway access)

  1. Provision Postgres on Railway, grab DATABASE_URL.
  2. DATABASE_URL=… npm run db:push to create the schema.
  3. Drop blogpost.json / project.json exports into ./seed/ and npm run db:seed (adjust field mapping in scripts/seed.ts if your export shape differs).
  4. Deploy the blog to Railway; set DATABASE_URL as a service variable; point sams.land at it and retire the Vercel project.

Not yet verified

I couldn't run npm install / next build in this environment — dependency version ranges (drizzle-orm ^0.38, drizzle-kit ^0.30, postgres ^3.4, tsx ^4.19) and the build should be confirmed locally. Logic is a 1:1 port of the previous Xata filters (incl. published < now excluding drafts, projects ordered by updated_at).

https://claude.ai/code/session_01FgRm4bvPixcxQoyZu4X8Gh


Generated by Claude Code

Replaces the deleted Xata workspace with Drizzle ORM over a Postgres
database (intended for Railway). Adds schema, db client, drizzle-kit
config and a seed script; rewrites every Xata query (home, article,
project, project metadata, rss) to Drizzle. DB-backed routes are now
rendered dynamically so the build no longer needs DB access.
@vercel

vercel Bot commented May 29, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
blog Error Error May 29, 2026 6:48pm

@what-the-diff

what-the-diff Bot commented May 29, 2026

Copy link
Copy Markdown

PR Summary

  • Database Connection Update
    The .env.dist has been amended to replace Xata API keys with our new Postgres connection string (DATABASE_URL).

  • .gitignore Modification
    Added a rule to ignore any database seed dumps that are now positioned in the seed directory.

  • Removal of .xatarc
    Deleted the Xata configuration file as we are transitioning away from Xata.

  • Migration Documentation
    A new file, MIGRATION.md, has been added to describe the process of migrating from Xata to Drizzle ORM with Postgres.

  • Revise Database Section of README.md
    Updated the database section to highlight the new structure using Postgres with Drizzle ORM. It now provides common database tasks.

  • Data Fetching Refactors
    Updated all database queries in app/* from Xata to Drizzle ORM. This affects how we fetch articles, projects, generate pages, filter methods, generate project metadata, and fetch articles for RSS feed - leading to more dynamic page generation.

  • Drizzle Configuration
    Added drizzle.config.ts, a new file for configuring Drizzle ORM. Contains schema and database credentials.

  • Updated globals/db.ts
    Replaced initialization of Xata client with Drizzle's database client and schema. This fits with our transition away from Xata.

  • New Schema Definitions
    Added globals/schema.ts that provides new schema definitions for blogposts and projects using Drizzle ORM's schema builders.

  • Removal of Xata-specific Code
    Deleted the entire Xata client along with its related code in globals/xata.ts.

  • Updated package.json
    Removed Xata dependencies, added Drizzle ORM commands for smoother database operations.

  • Added Database Seeding Script
    Introduced scripts/seed.ts, a new script for seeding the database from JSON data files.

  • Instructions for Database Seeding
    Added seed/README.md, which offers comprehensive instructions for using data files in seeding the database.

🔔 What The Diff can not only summarize your PRs or help you refactor your code!

Get a weekly Slack notification summing up all the work you did within the last 7 days – a great way to keep everyone informed on the status of blog's progress!
You can configure the Slack integration in your repository settings.

The two dedicated pages were missed in the first pass:
- app/a/communication-between-components used the removed getXataClient
  (this broke the build); now queries Drizzle.
- app/p/polar-printer's generateMetadata hits the DB; mark both routes
  force-dynamic so the build doesn't need a database.
Next imports every route module during build; throwing at import time
when DATABASE_URL is unset failed the build on environments without a DB.
Defer client creation to first query via a proxy, so `next build` (all DB
routes are force-dynamic) succeeds without a database and only runtime
queries require the connection.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant