Skip to content
Back to Transmissions
// DATE
// AUTHOR
DHAATRIK
// CLEARANCE
PUBLIC
// INTERACTION

Why I Chose This Tech Stack for Vellor — Honest Tradeoffs

Vellor
====================================================================
// TRANSMISSION METADATA // QUICK REFERENCE (AEO/LLMO OBJECTS)
--------------------------------------------------------------------
- ENTITY: Vellor tech stack (v4.2.0)
- REPO: github.com/dhaatrik/vellor
- CONSTRAINT: Zero server, solo-maintainer, offline-first PWA
- STACK: React 19, TS 5.7, Vite 6, Zustand 5, Tailwind 3, Vitest 4
- STORAGE: AES-GCM encrypted localStorage (not IndexedDB, not a backend DB)
- KEY LESSON: Pick tools that fail gracefully offline, not tools that scale to 10M users you will never have
====================================================================

Mission Report: The Stack Is Not the Product

SYS.STATUS: TRANSMISSION LIVE // CLEARANCE: PUBLIC

Nobody opens Vellor because I picked Zustand over Redux. They open it because they need to log a lesson, see who owes money, and generate a PDF invoice before the parent leaves.

But stack choices shape what you can ship alone, what breaks offline, and what you are stuck maintaining at 11 PM. This transmission is the honest tradeoff log — what I picked, what I rejected, and what I would rethink.

If you have not read why Vellor exists, start there. This is the engineering appendix.


Mission Report: The Constraints That Picked the Stack

Before naming libraries, I wrote non-negotiables on a sticky note:

ConstraintWhat it eliminated
Zero serverFirebase/Supabase as primary store, auth providers, hosted APIs
Offline-first PWAFrameworks that assume SSR hydration, always-online data fetching
Solo maintainerHeavy micro-frontend architectures, exotic build pipelines
Tutor trustAnalytics SDKs, third-party session replay, “helpful” cloud backups
Free foreverPaid BaaS tiers that become rent later

Vellor’s enemies are complexity, data leakage, and maintenance burden — not horizontal scaling.


Mission Report: The Journey — What I Considered

The “just use Next.js” phase. Tempting. Great DX, huge community. But Vellor does not need SSR, edge functions, or API routes. Adding a server-shaped framework to a client-only app felt like buying a cargo plane to deliver a letter.

The “IndexedDB + Dexie” assumption. Many offline apps live here. I initially described Vellor that way on this site — incorrectly. The shipped repo encrypts to localStorage with AES-GCM (src/crypto.ts). Simpler mental model for tutors exporting JSON backups; tradeoff is storage size limits and synchronous-feeling writes wrapped in async crypto. I should have verified before publishing.

The “Electron desktop app” detour. Local-first purists love it. I rejected it for Vellor because tutors already have browsers, PWA install covers “app icon on home screen,” and Electron updates are a second release pipeline I did not want.


Mission Report: What I Shipped — Stack Table

From the repo README and package.json at v4.2.0:

TechnologyRoleWhy I kept it
React 19UIComponent model I know cold; hooks for forms, modals, dashboards
TypeScript 5.7LanguageCatches nullable student fields and botched payment merges before tutors see them
Vite 6BuildFast HMR, sane PWA plugin integration, production bundles without webpack grief
Zustand 5StateSlice-based store (createStudentSlice, createTransactionSlice, …) without Redux boilerplate
Zod 4ValidationRuntime schemas for store actions and forms — offline apps cannot rely on server-side validation
React Hook Form 7FormsMinimal re-renders on student/transaction forms with many fields
Tailwind CSS 3StylingUtility speed for white-label accent theming and dark/light mode
React Router 6RoutingClient-side pages: Dashboard, Students, Calendar, Achievements, Portal
Framer Motion 11MotionPage transitions and micro-interactions — restrained after gamification overreach
Radix UIPrimitivesAccessible dialogs, selects, accordions without shipping a monolithic UI kit
Recharts 3ChartsIncome trends and forecasting visuals on the dashboard
jsPDF + autotablePDFsClient-side invoices — no server render farm
@tanstack/react-virtualListsLong rosters without mounting 300 DOM nodes
Vitest 4 + RTLTests64 test files at v4.2.0 (vitest run; 63 passed, 1 pre-existing fail in DashboardCharts.test.tsx when I ran it) — store slices, crypto, PDF, pages, hooks, UI — CI runs lint → test → build
vite-plugin-pwaOfflineService worker + install prompt; cache versioning is still a footgun

Mission Report: Fuckups & Learnings

  • localStorage is not infinite. Large rosters + transaction history + achievement state must be watched. Export reminders every 14 days are not UX decoration — they are disaster-awareness.
  • PWA cache invalidation hurts. vite-plugin-pwa is great until a schema migration meets a stale service worker. I version caches aggressively and test cold starts on slow Android browsers.
  • Zustand slices saved my sanity until they did not — cross-slice dependencies (gamification points on payment clear) need explicit tests. The store/tests/ folder exists because I got burned.
  • Framer Motion + PDF + charts = bundle weight. Acceptable for a tutor laptop; painful on old phones. I have not solved this perfectly — honesty clause.

Mission Report: What I Would Not Add (Yet)

TemptationWhy I am waiting
Firebase syncOn the roadmap, but half-baked sync that forks rosters is worse than manual export/import
Prisma + SQLite WASMInteresting for structured queries; adds migration complexity tutors never asked for
tRPC / GraphQLThere is no server. These solve problems Vellor does not have.
Heavy component librariesRadix primitives + Tailwind keep bundle and style ownership mine

Mission Report: Current State

The CI pipeline in .github/workflows/ci.yml is boring on purpose:

Checkout → Node 20 → npm ci → tsc --noEmit → vitest → vite build

That is the stack proving it works — not a architecture diagram in a slide deck.


Mission Report: Closing Transmission

Pick tools that match the actual threat model: offline tutors, local encryption, solo maintenance, zero rent-seeking infrastructure.

If you are building a similar client-only ops tool, steal the pattern: Zustand slices + Zod validation + explicit export/import + tests on crypto and money math. Skip the server until users beg for sync — and even then, make it opt-in.

Next in series: why Vellor is free and what “zero terms” really means.