Rock8Cloud
Blueprints

Next.js + React — Blueprint

Fullstack app with Next.js 15, React 19, and PostgreSQL

Fullstack application built with Next.js 15, React 19, and PostgreSQL. The backend exposes a JSON API; the frontend is a React client component that fetches and displays the data. Intended as a starting point for Kubernetes-deployed services: one table, one API endpoint, one page, full Docker support out of the box.

Tech stack:

LayerTechnology
RuntimeNode.js 20
FrameworkNext.js 15
FrontendReact 19 (client component)
LanguageTypeScript 5
Database drivernode-postgres (pg)
MigrationsCustom runner (plain SQL)

The application runs on port 3000. Opening / shows the React frontend with a live connection indicator and a table of space targets.

View on GitHub →

Project Structure

app/
├── page.tsx                         # React client component: fetches API, renders table
├── layout.tsx                       # Root layout
└── api/
    ├── targets/route.ts             # GET /api/targets
    └── info/route.ts                # GET /api/info

lib/
├── db.ts                            # pg Pool (DATABASE_URL or DB_*), sslmode handling
└── migrate.ts                       # Reads and runs SQL files from db/migrations/

db/migrations/
└── V1__init.sql                     # Creates space_target table + seed data

instrumentation.ts                   # Next.js hook: runs migrations on server startup
next.config.ts                       # output: 'standalone' for Docker

Key design decisions:

  • app/page.tsx is a 'use client' component: it runs in the browser, calls /api/info and /api/targets via fetch, and renders the table once both requests succeed. The connection indicator dot reflects the fetch status.
  • lib/db.ts strips sslmode from the connection string before passing it to pg because pg v8+ treats sslmode=require as verify-full (rejecting self-signed certs). SSL is instead controlled via the ssl object, with rejectUnauthorized: false for cloud-managed databases.
  • Migrations run via Next.js instrumentation.ts, called once when the Node.js server starts.
  • next.config.ts sets output: 'standalone' for minimal Docker images. The db/ directory is copied separately in the Dockerfile because instrumentation.ts needs the migration files at runtime.
  • To add a new endpoint: create a route.ts under app/api/ and query via the pool from lib/db.ts. Update app/page.tsx to display the new data.

Environment Variables

The application runs on port 3000 and requires a PostgreSQL database.

Database connection is configured via one of two approaches:

VariableRequiredExample
DATABASE_URLyespostgres://user:pass@host:5432/dbname?sslmode=require

Option B — Individual variables

VariableRequiredDefaultDescription
DB_HOSTnolocalhostDatabase host
DB_PORTno5432Database port
DB_NAMEnospacedbDatabase name
DB_USERnopostgresDatabase user
DB_PASSWORDnopostgresDatabase password
DB_SSL_MODEno(none)Set to require to enable SSL

DATABASE_URL takes precedence. If it is set, the individual DB_* variables are ignored.


Running Locally

With Docker Compose

docker compose up

Starts the application together with a PostgreSQL instance and sets DATABASE_URL automatically. No additional configuration needed.

Standalone

# install dependencies
npm install

# run in development mode (DATABASE_URL or DB_* must be set)
DATABASE_URL=postgres://postgres:postgres@localhost:5432/spacedb npm run dev

# build and run in production mode
npm run build
DATABASE_URL=postgres://postgres:postgres@localhost:5432/spacedb npm start

On this page