TL;DR: Every modern AI tool collection uses a build step. I threw mine away. The result: 120 tools in 120 HTML files, a shared runtime in one JS file, bilingual copy in two JS files, and a deploy pipeline that's literally rsync. The site loads in under 2 seconds, works offline as a PWA, and costs €0/month to host. Here's exactly how it works.
The Problem With Build Steps
Last year I watched a developer spend 45 minutes debugging a Vite config that broke after an update. Their project? A single-page AI chat tool. The config was 200 lines. The actual tool logic was 80.
This is the state of modern web development: the build system is more complex than the product.
Every AI tool platform today — every SaaS dashboard, every open-source template, every "starter kit" — follows the same pattern:
- Install Node.js (and hope your version matches)
- Clone the repo (400MB with
node_modules) - Run
npm install(pray to the dependency gods) - Configure
.env(15 environment variables) - Run the dev server (port 3000, or 3001 if something's already there)
- Build for production (and hope tree-shaking doesn't break anything)
- Deploy (Vercel, Netlify, or a Docker container you now maintain)
That's 7 steps before you write a single line of tool logic. And every step is a failure point.
What if the answer was: edit an HTML file, save it, and it's live?
The No-Build Philosophy
In January 2026, I started building AI tools for my own workflow. A contract analyzer, a research copilot, a writing assistant. Each one needed:
- An API connection to OpenRouter (for model routing)
- A streaming chat interface
- API key management (BYOK — bring your own key)
- Error handling and retry logic
- A consistent UI
The conventional approach: extract a shared React component library, create a monorepo, set up Turborepo, configure TypeScript, add Storybook for component previews...
I did none of that.
Instead, I asked: what's the simplest architecture that works for 120 tools?
The answer was embarrassingly simple:
index.html ← The SPA shell (React 19 via CDN)
main.js ← All React components (1 file, 1035 lines)
byok-runtime.js ← Shared API runtime (keychain, streaming, error handling)
copy.js ← Bilingual content (EN + FR)
styles.css ← All styles (1 file, 1698 lines)
Applications/ ← 120 HTML files, one per tool
That's it. No build step. No bundler. No package.json. No node_modules.
Screenshot: The full file tree
120 HTML files + 5 shared JS files + 1 CSS file = the entire platform
How ES Modules Made This Possible
The trick that makes zero-build work in 2026 is native ES modules with import maps. Browsers now support them natively:
<script type="importmap">
{
"imports": {
"react": "https://esm.sh/react@19",
"react-dom/client": "https://esm.sh/react-dom@19/client",
"htm": "https://esm.sh/htm@3.1.1"
}
}
</script>
<script type="module" src="main.js"></script>
No bundler needed. The browser resolves imports directly from CDN URLs. React 19, htm 3.1.1, GSAP 3.12.7 — all loaded from esm.sh with zero build step.
Each of the 120 tool files is a standalone HTML page that:
- Imports the shared runtime
- Defines its system prompt and UI schema
- Renders itself
Here's what a minimal tool looks like:
<!DOCTYPE html>
<html>
<head>
<script type="importmap">{"imports":{"react":"https://esm.sh/react@19"}}</script>
</head>
<body>
<div id="app"></div>
<script type="module">
import { initTool } from './byok-runtime.js';
initTool({
id: 'my-tool',
title: 'My AI Tool',
systemPrompt: 'You are a helpful assistant...',
fields: [{ label: 'Topic', key: 'topic', type: 'textarea' }]
});
</script>
</body>
</html>
That's a complete, deployable AI tool. No build. No compile. Save and refresh.
The Shared Runtime: One File to Rule Them All
The byok-runtime.js file is the spine of the entire studio. It handles:
Keychain Management
Users enter their OpenRouter API key once. It's stored in localStorage and shared across all 120 tools. One key, every tool.
// From byok-runtime.js
function getKey() {
return localStorage.getItem('openrouter-key') || '';
}
function setKey(key) {
localStorage.setItem('openrouter-key', key);
}
Streaming Chat Completions
Every tool gets streaming output — token by token, in real time. The runtime handles the SSE connection, retry on failure, and graceful degradation.
// Direct browser-to-OpenRouter — your key never touches my server
const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': `Bearer ${getKey()}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ model, messages, stream: true })
});
Token Ledger
The runtime tracks every token spent across every tool. Users see exactly how much they've spent — no surprise bills.
Screenshot: Token Ledger
Cross-tool spending tracker in the sidebar — real-time cost visibility
The Numbers That Matter
This isn't a prototype. It's a production site serving real users. Here are the actual metrics:
| Metric | Value | Notes |
|---|---|---|
| AI tools shipped | 120+ | Chat, research, code, images, video, audio, 3D, wellness, education |
| Build steps | 0 | Edit HTML → save → rsync → live |
| Monthly infrastructure cost | €0 | Shared IONOS hosting (already paid for), BYOK for AI |
| Languages | 2 | Full bilingual EN/FR with one toggle |
| Lighthouse Performance | 90+ | No JS bundle to parse — just the runtime |
| Total CSS weight | ~45KB | One file, responsive, dark mode, animations |
| Deploy time | ~3 seconds | rsync -avz --delete over SSH |
| Time to create a new tool | ~15 minutes | Copy a template, change the prompt, done |
The most important number: 15 minutes to create a new tool. That's from idea to deployed. No scaffolding, no config, no "where does this component go."
What About TypeScript? SSR? SEO?
I hear the objections. Let me address them:
"But TypeScript catches bugs!"
For a 120-tool platform maintained by one person, the overhead of TypeScript compilation isn't worth it. I use JSDoc comments for IDE hints and rely on the runtime's error boundaries for production safety. The tools are thin enough that type errors are rare and obvious.
"But SSR improves performance!"
My site loads in under 2 seconds. The React app is hydrated client-side from CDN-cached modules. For an AI tool platform where every interaction requires a network call to the LLM, the 50ms hydration cost is irrelevant.
"But you need a build step for SEO!"
The main SPA doesn't need SEO — it's an app, not content. The 233+ SEO pages (comparison pages, industry pages, capability pages) are static HTML files generated by a script. No framework needed. Google indexes them perfectly.
"But what about code splitting?"
Each tool is its own HTML file. The browser only loads the runtime when you visit a tool. That's natural code splitting — no webpack magic needed.
The Bilingual System
Every tool, every page, every error message is available in English and French. The entire translation system is two files:
// copy-en.js
export const COPY = {
hero_title: "Your AI-Powered Creative Studio",
hero_subtitle: "120+ tools. Zero build step. Your keys, your data.",
cta_try: "Try It Free",
// ... 200+ keys
};
// copy-fr.js
export const COPY = {
hero_title: "Votre Studio Créatif Alimenté par l'IA",
hero_subtitle: "120+ outils. Zéro étape de build. Vos clés, vos données.",
cta_try: "Essayer Gratuitement",
// ... 200+ keys
};
Switching languages is instant — it's just a localStorage toggle that swaps which copy module is active. No page reload. No server round-trip.
The PWA Layer
The no-build architecture makes PWA support trivial. There's no complex webpack-generated asset manifest to cache. The service worker caches:
- Static assets — CSS, JS, icons (cache-first)
- HTML pages — network-first with offline fallback
- Fonts — stale-while-revalidate
The result: the site is installable, works offline, supports background sync (queue API calls when disconnected), and even has a share target (share text to any tool from your phone's share menu).
Total service worker complexity: ~300 lines. No webpack-plugin-generated manifest needed.
The Deployment Story
When I'm ready to ship, it's one command:
rsync -avz --delete \
--exclude 'node_modules/' \
--exclude '.git/' \
./ \
user@server:/var/www/html/
That's it. No CI/CD pipeline. No Docker containers. No Vercel deployment logs. No "building... 47/234 modules transformed."
Edit → Save → rsync → Live. Three seconds from my terminal to production.
For the PHP backend (the artist portal at glennguilloux.com/morgane), it's the same rsync command. PHP on shared hosting requires zero configuration — it just works.
What I'd Do Differently
No architecture is perfect. Here's what I'd change if I started over:
- Extract the runtime earlier. I built 20 tools before extracting
byok-runtime.js. The first 20 had duplicated API logic. The next 100 were clean. - Add structured data from day one. I added
SoftwareApplicationschema to all 120 tools after the fact. Should have been in the template from the start. - Build the QA harness first. My sitemap parity checker, link checker, and static smoke test would have caught 10+ broken links that shipped undetected.
But the core decision — no build step — I'd make again every time.
Should You Go No-Build?
Not always. The no-build approach works when:
- ✅ You're building a tool platform (many small, independent tools)
- ✅ You want BYOK (client-side API calls, no server proxy)
- ✅ You deploy to shared hosting (no Node.js server needed)
- ✅ You're a solo developer or small team (no need for component libraries)
- ✅ You value speed of iteration over type safety
It doesn't work when:
- ❌ You need server-side rendering for SEO (use Next.js)
- ❌ You have 50+ developers committing daily (use a monorepo)
- ❌ You need complex state management across pages (use Redux/Zustand)
- ❌ Your tools share heavy dependencies (Three.js, TensorFlow)
For my use case — a solo-built AI studio with 120 lightweight tools — the no-build approach saved hundreds of hours of build configuration, dependency management, and deployment complexity.
Get the Blueprint
I've packaged the entire methodology into a product: The No-Build AI Studio Blueprint. It includes:
- The shared runtime (
byok-runtime.js) - 5 production-ready tool templates
- The bilingual copy system
- The PWA setup (service worker, manifest, offline)
- The deploy script
- A written methodology guide
One-time purchase. No subscription. You own it forever.
Starter €149 · Pro €299 · Complete €490
Glenn Guilloux is a creative technologist and AI systems architect based in Brittany, France. He builds AI tools, workflow systems, and digital-physical experiences — all with zero build step.