Built on web standards • Native to AI

Reach for the platform first.

Browsers ship modules, components, dialogs and fetch() . PHP and SQLite run on a £5-a-month host. VanillaFirst is the habit of checking what the platform already does before you install something to do it.

this page, measured in your browser
$ measure ./this-page
# plain HTML, two stylesheets, two small modules; no framework, no build step
# with JavaScript running, this window measures the page in your browser

Why the platform, and why now

For a decade the default answer to a new web project was a framework, a bundler and a few hundred packages. Three things have changed since that default was set.

The platform has arrived

Grid, <dialog> , ES modules, fetch() , Web Components and native CSS nesting ship in every current browser. The features people installed libraries for are built in, so a page goes from editor to browser with no compile step: save, refresh.

Native to AI

fetch() , querySelector() , PDO and SQL work as they did years ago, so what a model learned from older code is still correct. Framework APIs move between versions, and models mix them. The catch: ask an AI tool for an interface without naming a stack and it usually reaches for React. Say "plain HTML, CSS and JavaScript, no framework" in the prompt.

Learn the web, not a tool

HTTP, the DOM and SQL have outlived every framework built on top of them. Learn those, and any framework becomes a layer you can read rather than a box you can't open. Beginners who start with an abstraction get stuck when it leaks; beginners who start with the platform know where to look.

What it costs, and what it saves

The trade, row by row. The VanillaFirst column includes the limits, because a philosophy that hides its costs isn't worth adopting.

Concern Framework default VanillaFirst
Build Brittle A bundler and transpiler between your editor and the browser, with config to maintain. Zero build None. The browser runs what you wrote.
Dependencies High Hundreds of packages in node_modules , each an npm audit warning waiting to happen. Minimal None in the kits. Anything you add is one vendored file you can remove in an afternoon.
Hosting Complex A Node runtime, a separate database server, often a platform bill that grows with traffic. Simple PHP and one SQLite file on shared hosting or a small VPS. Limit: one writer at a time, one server.
Longevity Short Class components to hooks, Pages Router to App Router, Vue 2 to 3: each a migration. Long Browsers keep old pages working; SQLite supports its file format through 2050. Limit: pin your PHP version and upgrade on your schedule.
Onboarding Steep Learn the framework's conventions, then the project's. Day one Anyone who knows HTML, CSS, JavaScript and SQL can read the code.

The four rules

A default, not a dogma. When a project genuinely needs a framework, use one, deliberately.

  1. Default to the platform

    Use what the browser and the server already do before adding a package.

  2. Eliminate build steps

    No transpiling, bundling or compiling unless something genuinely needs it.

  3. Keep infrastructure simple

    One SQLite file and plain PHP before a database server and an orchestration layer.

  4. Build to last

    Write to the standards, pin your runtime, and upgrade on your schedule, not a framework's.

Questions people ask

Scaling, maintenance and the trade-offs, answered with the limits included.

Frontend, Backend or Full-Stack Kit, or VanillaSaaS: which one do I need?

Ask two questions: does anything need saving on a server, and will anyone sign in? Nothing saved on a server: the Frontend Kit. Data saved but no pages served: the Backend Kit. Data saved and pages served, nobody signs in: the Full-Stack Kit. People sign in: VanillaSaaS Core.

Choose before you write any code. The kits share their front-end files and router, so moving between them is cheap; moving from a kit to Core means rewriting every page.

Isn't vanilla code hard to maintain as a project grows?

Not if it's structured well. The spaghetti argument usually compares badly written vanilla code with well-architected framework code. ES modules, CSS custom properties and nesting, and routed PHP controllers give you modular, readable code. Frameworks don't remove technical debt; they change its kind, often trading code complexity for dependency complexity.

How do you build complex interfaces without React, Vue or JSX?

With components the browser already ships, and a rule for when that isn't enough. Custom Elements give you reusable components with their own lifecycle; the kits' <bookmark-card> is about 70 lines. Most pages don't need client-side state at all: render HTML on the server, enhance it with fetch() , and the state stays in the database.

When you do need a library, it must be one file you can vendor, need no build step, and be removable in an afternoon. HTMX and Alpine.js pass. The limit: dozens of widgets sharing fast-changing state, as in a spreadsheet or a real-time editor, is where a framework's reactivity earns its cost.

SQLite in production? Isn't it a development database?

For most web apps it's production-ready, and the limits are specific. In WAL mode, reads run alongside a write, and queries read a local file instead of crossing a network. The cost: one writer at a time. Writes queue behind a busy timeout. A blog, a booking system or a dashboard sits well inside that; a chat app with thousands of people posting at once doesn't.

The second limit is one server. Several app servers behind a load balancer means a different database or a replication layer. If you need replication on day one, you probably need Postgres.

Won't developers used to frameworks find this boring?

Boring is the point, and it isn't the same as slow. The hours a framework project spends on upgrades, build configuration and audit warnings go into features instead. The honest cost: you write some things a framework would have generated, such as a router and form validation. The kits ship both already written, each under 100 lines, so you start with them rather than from nothing.

Is VanillaFirst against frameworks?

No. It's a default, not a dogma. Reach for the platform first. If a project genuinely needs a client-side framework or a distributed database, use one, on purpose. The goal is to stop defaulting to abstractions when the browser and the server already do the job.

Pick a kit

All three build the same bookmark list, so you can compare exactly what each layer adds. Each is a template repository: click "Use this template" on GitHub, or clone it.

Frontend Kit

HTML, CSS and JavaScript. Nothing saved on a server.

For: a portfolio, a static site, a front-end exercise, a page that reads someone else's API.

Needs: any local web server. Double-clicking index.html won't load the modules.

git clone https://github.com/vanillafirstdev/frontend.git my-site
cd my-site
python -m http.server 8000

Backend Kit

A JSON API in PHP and SQLite. No pages.

For: an API behind a separate front end, a mobile app or another service.

Needs: PHP 8.1+ with pdo_sqlite . Send requests from the included requests.http or curl.

git clone https://github.com/vanillafirstdev/backend.git my-api
cd my-api
php -S localhost:8000 -t public

Full-Stack Kit

Pages, forms and a JSON API, in PHP and SQLite.

For: a content site with a contact form, docs, a calculator, an internal tool. Nobody signs in.

Needs: PHP 8.1+ with pdo_sqlite , which most PHP installs, XAMPP and shared hosts already have.

git clone https://github.com/vanillafirstdev/fullstack.git my-app
cd my-app
php -S localhost:8000 -t public

People sign in? Don't bolt a login onto a kit. Start from VanillaSaaS Core : hashed passwords, expiring reset tokens, sign-in rate limiting and session timeouts, already written and free under the MIT licence.