bQuery.js — Framework Specification v1.11.0
"The full-stack web framework that speaks jQuery."
1. Philosophy & Design Principles
1.1 Mission Statement
bQuery.js is a batteries-included framework for the modern web. It brings jQuery's ergonomic API to reactivity, zero-build concurrency, async data, HTTP clients, polling, pagination, realtime transports, REST helpers, dependency-free backend routing, runtime-agnostic SSR, components, motion, routing, stores, declarative views, forms, i18n, accessibility, media signals, plugins, testing, and WebSocket sessions.
1.2 Core Principles
| Principle | Description |
|---|---|
| Zero Build | Works directly in the browser via CDN or ES Modules. Vite is optional for development. |
| Progressive Enhancement | Enhances native HTML/JS without replacing it. Every feature is opt-in. |
| Secure by Default | DOM writes are sanitized by default. CSP- and Trusted-Types-compatible. |
| Predictable & Debuggable | No virtual DOM or hidden magic. State changes map directly to DOM updates. |
| Modular by Choice | Import only what you need, or use the full framework bundle with consistent APIs. |
| Typed & Documented | TypeScript-first APIs with inline TSDoc for every public surface. |
1.3 Target Audience
- Developers building multi-page applications (MPAs)
- CMS/WordPress themes with interactive blocks
- Prototyping and fast UI experiments
- Legacy projects modernizing incrementally
- Teams avoiding React/Vue overhead
2. Architecture
2.1 Modular Layout
bQuery.js
├── core/ (selectors, DOM ops, events, utils)
├── reactive/ (signals, computed, effects, async data/fetch, HTTP, polling, pagination, realtime)
├── concurrency/ (zero-build worker tasks, RPC helpers, pools, collection pipelines)
├── component/ (custom elements, props, lifecycle, shadow DOM, defaults)
├── storybook/ (template helpers for Storybook web-component stories)
├── motion/ (view transitions, FLIP, springs)
├── security/ (sanitizer, CSP compatibility, Trusted Types)
├── platform/ (storage, cache, cookies, announcers, page meta, config)
├── router/ (SPA routing, guards, current route)
├── store/ (signal-based state management)
├── view/ (declarative DOM bindings)
├── forms/ (reactive forms and validation)
├── i18n/ (translations, pluralization, Intl formatting)
├── a11y/ (focus management, announcements, audits)
├── dnd/ (draggable, droppable, sortable)
├── media/ (reactive browser/device signals)
├── plugin/ (global plugin registration)
├── devtools/ (runtime inspection helpers)
├── testing/ (mounting and assertion helpers)
├── ssr/ (runtime-agnostic server rendering, streaming, hydration, adapters)
└── server/ (dependency-free backend routing, middleware, WebSocket sessions)2.2 Import Strategies
// Full bundle (CDN, zero build)
import { $, signal, component } from 'https://unpkg.com/@bquery/bquery@1/dist/full.es.mjs';
// Core only
import { $ } from '@bquery/bquery/core';
// À la carte
import { $, $$ } from '@bquery/bquery/core';
import { signal, computed } from '@bquery/bquery/reactive';
import { createSSRContext, renderToResponse } from '@bquery/bquery/ssr';
import { createServer } from '@bquery/bquery/server';2.3 OOP Core Contracts
The core is intentionally object-oriented to keep DOM operations predictable, chainable, and discoverable.
/**
* OOP wrapper for a single DOM element.
* - Keeps API chainable
* - Encapsulates read/write operations
*/
class BQueryElement {
/** The underlying native element (read-only). */
readonly node: Element;
/**
* Add a CSS class and return `this` for chaining.
*/
addClass(name: string): this;
/**
* Set HTML with sanitization by default.
*/
html(value: string): this;
}
/**
* Collection wrapper for multiple DOM elements.
*/
class BQueryCollection {
/** Total matched elements. */
readonly length: number;
/** Iterate each matched element. */
each(fn: (el: BQueryElement, index: number) => void): this;
}2.4 DRY Architecture Rules
- Single source of truth for selectors and DOM helpers in
src/core/shared.ts. - Reusable primitives (signals/effects) live in
src/reactive/signal.ts. - Cross-module utilities live in
src/core/utils/as focused helper modules (re-exported fromsrc/core/utils/index.ts). - Module boundaries are strict: no cross-imports that create circular dependencies.
3. API Reference
3.1 Core Module (@core)
3.1.1 Selectors
const button = $('#submit');
const items = $$('.item');3.1.2 DOM Manipulation
$('#box').addClass('active').css({ opacity: '0.8' }).attr('data-state', 'ready');
$('#content').text('Hello');
$('#content').html('<b>Bold</b>'); // sanitized by default3.1.3 Events
$('#save').on('click', (event) => {
console.log('Saved', event.type);
});3.1.4 Utilities
import { merge, uid, utils } from '@bquery/bquery/core';
const id = uid();
const config = merge({ a: 1 }, { b: 2 });
const legacyId = utils.uid();3.1.5 In-Code Documentation (TSDoc)
All public APIs include inline documentation for IDEs and generated docs.
/**
* Create a unique, stable ID scoped to the current session.
* @returns A short, collision-resistant string.
*/
export function uid(): string;3.2 Reactive Module (@reactive)
import {
signal,
computed,
effect,
batch,
useFetch,
createHttp,
useEventSource,
} from '@bquery/bquery/reactive';
const count = signal(0);
const doubled = computed(() => count.value * 2);
effect(() => {
console.log(count.value);
});
batch(() => {
count.value = 1;
count.value = 2;
});
const profile = useFetch('/api/profile');
const api = createHttp({ baseUrl: 'https://api.example.com' });
const events = useEventSource('/api/profile/events');3.2.1 Reactive Contracts
signal<T>exposes mutable state via.value.computed<T>is pure and lazy; no side-effects inside.effectis side-effect only; no state writes unless wrapped inbatch.- Transport helpers reuse the same signal-based lifecycle conventions (
data,error,status,pending) asuseAsyncData().
3.2.2 Concurrency Module (@concurrency)
import { createTaskPool, parallel, pipeline } from '@bquery/bquery/concurrency';
const pool = createTaskPool(({ value }: { value: number }) => value * 2, {
concurrency: 4,
maxQueue: 16,
});
const results = await parallel([
{ handler: (value: number) => value + 1, input: 1 },
{ handler: (value: number) => value + 1, input: 2 },
]);
const transformed = await pipeline([1, 2, 3, 4])
.map((value) => value * 2)
.toArray();The concurrency layer keeps worker-based parallelism explicit: no decorators, no proxy magic, and no hidden build step.
3.3 Component Module (@component)
import { bool, component, html } from '@bquery/bquery/component';
component('user-card', {
props: {
username: { type: String, required: true },
},
render({ props }) {
return html`<button ${bool('disabled', !props.username)}>Hello ${props.username}</button>`;
},
});3.3.1 Component Lifecycle
connected→ runs when the element mounts.disconnected→ runs on teardown.updated→ runs after reactive props/state/signal changes and can receive attribute-change metadata.
3.3.2 Typed State & Signals
Components may declare explicit typed state and a signals map for external reactive inputs. This keeps render(), lifecycle hooks, and getState() / setState() strongly typed while avoiding accidental subscriptions to undeclared reactive reads.
3.3.3 Default Component Library
import { registerDefaultComponents } from '@bquery/bquery/component';
const tags = registerDefaultComponents({ prefix: 'ui' });
console.log(tags.button); // ui-button3.3.4 Storybook Helpers
import { storyHtml, when } from '@bquery/bquery/storybook';
const story = storyHtml`
<ui-card>
<ui-button ?disabled=${false}>Save</ui-button>
${when(true, '<small>Ready</small>')}
</ui-card>
`;storyHtml() preserves custom elements, sanitizes interpolated markup, and supports Storybook-friendly boolean attribute shorthand.
3.4 Motion Module (@motion)
import { transition } from '@bquery/bquery/motion';
await transition(() => {
$('#content').text('Updated');
});
await transition({
update: () => $('#content').text('Configured update'),
classes: ['page-transition'],
types: ['navigation'],
});3.5 Security Module (@security)
import { sanitize, sanitizeHtml, trusted } from '@bquery/bquery/security';
import { safeHtml } from '@bquery/bquery/component';
const safeMarkup = sanitize(userInput);
const trustedBadge = trusted(sanitizeHtml('<strong>Safe</strong>'));
const button = safeHtml`<button>${trustedBadge}</button>`;3.6 Platform Module (@platform)
Unified endpoints for web platform storage and system APIs. The goal is a consistent, promise-based interface with predictable errors.
3.6.1 Storage Adapters
import { storage } from '@bquery/bquery/platform';
// localStorage
const local = storage.local();
await local.set('theme', 'dark');
const theme = await local.get<string>('theme');
// sessionStorage
const session = storage.session();
await session.set('wizardStep', 2);
// IndexedDB (key-value facade)
const db = storage.indexedDB({ name: 'bquery', store: 'kv' });
await db.set('user', { id: 1, name: 'Ada' });
const user = await db.get<{ id: number; name: string }>('user');Adapter Interface
type StorageAdapter = {
get<T>(key: string): Promise<T | null>;
set<T>(key: string, value: T): Promise<void>;
remove(key: string): Promise<void>;
clear(): Promise<void>;
keys(): Promise<string[]>;
};3.6.2 Storage Buckets
import { buckets } from '@bquery/bquery/platform';
const bucket = await buckets.open('assets');
await bucket.put('avatar', new Blob(['...']));
const avatar = await bucket.get('avatar');
await bucket.remove('avatar');3.6.3 Notifications
import { notifications } from '@bquery/bquery/platform';
const permission = await notifications.requestPermission();
if (permission === 'granted') {
notifications.send('Build complete', {
body: 'Your docs are ready.',
});
}3.6.4 Cache Storage
import { cache } from '@bquery/bquery/platform';
const assets = await cache.open('bquery-assets');
await assets.add('/styles.css');
const response = await assets.match('/styles.css');
await assets.remove('/styles.css');3.6.5 Runtime Config, Cookies, and Metadata
import {
defineBqueryConfig,
useCookie,
definePageMeta,
useAnnouncer,
} from '@bquery/bquery/platform';
defineBqueryConfig({
fetch: { baseUrl: 'https://api.example.com' },
components: { prefix: 'ui' },
});
const theme = useCookie('theme', { defaultValue: 'light' });
const cleanup = definePageMeta({ title: 'Dashboard' });
const announcer = useAnnouncer();
announcer.announce('Saved');
cleanup();
theme.value = 'dark';3.7 SSR & Server Modules (@ssr, @server)
import { createSSRContext, renderToResponse } from '@bquery/bquery/ssr';
import { createServer } from '@bquery/bquery/server';
const app = createServer();
app.get('/', (ctx) => {
const ssr = createSSRContext({ request: ctx.request });
return renderToResponse(
'<html><head></head><body><h1 bq-text="title"></h1></body></html>',
{ title: 'Hello 1.11.0' },
{ context: ssr, etag: true }
);
});The SSR pipeline is runtime-agnostic: renderToString(), renderToStringAsync(), renderToStream(), and renderToResponse() all work on Bun, Deno, and Node.js ≥ 24, automatically falling back to a DOM-free renderer when DOMParser is unavailable. The server module layers lightweight routing, middleware, and WebSocket session handling on top of that surface.
4. Implementation Notes
4.1 TypeScript First
- Public APIs are typed.
- Internal modules are organized by capability (
core,reactive,component,motion,security). - OOP wrappers (
BQueryElement,BQueryCollection) keep DOM operations predictable and chainable.
4.2 Documentation in Code
- Use TSDoc on every exported function/class/type.
- Keep examples copy-pasteable and minimal.
- Document default behavior (e.g., sanitization, event delegation).
4.3 DRY Conventions
- No duplicated DOM helpers or selector logic across modules.
- Shared type definitions live in a single module per domain.
- Prefer composition over inheritance for new features.
4.4 Error Handling
- Public APIs return predictable errors with descriptive messages.
- Async platform APIs always reject with
Errorinstances. - Errors never expose sensitive HTML content.
5. Tooling & Project Structure
This repo uses Bun, Vite, VitePress, Storybook, and TypeScript.
.
├── docs/ # VitePress site
├── .storybook/ # Storybook config
├── stories/ # Component stories
├── src/ # TypeScript source
├── tests/ # bun:test suites
├── package.json
└── tsconfig.json5.1 Scripts
bun run dev— VitePress docsbun run build— Build library bundles + typesbun run build:docs— Build docs sitebun run preview— Preview docsbun run storybook— Storybook dev serverbun test— Run testsbun run check:ai-guidance— Verify version / engine / guidance sync
5.2 Tooling Contracts
- Bun is the runtime and test runner. No Node-only globals in source.
- Supported validation floor is Node.js ≥ 24.0.0 and Bun ≥ 1.3.13.
- Vite powers the library builds and Storybook builder.
- VitePress builds the documentation site from
docs/. - Storybook is the primary component preview/development environment.
- TypeScript is required for all public APIs and examples.
5.3 Local Development Flow
bun installbun run dev(docs)bun run storybook(components)bun test(verify behavior)bun run check:ai-guidance(release / metadata sync)
6. Testing Strategy
- Unit tests live in
tests/and run viabun test. - Each module has a dedicated test file (e.g.,
core.test.ts). - Tests must cover happy path and edge cases (empty selections, null inputs, invalid HTML).
- Keep tests isolated and deterministic.
7. Compatibility
| Browser | Version | Support |
|---|---|---|
| Chrome | 90+ | ✅ Full |
| Firefox | 90+ | ✅ Full |
| Safari | 15+ | ✅ Full |
| Edge | 90+ | ✅ Full |
No IE support by design.