Yeeted

HOSTING FOR AI-BUILT APPS

Deploy a Next.js blog with PostgreSQL on Yeeted

A Yeeted sample: Next.js App Router on managed postgres. What it demonstrates:

The two things that catch people

next build executes your server components. It prerenders every route it can, at build time, on a machine with no database. A page that queries postgres without opting out is either a build failure or, worse, a static file baked from an empty store and served forever, so the app deploys clean and shows nothing. app/page.js and the API route set export const dynamic = "force-dynamic"; /stats deliberately does not, and revalidates instead.

pg must stay out of the bundle. serverExternalPackages: ["pg"] in next.config.mjs. Without it next build tries to resolve pg's optional native bindings at compile time and fails.

Routes

Route What it is
/ server-rendered per request, lists posts from postgres
/stats statically generated, revalidate = 10
/api/posts GET lists, POST creates ({"title","body"})
/healthz ok

/stats is the one route that makes next start write to .next/cache at runtime, on a root filesystem the platform mounts read-only except for /tmp. It is here so that the case is exercised rather than avoided.

Tests: npm test (unit, zero services) · ./smoke.sh https://... (smoke).

Run locally

Use a Node.js version supported by the pinned Next.js dependency (Node 20.9+ for Next.js 16). From node/blog-next inside the examples tree:

npm ci
npm test
npm run dev

Open http://localhost:3000. Without DATABASE_URL, posts live in memory and are lost on restart. For a database-backed local run, provide a PostgreSQL connection string through your environment before starting the server. The unit tests exercise the memory store, not PostgreSQL or rendering.

Deploy and verify

Follow the deployment walkthrough, using this folder as the source root. Include the lockfile, next.config.mjs, migrations, and yeeted.yaml. The manifest requests PostgreSQL. The store opens lazily, applies its migration on first use, and exposes its kind in API responses.

sh smoke.sh "$PREVIEW_URL"

Expect health and page checks to pass, a new post to return 201, and GET /api/posts to contain the new post and "store":"postgres". The script also fetches /stats and rejects a blank title with 400. Merely rendering /stats does not verify that its cached count eventually changes; check again after its revalidation interval when testing that behavior.

For a manual write:

curl -i "$PREVIEW_URL/api/posts" -H 'Content-Type: application/json'   -d '{"title":"My first Yeeted post","body":"Deployed from my coding agent."}'
curl -fsS "$PREVIEW_URL/api/posts"

What to change before real use

There is no author authentication. Migrations are recorded, but the sample migration runner does not serialize concurrent instances. Use a coordinated migration step before running multiple replicas. A rollback of application code does not undo a schema migration. Verify production rendering and PostgreSQL behavior separately from the in-memory unit tests.

All examples · Deploy an example