A minimal Node.js starter template with SQLite/PostgreSQL, Docker, and Fly.io deployment.
- README.md - This file. Setup, usage, and deployment instructions.
- SPEC.md - Project-specific details: endpoints, structure, environment variables.
- CLAUDE.md - Instructions for Claude Code AI assistant. Workflow and maintenance guidelines.
- CHANGELOG.md - Project history, changes, and learnings.
- GOTCHAS.md - Known issues, confusing behaviors, and post-mortems.
- fly-deploy.md - Fly.io deployment reference and troubleshooting.
- Express.js server with health check endpoints
- SQLite database (default) or PostgreSQL (optional)
- Docker setup for local development
- Fly.io configuration for production deployment
- Status page at
/showing server and database health
- Docker (required)
- Node.js v20+ (optional, for local dev without Docker)
- Fly CLI (for production deployment)
- PostgreSQL running locally on port 5432 (only if using PostgreSQL mode)
git clone <this-repo> my-project
cd my-project
docker compose up --buildOpen http://127.0.0.1:3000 to see the status page.
That's it! SQLite is the default -- no external database needed.
This starter supports two database backends, chosen at project init time:
| SQLite (default) | PostgreSQL | |
|---|---|---|
| Best for | Simple apps, prototypes, MVPs | Multi-user apps, complex queries |
| Setup | Zero config | Requires PostgreSQL on host |
| Compose file | docker-compose.yml |
docker-compose.postgres.yml |
| Fly.io | Volume + 1 machine | Managed Postgres (MPG) |
See CLAUDE.md "Step 0: Choose Database" for decision criteria.
src/
index.js # Express server with routes and status page
db.js # Database abstraction (SQLite/PostgreSQL)
healthcheck.js # Health check script for testing
scripts/
init-db.sh # Creates PostgreSQL database if needed
get-port.sh # Generates deterministic port from project name
Dockerfile # Production container image
docker-compose.yml # Local dev (SQLite mode)
docker-compose.postgres.yml # Local dev (PostgreSQL mode)
fly.toml # Fly.io deployment configuration
.claude/ # Claude Code settings
| Variable | Default | Description |
|---|---|---|
PORT |
3000 |
Server port (use ./scripts/get-port.sh for deterministic port) |
DB_TYPE |
sqlite |
Database backend: sqlite or postgres |
SQLITE_PATH |
./data/myapp.db |
SQLite database file path |
DATABASE_URL |
- | PostgreSQL connection string (when DB_TYPE=postgres) |
DB_NAME |
myapp |
Database name for PostgreSQL init script |
Replace myapp with your project name and set a deterministic port:
# On macOS
sed -i '' 's/myapp/my-project-name/g' package.json docker-compose.yml .env.example
# Generate a deterministic port (avoids conflicts when running multiple projects)
PORT=$(./scripts/get-port.sh my-project-name)
sed -i '' "s/PORT=3000/PORT=$PORT/" .env.example
# Create your .env file
cp .env.example .envOr manually update package.json, docker-compose.yml, and .env.example.
| Endpoint | Description |
|---|---|
GET / |
Status page showing server and database health |
GET /health |
JSON health check (server only) |
GET /health/db |
JSON health check (server + database, shows DB type) |
# SQLite mode (default)
docker compose up --build
# PostgreSQL mode
docker compose -f docker-compose.postgres.yml up --build
# View logs
docker compose logs -f app
# Stop
docker compose down# Install dependencies
npm install
# Create and configure .env
cp .env.example .env
# Start the server with auto-reload
npm run dev
# Test the health endpoint
npm testSee fly-deploy.md for complete reference and troubleshooting.
fly launch # Create app (say NO to Postgres, NO to deploy)
fly volumes create data --size 1 # Create volume for SQLite
# Uncomment [mounts] section in fly.toml
fly scale count 1 # SQLite needs exactly 1 machine
fly deployfly launch # Create app (say NO to Postgres, NO to deploy)
# Create Managed Postgres via Fly Dashboard
fly secrets set DATABASE_URL="..." # Set connection string
fly deploySee fly-deploy.md for details.
- Make sure PostgreSQL is running on port 5432:
pg_isready - Check init-db logs:
docker compose -f docker-compose.postgres.yml logs init-db - On Fly.io, check DATABASE_URL:
fly secrets list
Change the port in your .env file or docker-compose.yml.
Use http://127.0.0.1:PORT instead of localhost. Or use an incognito window.
| Command | Description |
|---|---|
npm start |
Start the server |
npm run dev |
Start with auto-reload (Node.js --watch) |
npm test |
Run health check against running server |
MIT