Shane HobanShane Hoban

Shane Hoban

MSc. Computer Science (UCD) · Full Stack Developer

Crosshaven, Cork, Ireland
All Articles

ho-starter-kit: extracting a production-ready template from hobnb

24 February 2026
ai-assistedstarter kittanstack startbetter authdrizzle ormsqlitepostgrescoolifyplaywrightsecurity

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:

  1. single app service with SQLite (persistent volume mounted at /app/data)
  2. 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.