npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@awacloud/fw

v0.1.0

Published

Zero-dependency browser framework: a DI module runtime with 200+ ESM modules — codecs, compression, crypto (WebCrypto + WASM tiers, post-quantum), DOM rendering and query, workers, security lockdown — usable without a bundler via import maps.

Readme

@awacloud/fw

JavaScript browser framework — full stack control, security by default, zero npm dependencies.

@awacloud/fw is a standalone framework for websites and web applications of moderate complexity. It takes the opposite stance from the modern toolchain (mandatory bundler, opaque dependency tree, supply chain to audit) by providing 202 autonomous modules (src/core/modules.js registry, measured) organised around an explicit resolution runtime and a global-lockdown layer that runs before any other code.

For complex multi-screen applications, fw serves as the foundation for the sd-common layer (app patterns) and sde/sdc (multi-app / mono-app runtimes).

Why @awacloud/fw

| Concern | fw's answer | |---|---| | Supply chain | Zero external dependencies. Everything is read, audited, and written in this repo. | | JS attack surface | sanity/base.js blocks eval, Function, Reflect, Math.random, crypto.randomUUID, performance.now, history.pushState/replaceState; redirects innerHTML → innerText; freezes native prototypes. Loaded before any other script. The sanity/lockdown tier adds SES-grade transitive freezing of the intrinsic graph. | | Mandatory bundler | None. Import-map in dev; in prod, sanity.min.js (classic, loaded first) plus one or more ESM fw.<preset>.min.js bundles per the chosen preset. | | Blind tree-shaking | Strict factory pattern: each module declares its dependencies. The runtime resolves on demand. No module is loaded until requested. | | Workers as second-class citizens | Serializable factories (.toString() → string sendable to the worker). Every module flagged worker-safe instantiates identically in a worker. | | Browser cryptography | Own implementations of SHA-2/3, AES modes, ChaCha20-Poly1305, RSA, Ed25519/X25519, ML-KEM, ML-DSA, SLH-DSA, plus a WebCrypto tier and a WASM tier. Early release: the tier is validated against the NIST ACVP / RFC vectors listed in src/crypto/NIST_CONFORMANCE.md and is scheduled for a full rework against the service-acvp harness in the next program; treat it as pre-audit software. | | DOM clobbering, XSS | parser → render → template → uiSession pipeline with explicit sanitisation, URL attribute allowlist, CSP-nonce, silent redirection of dangerous sinks. |

Use cases

Static website

Global locking, DOM helpers, hash-based routing, i18n, forms, accessibility, animations. No bundler.

Paths below assume node_modules/ is reachable from the HTTP docroot (the default after npm install); adjust the prefix to wherever you serve node_modules/@awacloud/fw/ from.

<!doctype html>
<script src="/node_modules/@awacloud/fw/dist/build/sanity.min.js"></script>       <!-- lock before any JS -->
<script type="importmap">
{ "imports": { "@awacloud/fw": "/node_modules/@awacloud/fw/src/main.js" }}
</script>
<script type="module">
    import fw from '@awacloud/fw';
    import modules from '@awacloud/fw/core/modules.js';
    const { runtime, domReady } = fw;
    runtime.registerAll(modules);

    const route = runtime.resolve('route');
    const i18n = runtime.resolve('i18n');

    route.on('home', '/', () => render('home'));
    route.on('contact', '/contact', () => render('contact'));

    domReady.loaded(() => route.start());
</script>

Web application (SPA / multi-view)

Declarative rendering pipeline, reactive state (signal), event bus, virtual lists, scoped UI sessions, SSR hydration.

import fw from '@awacloud/fw';
import modules from '@awacloud/fw/core/modules.js';
const { runtime } = fw;
runtime.registerAll(modules);

const tpl = runtime.resolve('template');
const uiSession = runtime.resolve('uiSession');   // factory: (containerName) => UISession
const signal = runtime.resolve('signal');
const ajax = runtime.resolve('ajax');             // factory: (baseUrl?, defaults?) => AjaxInstance
tpl.init('todos', { to: '#app' });
const ui = uiSession('todos');
const items = signal.create([]);

ui.add([{ id: 'list', block: ui.parse('<ul>${items}</ul>'), data: {} }]);
const rows = ui.list('list', 'items', { keyFn: i => i.id, block: ui.parse('<li>#{title}</li>') });
items.subscribe(data => rows.sync(data));
items.set(await ajax(location.origin).get('/api/todos', { type: 'json' }));

Offline app / PWA

Service worker, IndexedDB, BroadcastChannel, Cache API, push notifications, background sync, multi-tab leader election.

const sw = runtime.resolve('serviceWorker');
const idb = runtime.resolve('indexedDB');
const leader = runtime.resolve('leaderElection');

await sw.register('/sw.js');
const db = await idb.open('app', 1, (d) => { d.createObjectStore('inbox', { keyPath: 'id' }); d.createObjectStore('outbox', { keyPath: 'id' }); });
leader.create({ channel: 'sync-leader' }).onLeader(() => syncOutbox(db));

High-requirement app (crypto / workers)

E2EE, signatures, hashing, post-quantum, parallel workers with RPC.

const ed = runtime.resolve('ed25519');
const aead = runtime.resolve('chacha20poly1305');
const worker = fw.createWorker(
    function ({ libs, args }) {
        const sig = libs.ed25519.sign(args[0], args[1]);
        self.postMessage(sig);
    },
    { dependencies: ['ed25519'], args: [secretKey, message] }   // ed25519.sign(privateKey, message)
);

Architecture

sanity/         global and prototype lockdown (loaded FIRST)
  base.js       blocks eval/Function/Reflect/random; freezes prototypes
  community.js  framework-friendly degraded layer (optional)
  lockdown.js   SES-grade integrity tier (composes base.js); lockdown-apply.js self-applies it; wasm-gate.js gates WebAssembly

core/           runtime, logger, readyState, worker-helper, modules (barrel)
process/        message, rpc, workerPool — inter-context communication

io/             DOM-free primitives
  binary, calc, codec, compress, i18n, math,
  structures, sync, text, time, timing, utils

crypto/         FIPS / RFC primitives, post-quantum ML-*, SLH-DSA
  cipher, hash, mode, pkc, utils, webcrypto, wasm

dom/            everything touching the DOM
  display, fs, lifecycle, net, query,
  rendering, sensors, sw, utils

Each module follows the strict factory pattern:

export const myModule = {
    name: 'myModule',
    version: '1.0.0',
    type: 'fw.io.utils',
    dependencies: ['hex', 'utf8'],
    factory({ hex, utf8 }) {
        return {
            encode: (s) => hex.fromBytes(utf8.toBytes(s)),
        };
    },
};

The factory is called once by the runtime, after dependency resolution. The body of factory must be self-contained (no references to module-scope bindings) to remain serializable to a Worker.

Installation

npm install @awacloud/fw

Statically served HTML

<script src="/node_modules/@awacloud/fw/dist/build/sanity.min.js"></script>
<script type="importmap">
{ "imports": {
    "@awacloud/fw":  "/node_modules/@awacloud/fw/src/main.js",
    "@awacloud/fw/": "/node_modules/@awacloud/fw/src/"
}}
</script>
<script type="module">
    import fw from '@awacloud/fw';
    // ...
</script>

Production build

The sanity.min.js bundle is always isolated and loaded as a classic script to guarantee the lockdown runs before any other code, without depending on the defer of modules or the import map. The rest of the framework is served via one (or more) ESM bundle built according to the chosen preset.

Build presets

Six cascading prebuilt presets (minimal ⊂ core ⊂ site ⊂ site-interactive ⊂ spa ⊂ pwa), defined in fw.config.json (package root). Each preset can be emitted in two variants:

  • pure (default) — ESM-only, no side effects (<script type="module">, strict CSP, audit, embed).
  • classic — automatically attaches fw to globalThis.fw (useful for non-module <script>).

See docs/tools/bundler.md for the full list, CLI flags, and the procedure for adding a preset.

| Preset | Description | | ------------------- | ---------------------------------------------------------------------------------------------------------- | | minimal | Core runtime only (0 fw modules). | | core | Shared glue (errors, eventBus, signal, valid, ui8, abort, clock). | | site | core + DOM/render/route/a11y/essential codecs/i18n. Static site. | | site-interactive | site + AJAX, components, forms, UI structures, interactions. Dynamic site. | | spa | site-interactive + virtualScroll, chart, IndexedDB, workers, math, binary codecs. Reactive SPA. | | pwa | spa + service worker, cache, push, fsAccess, broadcastChannel, gzip/deflate. Offline app. |

bun run prebuild                       # all (presets + side-bundles + sanity)
bun run prebuild:presets               # all presets
bun run prebuild:side-bundles          # all side-bundles
bun run prebuild:minimal               # targeted build
bun run prebuild:core
bun run prebuild:site
bun run prebuild:site-interactive
bun run prebuild:spa
bun run prebuild:pwa
bun run prebuild:sanity                # sanity.min.js only

Outputs in dist/build/:

  • Presets: fw.<preset>.{min.js,js,meta.json} (classic) and fw.<preset>.pure.{min.js,js,meta.json} (pure).
  • Packs (when minimal is built): fw.pack.<group>.{min.js,js,meta.json} and fw.pack.<group>.pure.{min.js,...} for realtime, crypto-basic, crypto-identity, crypto-advanced, compress-heavy, sensors, text-advanced, structures-advanced.

Typical HTML loading order — classic (simplest):

<script src="/dist/build/sanity.min.js"></script>
<script type="module" src="/dist/build/fw.site.min.js"></script>
<script type="module" src="/dist/build/fw.pack.crypto-basic.min.js"></script>
<script type="module">
    const sha = window.fw.runtime.resolve('sha256');
</script>

pure variant (no global pollution, the user reassembles the pieces):

<script src="/dist/build/sanity.min.js"></script>
<script type="module">
    import fw from '/dist/build/fw.site.pure.min.js';
    import cryptoModules from '/dist/build/fw.pack.crypto-basic.pure.min.js';
    fw.runtime.registerAll(cryptoModules);
    const sha = fw.runtime.resolve('sha256');
</script>

Companion tools

Three helpers shipped with the package for specific use cases:

  • fw-bundler standalone (tools/fw-bundler) — Generates a self-contained ESM file for any fw module (e.g. aes_modes without the framework). bun run build:standalone <moduleName>. Details: docs/tools/standalone.md.
  • tools/rendering/precompilation/ — Pre-compiles HTML templates into ParseResult JSON, importable directly at runtime (zero parsing cost at first-paint). bun run build:parseresult <input>. Details: docs/tools/precompilation.md.
  • tools/rendering/aot/ — AOT-compiles HTML templates into imperative JS factory functions (direct DOM, no parser or renderer at runtime). bun run build:aot <input>. Details: docs/tools/aot.md.

See docs/tools/ for details on all three tools.

Integrations

Optional bridges to the ecosystem, in a scope separate from the core (integrations/) — @awacloud/fw remains dependency-free; each integration is opt-in.

| Category | Available | |---|---| | Bundlers (virtual modules virtual:@awacloud/fw/preset/*) | Vite, esbuild, Rollup, Bun, Webpack, Turbopack | | Frameworks | Astro (SSR + islands), Next.js (via the Webpack plugin), NestJS (environment-agnostic modules as Nest providers) | | Runtime targets (compat pages, not plugins) | Node.js, Deno | | Tests | Vitest (recommended, run the suite under Node), Jest | | Lint | ESLint (rules encoding framework invariants) | | Docs | TypeDoc (HTML API reference generated from the framework types) | | Node build | backend esbuild / Rollup — produces dist/build/* without bun |

Third-party tools (esbuild, rollup, vitest, …) are not committed dependencies: they are installed on demand (bun run setup:e2e / setup:vitest). See dev runtime for the bun/Node choice.

Security (sanity tiers)

New applications call lockdown() once at startup: in a browser realm it also applies the base DOM/XSS denylist, so lockdown() is a superset of applyBase() — there is no reason to call both.

import { lockdown } from '@awacloud/fw/sanity/lockdown';
lockdown();   // default tier — composes base in a browser realm

sanity/base.js (composed by the default tier, or usable alone on hosts that patch prototypes) runs before any other script and enforces:

| API | Behaviour after lockdown | |---|---| | eval, new Function, Reflect (property access) | throw | | Math.random | throw (force usage of crypto.getRandomValues) | | crypto.randomUUID | throw (force usage of the framework's uuid, which is traceable) | | performance.now | throw (timing vector — use the framework's clock) | | history.pushState, replaceState, go, back, forward | throw (use the framework's route) | | Element.innerHTML, outerHTML, insertAdjacentHTML (setters) | redirect to innerText/outerText/insertAdjacentText (no parse, no XSS) | | Native prototypes (Array.prototype, Object.prototype, …) | Object.freeze |

Consequence: any third-party code attempting these APIs fails loudly, which is both a safety net and an incompatibility detector. The fw modules that need them (e.g. uuid, route, clock, random) go through controlled channels.

See docs/guide/security.md for the full tier spectrum (community / base / lockdown) and docs/guide/worker-confinement.md for the confinement half (Workers, capability grants).

Crypto tier — early release

  • Green today: functional KAT against NIST ACVP / RFC vectors — see src/crypto/NIST_CONFORMANCE.md; the PQC hybrid combiners additionally carry docs/evidence/pqc-hybrid-evidence.md.
  • Not claimed: no constant-time attestation for the pure-JS tier, no third-party audit.
  • Rework: the whole crypto tier is redone against a dedicated ACVP validation harness in the next program.
  • Recommendation: prefer the WebCrypto tier (crypto/webcrypto/) where the browser natively provides the algorithm.

Documentation

Playground

Runnable examples for @awacloud/fw — see playground/README.md (not part of the published npm package; browse it in the source repository). Currently one axis: playground/integrations/ (one example per integration). Serve the package root and open /playground/: npx serve --no-clean-urls ..

The starters/ and usecases/ axes (and the create-fw-app scaffolding CLI, currently parked) are planned to return after the first publication.

Development & tests

@awacloud/fw is self-contained: the public monorepo (this package's directory) can be cloned and developed standalone, under bun (default dev runtime) or Node — tests, KAT and vectors included. The published npm package is lean (code + dist min + types) and does not ship the test suite; develop and audit against the source repository (see publishing.md).

cd packages/front/fw            # or the root of a standalone clone
bun install
bun run test                    # suite under bun (= bun test src/)
bun run setup:vitest && bun run test:vitest   # same suite under Node, without touching the tests

Detailed DX sheets in docs/dev/:

Upper layers

@awacloud/fw is usable standalone. For more complex applications, the mono-repo provides:

  • sd-common — application patterns above fw (auth flows, complex forms, etc.)
  • sde — multi-application runtime (shell + embedded apps)
  • sdc — mono-application runtime

Each layer includes fw; it does not replace it. A site with no application complexity can stop at fw.

Licence

Apache-2.0 — see LICENSE in this package.

Copyright (c) 2026 AwaCloud SAS

Project

  • Website: https://awaforge.eu
  • Source: packages/front/fw
  • Issues: this package's own repository has issues disabled — report at https://github.com/awacloud/awa/issues
  • Security policy and release verification: https://github.com/awacloud/awa/blob/main/SECURITY.md
  • Maintenance policy: https://github.com/awacloud/awa/blob/main/MAINTENANCE.md

A CycloneDX 1.6 and SPDX 2.3 SBOM is generated for each published release. Both SBOM files are attached to the release as assets, and their SHA-256 digests are listed in the release's signed digest manifest.

Developed by AwaCloud.