Why I Built a Crypto SaaS in Vanilla JavaScript (No React, No Build Step)
In 2026, suggesting "no framework" feels heretical. Every SaaS template is Next.js. Every Twitter dev is shipping React Server Components. The default answer to "what stack?" has become "Next + Supabase + Tailwind + shadcn." This is what I almost did for AlphaDesk.
Instead I shipped 4,200 lines of vanilla HTML/CSS/JS. Open the demo — it's a real-time crypto intelligence terminal with whale tracking, funding rates, and live news. No npm run build. No bundler. No virtual DOM. It loads in 280ms and weighs 87KB gzipped.
Here's the honest retrospective: when vanilla JS won, when it would have lost, and when I'd reach for React next time.
For a single-developer dashboard with ~10 views, ~5 data sources, and ~5,000 lines of code, vanilla HTML/CSS/JS is faster to ship, faster to deploy, and easier for buyers to audit. For anything with complex client state, complex routing, or 5+ contributors, React earns its complexity tax.
Numbers from AlphaDesk
| Metric | Vanilla (AlphaDesk) | Next.js (typical) |
|---|---|---|
| Lines of code | ~4,200 | ~6,500–8,000 |
| Bundle size (gzipped) | 87 KB | 180–280 KB |
| Time to first byte | 100ms | 300–600ms |
| Build time | 0 (no build) | 15–60s |
| Deploy time (Vercel) | ~10s | 30–90s |
| Setup for new buyer | Open file → run | npm install → run |
| Audit difficulty | Trivial — view source | Hard — bundled output |
| Refactor velocity (1 dev) | ≈ same | ≈ same |
| Refactor velocity (3+ devs) | Slower | Faster |
| Type safety | JSDoc only | TypeScript |
What vanilla JS got right
1. Boilerplate buyers can audit before paying
I'm selling AlphaDesk on Gumroad as a $149-599 boilerplate. A buyer's first question: "is the code actually good?" With vanilla, they open the live demo, hit "View Source," and read 4,200 lines of readable HTML/CSS/JS. With React, they'd see app.bundle.js minified to one line of mangled output. Trust gap is real.
2. Zero build step kills entire categories of bugs
I never had to debug:
- Webpack config issues
- "Module not found" after upgrading a transitive dep
- "Next 14 → 15 breaking change" angst
- SSR hydration mismatches
- Tailwind purge config edge cases
- tsconfig drift between IDE and CI
Save → reload → it works. That's the whole loop.
3. Vercel's serverless functions slot in seamlessly
For the optional Pro tier I added Supabase auth + Stripe Checkout via Vercel functions in /api/*.js. These work the same with or without a frontend framework. Vanilla frontend doesn't lock you out of modern serverless backends.
4. Performance is a feature
87 KB gzipped, 100ms TTFB on Vercel free tier. Lighthouse score 100 on Performance, Accessibility, Best Practices, SEO. With a typical Next.js app you start at ~85 and have to hand-tune to get back to 100. Default-fast vs. default-slow.
5. Drop-in for any framework
Buyers who want the AlphaDesk dashboard in their Next.js app copy the relevant dashboard.js functions and the HTML structure. No "convert from React" needed. The opposite direction (React → vanilla) is much harder.
What vanilla JS lost
1. Type safety
I added JSDoc annotations on critical functions (fetchTxns(addr), scanWhales()) but it's not the same as full TypeScript. Refactoring across 10 files is slower.
2. Component reuse
I duplicated some HTML markup (e.g. the "panel" structure) in 4 places. With React, that's a <Panel /> component. With vanilla I copy-pasted. ~50 LOC bloat.
3. Routing for complex apps
AlphaDesk has 9 dashboard views, all in one HTML file with display: none toggling. For a 30-view app this would be unwieldy. I'd reach for page.js or hash routing — but at that point Next.js's built-in routing pays off.
4. Forms with complex validation
Login + signup forms (Pro tier) ended up with manual document.getElementById(...).value patterns. React Hook Form is just better here. ~80 LOC bloat.
5. Hot module reload
Save → manual refresh. Not as snappy as Next.js's HMR. Trivial cost for a single-developer iteration loop, more painful in a team.
When I'd reach for React next time
- 30+ views or routes: hash-routing breaks down.
- Real-time multiplayer / collaborative editing: state sync is hairy.
- 3+ developers: TypeScript + component contracts pay for themselves.
- SEO-critical content with dynamic data: SSR is genuinely useful here.
- Marketing / landing-page-heavy product with A/B testing: React's component primitives + libraries (e.g.,
experimentwrappers) are mature. - You already know React deeply: don't relearn for the sake of it.
When I'd stay vanilla
- Single-developer dashboard with ≤15 views.
- Boilerplate / template you'll sell to others: trust gap matters.
- Performance-critical: every byte counts (mobile, low-end hardware, third world internet).
- Long lifespan target (5+ years): React's ecosystem churns; vanilla is stable.
- Embedded in another app / framework-agnostic deploy: drops in anywhere.
The honest answer
"Vanilla vs React" is a fake debate. The real questions are:
- How many views does your app have? <15 = vanilla works. >30 = framework helps.
- How many developers? 1 = either. 3+ = framework + types.
- What's the deploy / iteration loop? Vanilla wins on speed-of-iteration for solo devs.
- What does the buyer / user need to do with the source? If they need to audit / fork / customize, vanilla wins on accessibility.
- What's the lifespan? Vanilla survives framework deprecations. React gets you a 3-year window before the next migration.
For AlphaDesk specifically — single-developer, 9 views, "audit before purchase" use case — vanilla was the right call. For a 30-engineer Stripe-scale product, obviously not.
The takeaway isn't "vanilla is better." It's that defaulting to React for everything is the actual mistake. Pick the lightest tool that handles your specific problem.
AlphaDesk's full source is open-readable on the live demo. The 3-tier boilerplate ships the same code so you can fork into your own niche.
View live demo →FAQ
Isn't vanilla JS just "old"?
The web platform in 2026 has way more built-in primitives than 2014: native ES modules, fetch, Web Components, async/await, optional chaining, structured cloning, IntersectionObserver, ResizeObserver. You don't need a framework to build a polished UI anymore — you needed one in 2015.
How do you handle state without React?
For AlphaDesk: localStorage + a few in-memory Sets. For more complex state, look at Nano Stores (1KB) or just a hand-rolled event emitter. 99% of "state management" libraries solve a problem React itself created.
What about styling?
Plain CSS with custom properties (--accent-green: #00ff88) gives you everything Tailwind does without the build step. The only Tailwind feature I genuinely missed was arbitrary values; CSS got those in 2024 with @property.
What about SSR / SEO?
If your content is server-rendered HTML (which AlphaDesk's blog articles are), Google indexes it the same as any framework. For client-rendered SaaS dashboards, SEO doesn't matter (auth-walled). For marketing pages with dynamic content, you'd want SSR — at which point a framework helps.