Skip to content
  • TypeScript
  • ESM only
  • zero dependencies
  • MIT

The full-stack framework that speaks jQuery

Signals, Web Components, routing, forms, motion, runtime-agnostic SSR and a dependency-free server — 23 tree-shakeable entry points behind the $() you already know. A bundler is a choice, not a prerequisite.

install

bash
npm install @bquery/bquery
bash
bun add @bquery/bquery
bash
pnpm add @bquery/bquery
html
<script type="module">
  import { $, signal, effect } from 'https://unpkg.com/@bquery/bquery@1/dist/full.es.mjs';
</script>

Node ≥ 24 · Bun ≥ 1.4 · Deno · edge · evergreen browsers — support matrix

three ways in, one API
ts
import { $, effect, signal } from '@bquery/bquery';

const count = signal(0);

// No virtual DOM: the effect writes straight to
// the element it read, and nothing else re-renders.
effect(() => {
  $('#counter').text(`Count: ${count.value}`);
});

$('#counter').on('click', () => {
  count.value++;
});
ts
import { createServer } from '@bquery/bquery/server';

const app = createServer();

app.get('/', async (ctx) => {
  return ctx.renderResponse(`<h1 bq-text="message"></h1>`, {
    message: 'Hello from bQuery SSR',
  });
});

// No framework dependencies. Runs on Node, Bun or Deno.
await app.listen({ port: 3000 });
html
<button id="counter">Count: 0</button>

<script type="module">
  import { $, signal, effect } from 'https://unpkg.com/@bquery/bquery@1/dist/full.es.mjs';

  const count = signal(0);

  effect(() => $('#counter').text(`Count: ${count.value}`));
  $('#counter').on('click', () => count.value++);
</script>
0
runtime dependencies
23
tree-shakeable entry points
0
mandatory build steps
4
server runtimes

A familiar surface over a modern core

bQuery keeps the ergonomics that made $() stick — a typed, chainable wrapper around real DOM nodes — and puts fine-grained reactivity, components, routing and SSR underneath it.

You want…bQuery gives you
A jQuery-style DOM API on reactive primitives$(selector) returns a typed BQueryElement; signals and effects join the same chain — no virtual DOM, no diffing pass.
Zero build for small projectsOne <script type="module"> from a CDN. No Vite, no bundler, no transpiler.
A real framework once the project grows23 tree-shakeable entry points: routing, state, forms, SSR, server, motion, a11y, i18n, devtools, testing, plugins.
One stack for client and server@bquery/bquery/ssr and /server render and serve from the same runtime — Node, Bun, Deno or edge.
Security defaults that don't fight youEvery HTML-writing API sanitizes untrusted input; Trusted Types and CSP-friendly patterns are first-class.
Predictable bundle sizeZero runtime dependencies, sideEffects: false, one entry point per module. /full exists for CDN consumers only.

From a write to the DOM, with nothing in between

A signal write notifies exactly the computeds and effects that read it. Effects write to the elements they touched. There is no component re-render to opt out of.

  1. signal()writable source
  2. computed()derived, cached
  3. effect()re-runs on change
  4. $(el)typed DOM write
ts
import { batch, computed, effect, signal } from '@bquery/bquery/reactive';

const items = signal([{ done: false }, { done: true }]);
const open = computed(() => items.value.filter((item) => !item.done).length);

effect(() => {
  console.log(`${open.value} open`); // runs once now, then on every change
});

batch(() => {
  items.value = [...items.value, { done: false }]; // one notification,
  items.value = [...items.value, { done: false }]; // not two
});

Read the whole model in Reactivity, or the API surface in reactive.

23 entry points. Import exactly what you use.

Every public module is its own sub-path export with its own types, so bundlers drop what you never touch. The root entry is a convenience, not a requirement.

What ships in the box

Batteries included means the boring parts are already solved — sanitization, focus management, locale negotiation, request dedup, worker pools, hydration.

Pick the layer you need today

You do not have to adopt the whole framework at once. Start where your app is, and compose more modules in when you need them.