2026In Development

pda777

Vanilla JS · Express 5 · PostgreSQL · Next.js 16 · Prisma · Auth.js · OpenAI API

Overview

A nine-domain life organizer rebuilt twice: first as zero-framework vanilla JS, then as Next.js 16.

pda777 is a personal life organizer that pulls nine domains into one app: productivity, habits, health, goals, journal, notes, calendar, finances, and a dashboard that reads them all back. It started as a friend's vibecoded HTML prototype and became a full product, rebuilt twice over: first as a zero-dependency vanilla SPA on an Express 5/PostgreSQL API, then as a Next.js 16 rewrite on Prisma and Auth.js. The rewrite is the version in use today, and all nine domains work in it.

It runs as a joint venture with the friend who owns the product, with the SaaS foundation already in place: a premium tier, creator codes, and an admin analytics suite. Two generations share one repo and one PostgreSQL lineage, which makes the project a clean study in doing it twice: the domain model and the user-scoping discipline carry over, while a hand-rolled hash router gives way to a typed route tree, raw SQL to Prisma, hand-built token rotation to Auth.js.

pda777 dashboard: a three-by-three grid of module cards (productivity, finances, health, recap, habits, logs, goals, calendar, journal) on a dark interface
nine domains, one grid: the dashboard

How did a prototype become a product?

The original was a personal organizer the customer had built himself in plain HTML and vanilla JavaScript: real features, quick construction. In summer 2026 it was handed over for a professional rebuild and got one: a vanilla SPA with a 152-line hash router in front, an Express 5 API with raw parameterized SQL behind it, every query scoped by user_id. Both generations live in one repository, and the initial commit tells the story in miniature: the entire first rebuild, filed under 'legacy PDA' on day one, because the Next.js rewrite was already underway by the time the code reached git.

Why is the first rebuild plain JavaScript with no build step?

The customer has to live with the code, and he doesn't write TypeScript. So the first rebuild met him where he is: plain JavaScript end to end, a frontend running without a framework or a build step, pages fetched as HTML partials by the router, which re-executes their script tags and rewrites their cache-busters against a version constant. The only third-party code in the whole frontend is Quill, for rich text. The constraint bought something real: the owner can read every line of the product he owns.

What did the Next.js pass change?

The second pass moved the product onto Next.js 16, React 19 and TypeScript, and the upgrades are the kind you can point at. The hand-built token system (15-minute access tokens, 30-day refresh tokens, a shared promise so ten failing calls produce one refresh) became a single Auth.js session strategy. Raw SQL became Prisma, and a deletion routine that hand-enumerated 18 tables in dependency order became onDelete: Cascade. The whole API surface ships typed: 49 route files, 78 handlers, one authed() wrapper doing the session check in one place.

What does it actually look like?

It looks like a tool: one dark, monochrome interface where every module keeps the same shape, a list, a detail view, a history. Habits carry current and best streaks; the journal carries mood and tags; the calendar is a month grid with colored events; and health tracks workouts, body weight and the weekly routine. Above it all sit the two cross-module views: the dashboard grid and the recap, which reads the whole system back in four numbers.

pda777 habits view: today's habit cards with current and best streaks on the left, a per-day completion grid with percentages on the right
habits: boolean and count types · streaks in sql
pda777 health view: workout history with body weight above a Monday-to-Sunday routine row
health: logged workouts · body weight · the weekly routine
pda777 journal view: an entry list with mood dots and tags beside a rich text editor
journal: rich text entries · mood · tags
pda777 calendar view: a month grid with colored events beside an upcoming list
calendar: month grid, upcoming, colored events

What does the AI day score do?

Every day gets a grade. The day's activity logs and the active goals go to GPT-4o-mini, and a 0-100 score with a one-line read comes back, stored per user and date so the history builds into a trend. The first rebuild ran that on a midnight cron, Europe/Berlin, scoring the day while you slept; the rewrite puts it behind a Score now button next to the day's log. Either way the effect is the same: a stressful day closes with a number that says it still counted, and the chart shows the streak.

pda777 productivity view: today's activity log with entries and a score on the left, a productivity-over-time line chart and scored history on the right
the day's log, the ai score, the trend

Which module carries the most engineering?

Finances. It's the module the project's own wiki calls the most complex: transactions, budget categories, monthly planning keyed per user, category, year and month, and investment portfolios across eleven asset types. It's also where the two rebuilds show their characters. The first version stored a running balance on every transaction row, so the ledger read instantly; the rewrite computes the balance at read time instead, so an edit anywhere in history costs nothing extra. Same feature set, better shape: that is what building it twice buys.

pda777 finances overview: income, expense and savings categories in a budget table with tracked, budget, completion and remaining columns
finances: overview, charts, budget planning, transactions

Why build a product twice?

Because the lessons compound. The first rebuild applied discipline inside the customer's constraints: zero dependencies, hand-rolled routing, raw SQL under one invariant, every query scoped by user_id. The second applied the modern stack without touching the domain model: the same schema lineage, now 28 Prisma models with cascading deletes. Along the way the project picked up production habits most products never ship: every request logged into Postgres and turned into response-time percentiles, slow-endpoint rankings and anomaly detection; an admin suite with retention cohorts, funnels and AI cost tracking; GDPR consent and age verification enforced at registration. And because the product is aimed at becoming a SaaS, the commercial layer is already modeled: a premium tier, a price constant, and creator codes in the Fortnite sense, referral discounts that pay the creator.

What happens next?

The rewrite is in use today, and the roadmap is defined with the customer: the admin area on the new stack, automated scoring runs, creator-code onboarding, and the switch that turns the modeled subscriptions into live ones. Every piece has groundwork in place. The product grows from here: nine domains, one schema, and a second version built to be the one that lasts.

pda777 recap view: four summary cards (today's score, habits done today, active goals, net this month) above the latest note
recap: the whole system in four numbers

Field notes

  • ~34,000 lines across the three codebases: ~14,700 vanilla SPA, ~4,100 Express API, ~15,100 Next.js rewrite.
  • 142 endpoints in the legacy API across 14 route mounts; 78 typed handlers across 49 route files in the rewrite.
  • Zero npm dependencies in the SPA; the only bundled third-party code is Quill, for rich text.
  • 32 PostgreSQL tables in the first rebuild, 28 Prisma models in the rewrite; a hand-maintained 18-table deletion cascade became onDelete: Cascade.
  • First-rebuild auth: 15-minute access and 30-day refresh JWTs in httpOnly cookies with rotation, bcrypt cost 12, GDPR consent and age verification enforced by Zod at registration.
  • AI scoring: GPT-4o-mini, temperature 0.4, JSON mode; the day's logs and active goals go in, a 0-100 score and reasoning come back, upserted per user and date.
  • Habit streaks run in SQL with the islands technique: log_date minus ROW_NUMBER, current streak via DISTINCT ON, best-ever via MAX.
  • Every request lands in an api_logs table that becomes response-time percentiles and anomaly detection, watched by an admin suite with retention cohorts, funnels and AI cost tracking: 17 monitoring endpoints in total.

Source

github.com/notdezzi/pda777