← All Posts

When No Framework Is the Right Framework

5 min readMarch 1, 2026
htmlcssjavascriptno-frameworkvercelweb-fundamentals

When No Framework Is the Right Framework

When No Framework Is the Right Framework
When No Framework Is the Right Framework

Trip Planner — Bangkok · Hong Kong · Sanya itinerary
Trip Planner — Bangkok · Hong Kong · Sanya itinerary

Every new project I start, my first instinct is to npx create-next-app. It's fast, familiar, and I know all the gotchas. But for a trip planning tool, I made a different call: no framework, no npm, no build step.


The Constraint

The rule was simple: if I couldn't do it with what the browser ships, it didn't belong in the tool.

No React. No bundler. No node_modules. Just an index.html, a stylesheet, and a script tag.


What the Platform Gives You for Free

It's easy to forget how capable modern browsers are when you're always reaching for a framework. A few things I rediscovered:

Fetch API — async data fetching without axios, without SWR, without React Query.

CSS Grid + Custom Properties — responsive layouts and design tokens without Tailwind.

Template literals — dynamic HTML generation without JSX.

<dialog> element — native modals with keyboard trap and backdrop, no library needed.

localStorage — client-side persistence without a state management library.


What I Built

  • Day-by-day itinerary builder
  • Destination notes per day
  • Packing list with check-off
  • Clean print layout (it's a travel tool — people actually print these)

The Deploy Story

Vercel deploys static HTML with zero configuration. Push to main, it's live in under 10 seconds. No build command, no output directory to configure, no environment variables. The simplest possible path from code to URL.


When to Use This Approach

No framework makes sense when:

  • The tool is small and the scope is fixed
  • You don't need server-side rendering or API routes
  • Performance matters more than developer ergonomics
  • You want zero maintenance surface (no dependency updates, no security patches)

It stops making sense when you need shared state across many components, server data fetching, or a team working on the same codebase.


The Real Lesson

The constraint forced clarity. Every feature I considered had to justify its complexity. If it required component state or lifecycle management, I asked whether the tool actually needed it — or whether I was just defaulting to framework thinking.

Most of the time, it didn't need it.