All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
- SQLite support as the default database (via
better-sqlite3) - Database abstraction layer (
src/db.js) supporting both SQLite and PostgreSQL docker-compose.postgres.ymlfor PostgreSQL modeDB_TYPEenvironment variable to choose database backendSQLITE_PATHenvironment variable for SQLite file location- SQLite volume mount option in
fly.tomlfor Fly.io deployment .claude/settings.jsonwith default Claude Code permissions.dockerignoreto speed up Docker builds (excludes node_modules, .git, docs, data)APP_NAMEenvironment variable for status page display name- Graceful shutdown handler (SIGTERM/SIGINT) -- closes DB connection and HTTP server cleanly
PG_USERandPG_PASSWORDenv vars in docker-compose.postgres.yml (no more hardcoded credentials)
- API key convention in CLAUDE.md: avoid
sk_live_/sk_test_prefixes (GitHub secret scanner blocks them) (fixes #1)
- Init Step 1 now removes the starter origin (
git remote remove origin) to prevent accidental commits back to plc/starter - Claude will file GitHub issues on plc/starter if it finds bugs in the starter repo itself
- Default database is now SQLite (was PostgreSQL)
docker-compose.ymlnow runs in SQLite mode (no init-db service needed)src/index.jsusesdb.jsabstraction instead of directpgusage- Status page and health endpoints now show database type
- Updated all documentation for dual-database support
- Replaced
.claude/settings.local.jsonwith clean.claude/settings.json - SQLite query detection in db.js now uses
stmt.readerinstead of SQL string parsing (correctly handles RETURNING, EXPLAIN, comments, etc.) - Status page app name comes from
APP_NAMEenv var instead ofnpm_package_name(works in Docker CMD) - Status page HTML escapes app name to prevent XSS
- Fly.io deployment details in CLAUDE.md replaced with reference to fly-deploy.md (saves tokens)
- PostgreSQL init step now includes Dockerfile cleanup (remove native build tool lines)
- SQL injection in
scripts/init-db.sh-- database name now quoted as identifier - db.js incorrectly classified RETURNING, EXPLAIN, VALUES queries as write operations
- Status page showed "myapp" in production because
npm_package_nameis only set vianpm start
- Database choice is permanent per project, made at init time (Step 0)
- SQLite uses
?parameter placeholders; PostgreSQL uses$1 - SQLite on Fly.io requires a volume and exactly 1 machine
better-sqlite3requires native build tools in Alpine Docker (handled in Dockerfile)- Both database drivers ship in package.json; the unused one is removed during project init
- Initial project setup
- Express.js server with health check endpoints (
/health,/health/db) - Status page at
/showing server and database health - PostgreSQL database connection
- Docker development environment with auto-database creation
- Fly.io deployment configuration
- Deterministic port generation (
scripts/get-port.sh) - each project gets a unique port (3000-3999) based on its name - Comprehensive Fly.io Managed Postgres (MPG) documentation (
fly-deploy.md)
- Changed local PostgreSQL username from
postgrestoplcacross all config and docs - Updated Fly.io deployment instructions to use Managed Postgres instead of old Fly Postgres
- Compacted CLAUDE.md to reduce token usage (no info lost)
- Added explicit reminder to update CHANGELOG before committing
- Uses
host.docker.internalto connect to host PostgreSQL (not a separate container) - Database auto-created by
init-dbservice ondocker compose up - Run
fly launchbeforefly deployto create the app on Fly.io - Port is generated from project name hash to avoid conflicts when running multiple projects
- Fly Postgres has two products: Managed Postgres (MPG) is current/recommended; old Fly Postgres is legacy
- MPG clusters are NOT Fly apps -- use
fly mpgcommands, notfly postgrescommands