Skip to content

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

PrincipleDescription
Zero BuildWorks directly in the browser via CDN or ES Modules. Vite is optional for development.
Progressive EnhancementEnhances native HTML/JS without replacing it. Every feature is opt-in.
Secure by DefaultDOM writes are sanitized by default. CSP- and Trusted-Types-compatible.
Predictable & DebuggableNo virtual DOM or hidden magic. State changes map directly to DOM updates.
Modular by ChoiceImport only what you need, or use the full framework bundle with consistent APIs.
Typed & DocumentedTypeScript-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

text
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

ts
// 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.

ts
/**
 * 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 from src/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

ts
const button = $('#submit');
const items = $$('.item');

3.1.2 DOM Manipulation

ts
$('#box').addClass('active').css({ opacity: '0.8' }).attr('data-state', 'ready');

$('#content').text('Hello');
$('#content').html('<b>Bold</b>'); // sanitized by default

3.1.3 Events

ts
$('#save').on('click', (event) => {
  console.log('Saved', event.type);
});

3.1.4 Utilities

ts
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.

ts
/**
 * 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)

ts
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.
  • effect is side-effect only; no state writes unless wrapped in batch.
  • Transport helpers reuse the same signal-based lifecycle conventions (data, error, status, pending) as useAsyncData().

3.2.2 Concurrency Module (@concurrency)

ts
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)

ts
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

ts
import { registerDefaultComponents } from '@bquery/bquery/component';

const tags = registerDefaultComponents({ prefix: 'ui' });
console.log(tags.button); // ui-button

3.3.4 Storybook Helpers

ts
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)

ts
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)

ts
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

ts
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
ts
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

ts
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

ts
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

ts
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

ts
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)

ts
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 Error instances.
  • Errors never expose sensitive HTML content.

5. Tooling & Project Structure

This repo uses Bun, Vite, VitePress, Storybook, and TypeScript.

text
.
├── docs/                 # VitePress site
├── .storybook/          # Storybook config
├── stories/             # Component stories
├── src/                  # TypeScript source
├── tests/                # bun:test suites
├── package.json
└── tsconfig.json

5.1 Scripts

  • bun run dev — VitePress docs
  • bun run build — Build library bundles + types
  • bun run build:docs — Build docs site
  • bun run preview — Preview docs
  • bun run storybook — Storybook dev server
  • bun test — Run tests
  • bun 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

  1. bun install
  2. bun run dev (docs)
  3. bun run storybook (components)
  4. bun test (verify behavior)
  5. bun run check:ai-guidance (release / metadata sync)

6. Testing Strategy

  • Unit tests live in tests/ and run via bun 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

BrowserVersionSupport
Chrome90+✅ Full
Firefox90+✅ Full
Safari15+✅ Full
Edge90+✅ Full

No IE support by design.

Released under the MIT License.