No-Build Blueprint July 4, 2026 · 10 min read

How I Built a 120-Tool AI Studio With Zero Build Step

No Vite. No Next.js. No npm. 120 AI tools, bilingual EN/FR, BYOK by design — deployed by rsync to shared hosting. Here's the methodology.

Glenn Guilloux

AI Systems Architect · Creative Technologist

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:

  1. Install Node.js (and hope your version matches)
  2. Clone the repo (400MB with node_modules)
  3. Run npm install (pray to the dependency gods)
  4. Configure .env (15 environment variables)
  5. Run the dev server (port 3000, or 3001 if something's already there)
  6. Build for production (and hope tree-shaking doesn't break anything)
  7. 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:

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:

  1. Imports the shared runtime
  2. Defines its system prompt and UI schema
  3. 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 shipped120+Chat, research, code, images, video, audio, 3D, wellness, education
Build steps0Edit HTML → save → rsync → live
Monthly infrastructure cost€0Shared IONOS hosting (already paid for), BYOK for AI
Languages2Full bilingual EN/FR with one toggle
Lighthouse Performance90+No JS bundle to parse — just the runtime
Total CSS weight~45KBOne file, responsive, dark mode, animations
Deploy time~3 secondsrsync -avz --delete over SSH
Time to create a new tool~15 minutesCopy 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:

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:

  1. 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.
  2. Add structured data from day one. I added SoftwareApplication schema to all 120 tools after the fact. Should have been in the template from the start.
  3. 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:

It doesn't work when:

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:

One-time purchase. No subscription. You own it forever.

See Blueprint Pricing

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.

glennguilloux.com · glenn@glennguilloux.com