Independent product case study
Pay Period Planner
A household cash-flow workspace that turns income, recurring bills, savings, debt, and important dates into a versioned plan for the next pay period.
- Role
- Product design and end-to-end engineering
- Scope
- React, Spring Boot, PostgreSQL, and verification
- Status
- Local-first; not production hosted
- Data
- Synthetic household records only

Pay Period Planner is an independently built portfolio project. Professional outcomes described elsewhere on this site come from separate employer work; no employer code, data, or implementation details appear here.
Make the next decision visible
I designed Pay Period Planner around one practical question: after the next paycheck and its obligations, what cash is actually available for debt, savings, or the following period?
The interface keeps the answer connected to its inputs instead of hiding it behind an opaque score or a second editing surface.
Accessibility shaped the interaction model: financial tables reflow into labeled rows, grouped navigation becomes one compact selector, dialogs preserve focus, and core workflows remain keyboard operable.
Paychecks, additional income, cadence, and planning dates.
Recurring bills, annual obligations, housing, and debt.
Possible debt payments, savings transfers, and reserves.


From useful prototype to coherent system
I built the first React and Spring Boot version around one local JSON snapshot to validate the workflow quickly. When that model created two startup modes, global ownership, file-write risk, and no safe path for multiple users, I chose relational workspaces, versioned saves, and independent data re-entry.
A working financial tool had real value, but its prototype storage and authentication boundaries would multiply complexity with every new feature.
Create one scalable runtime without silently moving personal data or losing the pay-period workflow that made the product useful.
Introduce workspace ownership, sessions, relational records, optimistic versions, and additive migrations; verify the new path; then remove the obsolete runtime and transition layers.
One PostgreSQL startup path, one authenticated mutation boundary, cross-user isolation, conflict protection, and a smaller mental model despite substantially richer behavior.
- 01Record the target before moving data
ADRs captured ownership, migration, authentication, concurrency, and retirement decisions before runtime responsibilities changed.
- 02Make Flyway the only schema authority
Additive migrations introduced accounts, workspaces, sessions, typed records, projection roles, planning settings, and audit history.
- 03Move identity into the database
Signup, sign-in, session recovery, sign-out, CSRF, and membership checks replaced browser Basic authentication and global context.
- 04Consolidate around the aggregate
The browser owns one canonical draft and saves one expected version. The backend locks, validates, replaces, and audits the workspace transactionally.
- 05Delete verified transition architecture
Once independent re-entry was chosen, the JSON runtime, JSONB bridge, migration administration, and unowned compatibility rows were retired.
A visible path from UI to ownership
Each layer has one reason to change. HTTP resolves current workspace authority, application services own commands and queries, domain helpers own calculations, and repositories own relational details.
- 01React + Redux Toolkit
Session recovery, one canonical draft, editing workflows, and projections
- 02Spring Boot HTTP boundary
Workspace authority, CSRF, validation, and intentionally safe errors
- 03Queries and commands
Normalization, calculations, presentation, and versioned replacement
- 04PostgreSQL + Flyway
Identity, relational financial records, ownership, and audit history
Coherence over granular convenience
Projections depend on several related collections. Replacing one expected version gives the user a clear save boundary and guarantees that derived results come from one coherent workspace state.
A deliberate collaboration limit
Requests are larger and conflicts occur at aggregate scope. The decision should be revisited for real-time collaboration, external clients, or independently owned subdomains, not merely because a file looks long.
Database-backed sessions, HttpOnly cookies, CSRF-protected writes, current membership checks, safe error mapping, and workspace-scoped transactions keep every operation attached to an authorized owner.
Claims with scope and limits
The repository's qualified evidence report (opens in a new tab) maintains current counts and limitations. This portfolio summarizes the durable risk coverage across product behavior, PostgreSQL, live-browser, accessibility, responsive, and security checks.
Authentication, workspace isolation, save and reload persistence, stale-write conflicts, accessibility rules, responsive containment, and the relational runtime execute together against isolated schemas.
This is not cross-browser certification, a manual screen-reader audit, proof of zero vulnerabilities, or production operational readiness. Those boundaries stay explicit in the evidence report.
More real behavior, less accidental architecture
Pay Period Planner now tells one coherent product and engineering story: an authenticated user owns a relational workspace, edits one canonical draft, and saves against an expected version. PostgreSQL is the only runtime store, and obsolete personal data is neither seeded nor preserved as permanent infrastructure.
Hosting, managed backups, centralized telemetry, abuse controls, and demo reset policy remain deployment work. They are intentionally not disguised as completed production capabilities.