Skip to content

Repository files navigation

Busy2Easy (v0.1 — local skeleton)

A ground-up rebuild of the Busy2Easy concept as a modern, local-first web app: Next.js + TypeScript + PostgreSQL (via Prisma), replacing the Excel-file backend and single-machine WinForms app with something you can actually grow, deploy, and hand off to other developers.

This skeleton is intentionally a skeleton — it's built to run, look and feel right, and be obviously extensible, so we can decide together which module to flesh out first with real business logic and API routes.

What's in here

  • Company Setup — the industry → sub-category cascading picker, transcribed exactly from the existing Form1.vb (ComboBox5/ComboBox8), plus the Fundamentals and Financial Details fields from the original design.
  • Accounting — the full chart of accounts from General Ledger list.docx, organized by Asset/Liability/Equity/Revenue/Expense, ready to attach transactions to.
  • CRM, HR, Legal, Tax, Reports — module shells with the real tax taxonomy and report list from the source docs, ready for their own data models.
  • Prisma schema (prisma/schema.prisma) — Company → Departments (with a real self-referencing org hierarchy, not a flat list) → Accounts → Transactions → Contacts → Tax Records. One generic Transaction model replaces the ~20 near-identical VB.NET forms.

Navigation

The sidebar now reflects the full intended information architecture — Home, Business, People, Customers, Projects, Documents, Operations, Business Assistant, Settings — 9 groups, ~35 items. Anything without a real page behind it yet is marked Soon and isn't clickable; there are no dead links pretending to be finished features. As modules get built, flip their status from "soon" to "live" in src/lib/navigation.ts and add the route — everything else (sidebar, mobile drawer, command palette) picks it up automatically.

Navigation Assistant

A toggleable command palette (src/components/assistant/NavigationAssistant.tsx):

  • Open it via the floating button (bottom-right) or Cmd/Ctrl+K
  • Type to search any of the ~35 nav items by name or group, fuzzy-matched
  • Arrow keys + Enter to jump straight there — mouse optional
  • Contextual tip at the bottom, keyed to whatever page you're currently on (src/lib/page-tips.ts) — add an entry there for any new page you build
  • Turn off assistant inside the palette disables it entirely (preference saved in the browser); a small "Enable guide" pill stays in the corner to turn it back on

Device compatibility

  • Phone / narrow tablet: the sidebar becomes a slide-in drawer opened from a top app bar (hamburger menu), tables scroll horizontally instead of breaking layout, and grids collapse to a single column.
  • Tablet landscape / laptop / desktop: the fixed sidebar + top search bar layout from before.
  • Smartboards / large displays: above 1800px viewport width, base font size and tap targets scale up so content stays legible from a distance and touch input stays reliable.

All of this is one codebase — there's no separate mobile build to maintain.

What changed in this pass

  • Renamed VexBusiness → Busy2Easy throughout (package name, page title, sidebar wordmark).
  • Real charts (via Recharts) on the dashboard — revenue vs. expenses trend and an expense breakdown — using illustrative sample data shaped like what the ledger will produce once transactions flow through Accounting.
  • Motion (via Framer Motion) — animated count-up stats, staggered card reveals, a sliding active-tab indicator in the sidebar, and page-transition animations in the setup wizard.
  • Company Setup is now a 4-step guided wizard instead of one long form — aimed at someone who doesn't want to parse "Fiscal Year End" and "VAT Number" on the same screen as their first field. Plain-language dashboard copy for the same reason ("See your money, clearly" instead of "Accounting").
  • Country / State / Currency are now select-only (searchable, but you can only commit a value that's in the list) — no more typos or invalid entries.
  • HR, Legal, and CRM now have real structured tables/sections instead of a bare upload button.
  • No fabricated numbers anywhere — stats and charts show an honest "no data yet" state until real transactions exist.
  • Responsive layout — see "Device compatibility" above.

Reliability fix: no more silent hangs

Every page that fetches data used to call fetch(...).then(setState) (or an async function with no try/catch) with no error handling at all. If that fetch failed for any reason — a dropped connection, a non-JSON error page, anything — the promise rejected silently, setState never ran, and the page sat on its loading spinner forever with no indication anything was wrong. That's what caused the dashboard to hang on "Loading dashboard data..." even when the API itself was working correctly when tested directly.

Fixed properly, not patched around: every data-fetching page now uses a shared fetchJSON helper (src/lib/fetch-json.ts) that throws a real, readable error on failure, wrapped in try/catch, with a visible error screen and a Retry button (src/components/ui/ErrorState.tsx) instead of an infinite spinner. If something does go wrong now, you'll see what and be able to retry — not guess.

What went wrong before, and why we didn't switch to mock data

If you hit the "stuck on Loading" bug again: open the browser's DevTools (F12) → Network tab on the live page, reload, and look at the actual request to whichever /api/... endpoint is failing — the status code and response body will now be visible in the error screen too. Compare that to what you get testing the same endpoint directly; if they differ, that's the next thread to pull. Mock data was considered and deliberately rejected as the fix here — the database, Prisma, and the API were already confirmed working; the bug was purely a frontend error-handling gap, now closed everywhere.

Performance

Two real fixes applied, not just tuning:

  • Every API route is now export const dynamic = "force-dynamic" — Next.js was previously trying to pre-render some routes at build time, which meant database queries were running during the Vercel build itself. This is what caused the Can't reach database server build failures.
  • Balance and dashboard queries now aggregate at the database level (groupBy/_sum) instead of fetching every transaction row and summing in JavaScript. The dashboard summary also only pulls the last 6 months of transaction detail — bounded, not unbounded — while still using an all-time aggregate for the headline balances.
  • Indexes added on every companyId foreign key (and accountId, date where queries filter on them), so lookups stay fast as data grows instead of degrading linearly with table size.

If the live site still feels slow on first load after being idle: that's very likely Neon's free-tier "scale to zero" behavior — the database goes to sleep after inactivity and takes a moment to wake on the next request. That's expected free-tier behavior, not a bug in this codebase; a paid Neon tier (or periodic keep-alive pings) removes it if it matters for your use case.

Newly implemented this pass

Six modules that were "Soon" placeholders are now fully real — real Prisma models, real API routes, real UI:

  • Notifications — a real activity log, auto-generated whenever a transaction, contact, employee, asset, project, or bank account is added elsewhere in the app (see src/lib/notify.ts)
  • Assets — company equipment/vehicle/property register
  • Inventory — stock levels with reorder-point tracking (flags low stock automatically, including a Notification)
  • Projects & Tasks — projects with linked tasks, status updates inline
  • Banking — linked bank accounts (reconciliation still happens through Accounting; this isn't live bank-feed integration)
  • Files / Templates / Approvals — folded into the existing Documents module (Legal) as additional categories, rather than three more separate half-built pages

Still genuinely not implemented, and why: Inbox, Recruitment, Attendance, Sales, Marketing, Support, Purchasing, Manufacturing, Logistics, Insights, Automation, Workflows, Organization, Security, and Billing remain "Soon." Most of these need something bigger than a CRUD page to be real — email integration (Inbox), a rules/automation engine (Automation, Workflows), payment processing (Billing), or genuine multi-user authentication (Organization, Security) — and building shallow versions of them would mean more screens that look done but aren't, which is the opposite of what this project has been about. Worth tackling deliberately, one at a time, when you're ready for each.

Design system: "The Ledger"

A dark ink-teal ground with brass-gold and sage accents, serif display type (Fraunces) paired with a clean body sans (Inter) and a tabular monospace (IBM Plex Mono) for figures — evoking ruled ledger paper without looking like a spreadsheet. This was a deliberate choice to feel premium and trustworthy for financial data, distinct from generic SaaS templates.

Fully wired — what's real now

Every module now reads and writes to Postgres for real, via API routes under src/app/api/:

  • Company Setup saves as you move between steps, and reloads your data on return. Departments are fully unlocked (no premium gate) and functional — add one, it's saved and listed immediately.
  • Accounting shows real computed balances (a straight sum of recorded transactions per account — single-entry for this stage, not full double-entry debit/credit bookkeeping). Click any account to record a transaction; add custom accounts beyond the seeded chart.
  • CRM — add a contact, it's saved and grouped by type immediately.
  • Tax — click a register to log a real payable/receivable/refund entry; each card shows its running total.
  • HR — Employees are fully real (add one, assign a department). Payroll Runs and Leave Requests are honestly labeled as not yet modeled — they need their own database tables before they can be real, same principle we've used throughout: no faked completeness.
  • Legal — file upload is real. Files are written to public/uploads on local disk and tracked in the database.
  • Dashboard — stats and charts now compute from your actual transactions. With no data yet, it honestly shows "No data yet" instead of a fake number; once you record transactions in Accounting, everything here fills in live.

One important simplification: there's no login system yet, so the whole app currently operates as a single company (src/lib/current-company.ts). Every API route reads/writes against one record. Real multi-user accounts are a separate, bigger piece of work — worth doing once you're ready to have more than one person or company using this.

Deployment note for file uploads: writing to local disk (public/uploads) works for local dev and most traditional hosts, but Vercel's serverless filesystem doesn't persist uploaded files between requests. If you deploy Legal's file upload to Vercel, swap the disk write in src/app/api/documents/route.ts for Vercel Blob or S3 — the database side (name, category, fileUrl) doesn't need to change.

After the steps below, every button in the app does something real — nothing is a dead click.

Getting started (in VS Code)

You'll need Node.js 20+ and Docker installed locally — this sandbox has no network access, so dependencies haven't been installed yet.

# 1. Install dependencies
npm install

# 2. Start local Postgres
docker compose up -d

# 3. Set up your environment
cp .env.example .env

# 4. Push the schema and seed reference data (chart of accounts + industries)
npm run db:push
npm run db:seed

# 5. Run the app
npm run dev

Open http://localhost:3000 — that's your "local website."

Already had this running before this update? Just run npm run db:push again to add the new Employee/Document tables — your existing data stays put.

Browse the data visually any time with npm run db:studio.

Architecture

src/app/            → pages (one folder per module: accounting, crm, hr, legal, tax, reports)
src/components/      → layout/, ui/, and per-module components
src/lib/             → reference data (chart of accounts, industries) + db client
src/services/        → (next) business logic — calculations, validation, rules
prisma/schema.prisma → the data model, version-controlled from day one

Each module is self-contained, so adding a new one (e.g. Inventory, Payroll) never requires touching existing modules — that's what makes this "customizable" in the way the original desktop app wasn't.

What's stubbed vs. real

  • Real & accurate: the chart of accounts, the industry/sub-industry taxonomy, the tax type list, the data model relationships.
  • Stubbed (UI only, no API wiring yet): forms don't save, buttons don't submit, dashboard numbers are placeholders. This is the shell — next step is wiring up real API routes and forms module by module.

Suggested next steps

  1. Pick one module (Company Setup is the natural first one — everything else depends on it) and wire up real create/read/update via API routes + Prisma.
  2. Add authentication (NextAuth.js is the natural fit for this stack).
  3. Bring over the multi-language support from the original app (the design system already has room for it via a simple i18n dictionary layer).
  4. Layer in the Department/org-hierarchy premium feature once the base Company + Account models are proven out.

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages