The Decision
When we started building the AIUNITES network, the obvious technical choice would have been to pick a popular JavaScript framework and build a monorepo around it. React has excellent component reuse patterns. Next.js handles routing and server-side rendering. There are mature toolchains for everything you might want to build.
We went the other way. Vanilla JavaScript. Plain HTML. CSS with custom properties. SQLite databases. GitHub Pages for hosting.
The reason was not ideology or nostalgia for an earlier era of web development. It was a practical assessment of what we were actually building and what constraints we were working under.
We needed each site to be independently deployable without a build step. We needed the entire network to be hostable on GitHub Pages without any server-side runtime. We needed developers to be able to clone any individual site and understand it within minutes, without knowledge of a framework or a build pipeline. And we needed 18 different sites — with genuinely different purposes, different data models, different UI patterns — to share a consistent enough design language that they felt like a coherent network rather than 18 unrelated products.
Vanilla JavaScript with shared CSS variables and a template-based architecture satisfied all of those constraints. A framework would have satisfied some of them but introduced new ones.
The Architecture: Middleware as a Design Philosophy
AIUNITES is named for the idea of unity — the middleware layers that connect things that weren't originally designed to connect. That philosophy shaped the technical architecture from the start.
Rather than building a single large application, we built five shared middleware layers that any site in the network can implement:
Cross-site authentication is a shared SQLite user table with a consistent session pattern. Any site that implements the authentication module gets login, signup, demo mode, admin roles, and a user dropdown with settings, backup, and cache management — without writing any of that code from scratch.
CloudDB sync is a local-first data layer with optional sync to the cloud via Google Forms and Apps Script. Data lives in the user's browser by default. The cloud is a backup and sync mechanism, not the primary storage. This means the apps work offline, user data is portable, and there is no server to pay for or maintain.
The webring is a navigation bar that appears at the top of every page across all 18 sites, linking them together and giving users a way to move between applications while maintaining context. It is a twelve-line CSS block and a twenty-line JavaScript snippet — no framework needed.
MNN and VRN — the notation systems — are the data layer for movement and voice content. Open plain-text formats that any application can read and write without a shared library or API call.
DemoTemplate is the base template that new sites start from. It ships with authentication, admin panel, user modals, dark theme, responsive design, and webring integration already in place. A new AIUNITES site goes from zero to a fully functional application skeleton in the time it takes to clone a repository.
What Vanilla JavaScript Actually Means at Scale
The phrase "vanilla JavaScript" can suggest something small and simple — a few scripts on a modest page. That is not what we mean. The AIUNITES sites include complex authentication flows, modal systems, admin panels with multiple tabs, real-time data visualization, audio players with crossfade, avatar animation engines, and quiz systems with AI-generated content.
Writing these features in vanilla JavaScript requires discipline that frameworks often provide automatically. Without a component system, you need explicit conventions for organizing code. Without a state management library, you need clear patterns for where data lives and how it moves through the application. Without a build step, you need to write code that works directly in the browser without transpilation.
The conventions we settled on:
These patterns are not sophisticated by framework standards. They don't need to be. The goal is clarity and consistency, not architectural elegance for its own sake.
The Template Tiers
One of the most useful things we built was a tiered template system. Not every AIUNITES site needs the same level of complexity. A landing page site and a full application have different requirements. Forcing both into the same template creates either unnecessary complexity in the simple case or missing functionality in the complex case.
We defined three template tiers:
Cache Core is the minimal tier — CloudDB sync, webring, consistent styling. Appropriate for content sites and landing pages that don't need user accounts.
Modal Admin Core adds the full authentication system and a modal-based admin panel. This is appropriate for applications with user data and a moderate number of admin functions. The admin panel opens as a modal overlay rather than a separate page.
Page Admin Core extends to a dedicated admin page with a sidebar navigation for applications complex enough to need a substantial admin interface. The admin page has its own routing, multiple sections, and a changelog.
This tiering means that a developer building a new AIUNITES site doesn't start from scratch and doesn't over-engineer. They pick the tier that matches their use case and build from there.
Local-First as a Principle
The decision to build CloudDB as a local-first system — with the browser as the primary store and the cloud as a sync mechanism — was one of the most important architectural choices we made, and one of the most unusual.
Most web applications treat the server as the source of truth and the browser as a thin display layer. Data lives in the database, the API fetches it, the frontend renders it. This model is familiar, well-supported, and easy to reason about in simple cases.
It breaks down when you try to run 18 different applications without paying for 18 different server instances. GitHub Pages is static hosting — there is no server, no database, no API. Everything has to run client-side.
The local-first constraint turned out to have unexpected benefits beyond cost. Applications that store data in localStorage work instantly — no network latency on reads, no loading states for basic data operations. They work offline without any special service worker configuration. User data is inherently portable — the user can export their data as JSON from the backup modal and import it anywhere, without any server-side export operation.
Lesson: Constraints Produce Clarity
The GitHub Pages constraint forced a local-first architecture we might not have chosen otherwise. That architecture turned out to have genuine advantages for the use cases we were building for. Constraints that seem limiting often produce better design than unconstrained choice.
The Shared Database Problem
SQLite is the database engine for all AIUNITES sites. This is a somewhat unusual choice for web applications — SQLite is typically associated with mobile apps or desktop software, not web applications. But for our use case, it is the right tool.
SQLite is embedded, requiring no server process. It stores to a single file, making backup and portability trivial. It supports the full SQL feature set — joins, transactions, views, triggers — without any of the operational complexity of a server-based database.
The shared aspect comes from the database schema, not from a shared database file. All AIUNITES sites use a compatible schema for user data, sessions, and core application tables. This means that the authentication module can be deployed identically across all sites, and the backup and restore system works consistently regardless of which site the user is on.
Actual data storage is per-site — each site has its own SQLite file. The "shared" part is the design contract: compatible schemas and a consistent API for interacting with user data.
Consistency Across 18 Sites
Maintaining a consistent look and feel across 18 independently developed sites, without a component library enforcing it, required explicit conventions and discipline.
The CSS variable system is the main tool here. Every site imports the same base stylesheet, which defines the full set of design tokens — colors, spacing scale, typography, border radii, shadow values. Site-specific styles extend these variables rather than overriding them. A dark purple theme in one site and a dark teal theme in another can coexist because they both use the same variable names — `--primary`, `--primary-light`, `--accent` — just with different values.
Navigation is standardized at the component level. The webring bar, the top nav with hamburger menu, the footer — these are all identical HTML structures across sites, differing only in which links are highlighted as current. A designer who learns the nav pattern in one site immediately understands the nav in all of them.
The UATEST_PLAN.md system provides quality consistency. Every site has a test plan document that lists all implemented features and expected behaviors. Before and after any significant change to a site, the test plan is checked to ensure nothing has been accidentally broken. This is low-tech — it's a markdown file, not an automated test suite — but it is consistently applied and catches regressions.
What We Would Do Differently
The local-first architecture works well for the current network, but it has scaling limits. Authentication systems built on localStorage are not appropriate for applications handling sensitive data or requiring strong security guarantees. As the network grows and some sites accumulate real user data, migrating from localStorage-based auth to a proper database-backed authentication system will be necessary.
The current plan is to build a shared authentication service that the AIUNITES sites can call via a consistent API, replacing the local-first auth pattern while keeping the local-first data model for application-specific data. This preserves the offline capability and portability that local-first provides for content data, while bringing authentication to an appropriate security level.
We would also invest earlier in automated testing. The UATEST_PLAN.md system is useful but manual. As the network has grown to 18 sites, the time required to manually verify all test plans after a shared component change has become a meaningful bottleneck. Automated end-to-end tests for the core authentication and data flows would significantly reduce the risk of regressions going undetected.
The Bottom Line
Building 18 connected web applications without a framework has been entirely feasible, and in several respects preferable to what a framework-based approach would have produced. The constraint of no-build, static hosting forced design decisions that turned out to have genuine benefits. The discipline required to maintain consistency without automated enforcement has produced a network that is more legible and more maintainable than it might otherwise be.
The approach is not universally applicable. Applications with complex real-time requirements, large teams, or frequent UI iteration would benefit from the component model and tooling that frameworks provide. But for a network of independently deployed, primarily content-and-data applications with a small development team, vanilla JavaScript with shared CSS variables and a carefully designed template system has been the right choice.
The proof is in the network: 18 sites, consistently designed, independently deployable, running in production on free hosting, with zero framework dependencies and zero build steps required.
See the Network
Every site in the AIUNITES webring is live and running on the architecture described in this article. Browse the network, explore the specs, or get in touch about a project.
Explore the Network → Work With Us →