ho-starter-kit: extracting a production-ready template from hobnb
I built ho-starter-kit to avoid solving the same setup problems repeatedly when starting new products.
Instead of creating another empty scaffold, I extracted the parts of hobnb that were broadly reusable, then removed domain-specific behavior.
Project goal
The target was simple:
- keep what is repeatedly useful in real projects
- remove anything specific to one product domain
- make safe defaults the easiest path
This includes auth, admin workflows, migrations, route guards, email handling, and deployment behavior.
What ships in the template
ho-starter-kit includes:
- TanStack Start app shell with typed routes and server functions
- Better Auth with approval-first onboarding (
member,admin,super-admin) - role-gated admin tools (user approvals, role changes, password reset controls)
- SQLite and Postgres support from the same codebase
- Drizzle migrations and migration safety scripts
- email logs persisted in the database by default
- release audit scripts covering both DB providers
The first registered user is promoted to super-admin and auto-approved. Subsequent users require admin approval.
Database model and provider strategy
The template supports two deployment paths:
- SQLite for quick setup and lower operational complexity
- Postgres for managed database workflows and scaling needs
I kept migration commands provider-aware and made deployment scripts apply migrations at startup.
For local Postgres work:
pnpm start:local:db
pnpm db:generate:postgres
pnpm db:apply-migrations
pnpm dev
db:apply-migrations reads .env directly, so provider selection is not dependent on shell-exported variables.
Coolify deployment patterns
I documented two explicit patterns:
- single app service with SQLite (persistent volume mounted at
/app/data) - Postgres mode with either:
- separate managed Postgres service, or
- Docker Compose stack (
app+postgres) using compose service hostnames
The compose stack uses environment variable substitution so values are defined once in Coolify stack settings instead of duplicated in files.
Security and operational defaults
Security defaults were part of the template scope, not an afterthought:
- baseline security headers and CSP in Nitro config
- server-side origin checks on write operations
- explicit auth/session route guards
- audit policy gates for dependency vulnerabilities
- release checks for both SQLite and Postgres paths
The point is not theoretical hardening; it is reducing avoidable mistakes during day-to-day development and deployment.
Testing and release gates
The release workflow validates both provider paths before tagging:
- type/lint/tests
- naming checks
- security checks
- DB migration + smoke checks
- route/security E2E tests
This is intentionally strict because starter templates spread quickly across projects. If the baseline is wrong, the same issue gets replicated everywhere.
Developer ergonomics
I also focused on practical DX:
- docs page in the app with setup and deployment guidance
- explicit environment variable reference
- non-cheesy, production-appropriate default UI pages (home/docs/404/error)
- clear pnpm entrypoints so routine work does not require manually calling internal scripts
Why this matters
Most project delays are not caused by missing framework features. They come from repeated setup drift, weak defaults, and inconsistent deployment behavior.
ho-starter-kit is my attempt to standardize the part that should already be solved, so new project work can start closer to real product problems.

