Skip to main content
Paul Welty, PhD AI, WORK, AND STAYING HUMAN

2026-03-20 — SimpleBooks Next.js port: design and planning

What shipped today

Today was entirely about planning the migration of SimpleBooks from Rails 8 + PostgreSQL to Next.js 16 + SQLite. The Rails app hasn’t been touched in about 6 months, and the goal is to bring it onto the same stack as dinly, prakta, and eclectis — Next.js + shadcn/ui + Tailwind CSS 4 — while preserving all the financial data that’s already been entered.

The session explored the existing Rails codebase thoroughly (8 models, 12 controllers, AI-powered bank reconciliation, reports, CSV import, invoicing) and then stripped out the multi-tenant/auth/email layers that don’t apply to a single-user local tool. Key architectural decisions: SQLite via Drizzle ORM for zero external dependencies, Server Actions instead of REST API routes, and deferring Plaid and Stripe integrations (neither was ever implemented in Rails — just schema columns and gems).

A critical discovery was that the Postgres database isn’t running — the only data source is a dump file from November 2025 at db/backups/. The migration script needs to restore from this dump, carefully remap all IDs for SQLite, and handle ActiveStorage receipt files (which require a 3-table join, not a simple column copy). The spec and plan both emphasize this data is irreplaceable.

Completed

  • Design spec: docs/superpowers/specs/2026-03-20-nextjs-port-design.md
  • Implementation plan: docs/superpowers/plans/2026-03-20-nextjs-port.md (20 tasks, 7 phases)
  • Two rounds of automated review caught 14 issues total (nullable unique indexes in SQLite, DB hot-reload guard, ActiveStorage migration complexity, balance calculation logic mismatch, missing schema fields)

Release progress

  • March 2026 milestone: empty (no issues created yet — this is pre-implementation)

Carry-over

  • The entire implementation: 20 tasks spanning scaffold → data migration → core CRUD → promises → reconciliation → reports → CSV import → verification
  • No code has been written yet — today was design + planning only

Risks

  • Data migration is the #1 risk. The Postgres dump is the only copy of 6 months of financial data. The migration script must handle: ID remapping across 8 tables with FK relationships, ActiveStorage receipt file extraction, enum mapping, column renames (promise_numbernumber), and currency column consolidation. Any bug here loses data.
  • SQLite nullable unique indexes are fragile — uniqueness for plaid_transaction_id and promises.number must be enforced at the application layer, not the DB.
  • pdf-parse vs pdf-reader — the PDF text extraction library changed. The OpenAI prompt should still work but may need tweaking if statement parsing results differ.

Flags and watch-outs

  • Postgres is not running locally. Migration script will need Docker or a local Postgres install to restore the dump before extracting data.
  • The Rails app’s Account#current_balance sums ALL transactions after the last statement’s to_date regardless of status — the new implementation must match this exactly or balances will be wrong.
  • Stripe is a data source (SaaS revenue), not a payment processor. This is documented in the spec but easy to forget.

Next session

  1. Start implementation with Task 1 (scaffold Next.js project) — use subagent-driven development from the plan
  2. Task 2 (Drizzle schema) is the critical foundation — get the 8 tables right
  3. Task 5 (data migration) should be prioritized early to validate the schema against real data before building UI
  4. Consider creating GitHub issues from the plan phases to track progress through the milestone

Why customer tools are organized wrong

This article reveals a fundamental flaw in how customer support tools are designed—organizing by interaction type instead of by customer—and explains why this fragmentation wastes time and obscures the full picture you need to help users effectively.

Infrastructure shapes thought

The tools you build determine what kinds of thinking become possible. On infrastructure, friction, and building deliberately for thought rather than just throughput.

Server-side dashboard architecture: Why moving data fetching off the browser changes everything

How choosing server-side rendering solved security, CORS, and credential management problems I didn't know I had.

The work of being available now

A book on AI, judgment, and staying human at work.

The practice of work in progress

Practical essays on how work actually gets done.

The product changed its mind

A product pivoted its entire philosophy mid-session — from 'here's your list' to 'here's your next thing.' The code shipped in the same conversation as the idea. That's not iteration. That's something else.

Your project management tool was made for a non-human (AI) factory, not for you

Every project or task management tool on the market descends from Frederick Taylor's factory floor. The assumptions were wrong then. They're catastrophic in the Age of AI.

The last mile is all the miles

Building the product is the fun part. Deploying it, configuring auth, pasting email templates into dashboards, rotating leaked API keys — that's where the work actually lives.