The Problem
You're building a company landing page. Five static pages, a contact form, some animations. Your instinct: reach for React or Next.js. Why? Because that's what you know, that's what's on your resume, that's what everyone uses. AI scaffolds a Next.js project in seconds. You now have: a build process, 47 dependencies, 300MB node_modules, hydration to debug, and a 250KB bundle for what should be 20KB of HTML.
The problem: Framework overhead makes sense for complex apps but kills simple sites. AI makes both equally easy to build, so you never feel the cost until deployment.
Vanilla HTML/CSS/JS used to be harder because you'd reinvent basic functionality. AI changes that equation - it writes the vanilla code just as fast as framework code, but the vanilla version ships lighter and runs faster.
The Core Insight
With AI assistance, vanilla implementations are fast to build and maintain. For content-heavy sites with light interactivity, vanilla beats frameworks on every metric that matters: load time, bundle size, maintenance burden.
Modern web standards give you: CSS Grid, Flexbox, CSS Variables, async/await, Fetch API, IntersectionObserver, Web Components. AI knows all of these. You don't need React for layouts or jQuery for AJAX anymore.
When Vanilla Wins
Use Case 1: Marketing Sites
Profile: 5-20 pages, mostly static content, contact form, some animations.
Why vanilla:
- SEO critical - no hydration delays
- Content rarely changes - no need for complex state
- Performance matters - first impression is everything
- Non-devs update copy - HTML is readable
What you gain:
- Load time: <1 second
- Bundle size: 10-30KB total
- Deploy anywhere: S3, Netlify, even GitHub Pages
- No build step: edit HTML, refresh, done
// Prompt for AI:
"Create a marketing landing page with vanilla HTML/CSS/JS.
Requirements:
- Hero section with animated gradient background
- Features grid (3 columns, responsive)
- Testimonials carousel (no library, use IntersectionObserver)
- Contact form posting to FormSubmit.co
- Smooth scroll navigation
Design:
- Mobile-first with CSS Grid/Flexbox
- CSS custom properties for theming
- No frameworks, no build step
- Single HTML file acceptable (or minimal splitting)
Performance targets:
- < 50KB total HTML/CSS/JS
- Load in < 1 second on 3G
- 100 Lighthouse score"
Use Case 2: Documentation Sites (Simple)
Profile: Docs written in markdown, need search, responsive, fast.
Why vanilla (with a twist):
Actually, use a docs generator (Docusaurus, Mkdocs), but understand vanilla is the fallback for custom docs that don't fit a template:
// For custom documentation UI:
"Create a documentation page template using vanilla HTML/CSS/JS.
Features:
- Left sidebar navigation (auto-generated from headings)
- Sticky table of contents on right
- Code syntax highlighting (use Prism.js, only dependency)
- Copy button for code blocks
- Dark mode toggle (saves to localStorage)
- Search with Fuse.js for fuzzy matching
Structure:
- Main content is markdown converted to HTML
- Progressive enhancement: works without JS
- No build step required (but can run through markdown parser)"
Use Case 3: Prototypes and MVPs
Why vanilla for early stage:
You don't know if this product will work. Build the simplest version to validate:
// Prototype prompt:
"Build a minimal viable product for a [product idea] using vanilla HTML/CSS/JS.
MVP Features:
- [Core feature 1]
- [Core feature 2]
- [Core feature 3]
Constraints:
- Single page application (literally one HTML file if possible)
- All data in localStorage (no backend yet)
- Can demo to users immediately
- Easy to iterate - no build/deploy cycle
If this validates, we'll migrate to [real stack] later."
The PickBits.AI Case Study
This site is vanilla HTML/CSS/JS. Why? It's a content site with minimal interactivity. AI generated all pages following a consistent style. Deployment is drag-and-drop to S3. Load time is under 1 second globally. Maintenance is trivial. A React version would offer zero user benefits and significant developer costs.
Modern Vanilla Patterns
State Management Without React
// AI can generate clean vanilla state:
"Create a vanilla JS state management pattern using Proxy.
Requirements:
- Observable state changes
- React-like state updates
- Auto-update DOM when state changes
- No framework dependencies
Example usage:
const state = createState({ count: 0 })
state.count++ // DOM auto-updates"
AI output:
function createState(initialState) {
const listeners = new Set()
const handler = {
set(target, property, value) {
target[property] = value
listeners.forEach(listener => listener(target))
return true
}
}
const state = new Proxy(initialState, handler)
state.subscribe = (listener) => {
listeners.add(listener)
return () => listeners.delete(listener)
}
return state
}
// Usage:
const state = createState({ count: 0 })
state.subscribe(state => {
document.querySelector('#count').textContent = state.count
})
document.querySelector('#increment').onclick = () => {
state.count++
}
Component Pattern Without Framework
// Web Components for reusability:
"Create a reusable modal component using Web Components.
Requirements:
- Custom element:
- Shadow DOM for style encapsulation
- Slot for content
- Accessible (ARIA, keyboard nav)
- No build step
Usage:
Title
Content here
"
Routing Without SPA Framework
// Hash-based routing for single-page feel:
"Create a vanilla JS router using URL hash.
Requirements:
- Route definitions like: { '/': HomePage, '/about': AboutPage }
- Handle browser back/forward
- Update nav highlighting
- No page reload
- Fallback to 404 page
Keep it under 50 lines."
When Vanilla Doesn't Work
Be honest about limitations. Reach for a framework when you hit these:
| Sign It's Time for a Framework | Why Vanilla Hurts |
|---|---|
| Component tree more than 3 levels deep | Prop drilling and state become messy |
| Frequent data mutations requiring DOM updates | You're reimplementing React's reconciliation |
| Team collaboration on complex UI | Hard to maintain conventions without framework structure |
| Real-time data synchronization | State management gets complex fast |
| Large codebase (>5000 lines of JS) | Lack of structure creates spaghetti |
The Progressive Enhancement Path
Start vanilla, add complexity incrementally:
- Pure HTML/CSS: Works with JS disabled, content is accessible
- + Vanilla JS: Enhance with interactions, save to localStorage
- + Alpine.js: Add reactivity without build step (good middle ground)
- + htmx: Add dynamic server interactions without much JS
- + React/Vue: Only when you've outgrown simpler options
Alpine.js: The Vanilla+ Sweet Spot
Alpine.js gives you Vue-like reactivity in HTML attributes. No build step, tiny footprint (15KB). AI knows Alpine well. Great middle ground between vanilla and full framework.
Deployment Advantages
Vanilla sites deploy anywhere cheaply:
- Netlify/Vercel: Free tier forever, just drag-and-drop
- AWS S3 + CloudFront: Pennies per month, global CDN
- GitHub Pages: Free, automatic from repo
- Cloudflare Pages: Free, instant global distribution
Compare to Next.js SSR needing a Node server, or SPA needing special handling for client-side routing.
The "Just Add React" Trap
Easiest decision: add React for one interactive component. Hardest decision later: remove React when you realize it was overkill. Start vanilla, resist framework until pain is real, not anticipated.
Quick Reference
Choose Vanilla When:
- Content is static or infrequently updated
- Interactivity is forms, animations, simple toggles
- SEO is critical
- Performance is top priority
- Non-developers need to edit content
- Simple deployment is desired
Choose Framework When:
- Heavy client-side state management
- Component tree depth > 3 levels
- Real-time data synchronization
- Large team needs structure
- You're building a web app, not a website
Vanilla Stack Recommendation:
HTML5 semantic elements
CSS Grid + Flexbox for layouts
CSS Custom Properties for theming
Vanilla JS (ES6+) for interactions
Web Components for reusable UI
Fetch API for async requests
IntersectionObserver for lazy loading
localStorage for client state
FormSubmit.co or similar for forms
Deploy to: S3, Netlify, GitHub Pages
Prompt Template for Vanilla:
"Create [feature] using vanilla HTML/CSS/JavaScript.
Requirements:
- No frameworks or build tools
- Modern browser features only (no IE11)
- Progressive enhancement (works without JS)
- Accessible (ARIA, semantic HTML, keyboard nav)
- Mobile-first responsive design
Constraints:
- Single file or minimal file structure
- Total size < 50KB (excluding images)
- No external dependencies except [specific tool if needed]
Follow web standards and best practices."