Next.js with PostgreSQL
Deploy a Next.js app with its own PostgreSQL.
Every LazyFrog project runs your Next.js app as a real Node server beside its own PostgreSQL, one database for the preview and one for the live site. Your AI builds or imports the app, checks it in a real browser and publishes when you say so.
A real example: a book club app
We gave Codex one message on 13 November 2026. It took 29 steps on LazyFrog in about 4 minutes, and nothing failed. The book club is made up.
You
Use LazyFrog to build a small Next.js app for my book club, Page Turners: a page listing the books we've read and the next one, a form to suggest a book (title, author, who suggested it), and an admin page where I can delete suggestions. Keep the books and suggestions in the project's PostgreSQL database with a few sample rows. Call the project page-turners-check. Use sensible defaults, don't ask me questions, and show me the preview when it works. Don't publish.
- 1.Read LazyFrog's guide on planning, the database and forms, and made a project from the Next.js template.
- 2.Saved a short plan (the pages, the two tables, what counts as done) and, as asked, went ahead on sensible defaults.
- 3.Wrote a migration for the books and suggestions tables, applied it to the preview database and added sample books.
- 4.Protected /admin with a password page in the project's routing, so deleting needs the owner's password.
- 5.Filled in and sent the suggestion form in a real browser on a phone-sized screen, then deleted the suggestion from the admin page, and checked the database each time.
- 6.Took screenshots at phone, tablet and desktop widths, ran the design check, fixed what it found and tried the form again.
- 7.Committed the work. Nothing was published.
The files that make it run
These are the project's own files, as Codex left them. A new project from the Next.js template starts with the first two.
services.json: what runs. The preview runs dev with hot reload; publishing runs build, then start.
{
"services": {
"web": {
"type": "web",
"dev": "exec ./node_modules/.bin/next dev --hostname 0.0.0.0 --port $PORT",
"build": "pnpm build",
"start": "exec ./node_modules/.bin/next start --hostname 0.0.0.0 --port $PORT",
"port": 3000,
"healthcheck_path": "/api/health"
}
}
}lib/db.ts: one connection pool, from the DATABASE_URL LazyFrog sets in each environment.
import pg from "pg";
// One pool per server process. DATABASE_URL is set by the platform in every environment.
const globalForDb = globalThis as unknown as { db?: pg.Pool };
export const db: pg.Pool =
globalForDb.db ?? new pg.Pool({ connectionString: process.env.DATABASE_URL, max: 5 });
if (process.env.NODE_ENV !== "production") globalForDb.db = db;migrations/: the schema, as numbered SQL files. Applied to the preview, and to the live database on every publish after a rehearsal on a copy of it.
-- migrations/0002_book_club.sql
CREATE TABLE books (
id serial PRIMARY KEY,
title text NOT NULL,
author text NOT NULL,
status text NOT NULL CHECK (status IN ('read', 'next')),
note text NOT NULL DEFAULT ''
);
CREATE UNIQUE INDEX one_next_book ON books (status) WHERE status = 'next';
CREATE TABLE suggestions (
id serial PRIMARY KEY,
title text NOT NULL CHECK (length(title) BETWEEN 1 AND 200),
author text NOT NULL CHECK (length(author) BETWEEN 1 AND 200),
suggested_by text NOT NULL CHECK (length(suggested_by) BETWEEN 1 AND 100),
created_at timestamptz NOT NULL DEFAULT now()
);Queries take their values as parameters:
// app/suggest/submit.ts (a server action), shortened await db.query( "INSERT INTO suggestions (title, author, suggested_by) VALUES ($1, $2, $3)", [title, author, suggestedBy], );
Your own app
- 1.Connect LazyFrog to Claude, ChatGPT, Codex or Claude Code.
- 2.Ask for a new app, or to import yours: “import https://github.com/you/your-app into LazyFrog”. Code in a folder on your machine is pushed with git (how that works).
- 3.Check the preview. Your AI tries the pages in a real browser and reads the logs; you get the private address.
- 4.Say “publish it”. A test publish builds the app and rehearses the migrations on a copy of the live database first. A live site starts with Hobby at $9 a month.
Before it goes live, go through the security checklist. The book club app's own code scanned clean.
Questions
- How do I deploy a Next.js app with PostgreSQL?
- Connect LazyFrog to your AI (Claude, ChatGPT, Codex or Claude Code) and ask it to build or import the app. Every project has its own PostgreSQL and sets DATABASE_URL for the app; the preview runs next dev and the live site runs next build and next start.
- Where does DATABASE_URL come from?
- LazyFrog sets it in every environment: the preview's points at the preview database and the live site's at the live one. They're separate, and preview data is never copied to the live site.
- How do schema changes reach the live database?
- As numbered SQL files in migrations/. They're applied to the preview when your AI runs them or you push, and to the live database when you publish, after a rehearsal on a copy of it. A framework's own migration tool works too, as the migrate command in services.json.
- Do I need Vercel, Docker or a separate database provider?
- No. The app, its database and its address are in one project. A Dockerfile and compose.yml come with it so the same code runs anywhere else, with a PostgreSQL of its own.
- Which Next.js features work?
- The app runs as a Node server with next start, so server components, server actions, route handlers and middleware run as they do on your machine. Background work goes in a worker or a cron service beside the site.
- Is the book club example real?
- Yes. Codex built it on LazyFrog on 13 November 2026 from the one message on this page, on a Free account, and left it as a preview.