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

@miurajs/miura

v2.5.12

Published

The main package for the miura framework, bundling all core modules.

Readme

@miurajs/miura

The main package for the miura framework.

This package bundles and exports all the core modules, making it easy to get started with miura.

Included Building Blocks

  • MiuraElement for reactive custom elements
  • html, css, and trustedHTML() template utilities
  • property, state, and computed reactivity
  • structural directives, trusted HTML subtrees, and fine-grained bindings
  • component-scoped async resources with $resource()
  • component-scoped form state with $form()
  • lightweight shared state with $shared()
  • tree-scoped dependency injection with $provide() and $inject()
  • router bridge helpers with $route(), $routeSelect(), and $routeData()
  • route-driven async state with $routeResource()
  • island hydration helpers with $islandProps() and $islandResource()
  • integrated debugger runtime with framework-level dev overlays and component layers
  • signals and shared reactive primitives

Direct reads of signal-backed properties in templates can update at the binding level in both JIT and AOT components. Use transformed expressions when you want normal component rerender semantics; use direct reads for hot text, attribute, property, node, and trusted HTML bindings.

Example

import { MiuraElement, html, component } from '@miurajs/miura';

@component({ tag: 'app-user-card' })
class AppUserCard extends MiuraElement {
  user = this.$resource(() => fetch('/api/user').then((r) => r.json()));

  template() {
    return this.user.view({
      pending: () => html`<p>Loading...</p>`,
      ok: (user) => html`<p>${user.name}</p>`,
      error: (error) => html`<p>${String(error)}</p>`
    });
  }
}

When rendering sanitized HTML, prefer Miura's explicit trusted subtree helper instead of binding .innerHTML:

import { html, trustedHTML } from '@miurajs/miura';

html`
  <article>
    ${trustedHTML(cleanHtml, {
      afterRender: (root) => enhanceArticle(root)
    })}
  </article>
`

trustedHTML() does not sanitize. It marks content that your app has already sanitized or generated itself, and its afterRender hook runs after Miura mounts the subtree.

@component({ tag: 'app-signup-form' })
class AppSignupForm extends MiuraElement {
  form = this.$form({ email: '', acceptedTerms: false });

  template() {
    const email = this.form.field('email');

    return html`
      <form @submit=${this.form.handleSubmit(async (values) => {
        console.log(values);
      })}>
        <input &value=${email} @blur=${email.touch}>
        <input type="checkbox" &checked=${this.form.field('acceptedTerms')}>
        <p>${email.showError ? email.error ?? '' : ''}</p>
      </form>
    `;
  }
}

Async validation is also supported through validateAsync, and is automatically respected by submit() / handleSubmit(). Automatic modes are opt-in through validateAsyncOn: 'blur' | 'change'.

Resources can also participate in shared async caching through key, which gives you cache reuse, in-flight dedupe, and explicit invalidation with helpers like resourceKey(...), invalidateResource(...), and invalidateResourceNamespace(...). They also support staleWhileRevalidate, plus staleTime / cacheTime cache policy control.

Forms also keep submit outcome state through submitError, submitResult, and submitSucceeded, which helps keep success/error UI close to the form primitive instead of in separate component state.

Server-side field validation can also be mapped back into the form with setErrors(). For submit flows, failSubmit() can capture the submit error and field errors together. view() can render submit-state UI declaratively from the form itself. Nested field paths like profile.name and profile.meta.featured are supported too.

For lightweight cross-component state, $shared(key, initial) gives multiple components the same signal instance without requiring a full store setup. Use namespaced keys like blog-editor:theme, sharedKey(...), or createSharedNamespace(...) to avoid collisions.

For parent-to-descendant dependencies, use createContextKey(...) with $provide() and $inject() instead of reaching for shared global keys. Context stays tree-scoped, and the nearest provider wins. When descendants should react to changes, provide a signal or another reactive primitive as the context value.

Route-driven resources now bridge cleanly with router loaders too: $routeResource() can derive route-based cache keys automatically and hydrate from route data before revalidating. $routeData() can also return the full loader data object when you omit the key, and hydrateFromRouteData: true lets a route resource hydrate from that full payload directly. Islands can do the same on the server/client boundary with $islandProps() and $islandResource(), so server payloads can hydrate directly into component state before optional client revalidation.

When you build on MiuraFramework, the debugger can be enabled centrally from static config.debugger during development. Individual components can then refine their own debug presentation with static debug or @debug(...), for example to rename a layer label or opt out of reporting in a noisy internal helper component. The debugger runtime logger is exported here as debugLogger so it stays distinct from the component decorator.

See @miurajs/miura-element for the component API and docs for the broader framework documentation.