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

@vydra-js/core

v0.0.1

Published

Core framework for building microfrontends with Web Components using Lit. Provides dependency injection, microfrontend lifecycle management, and base abstractions for Vydra applications.

Readme

@vydra-js/core

Core framework for building microfrontends with Web Components using Lit. Provides dependency injection, microfrontend lifecycle management, and base abstractions for Vydra applications.

Installation

npm install @vydra-js/core

Quick Start

import {
  Injectable,
  Inject,
  createMicrofrontendLifecycle,
  ScopedElementsMixin,
} from '@vydra-js/core';
import { LitElement, html } from 'lit';

// Define an injectable service
@Injectable()
class UserService {
  getUser() {
    return { name: 'John' };
  }
}

// Create a component
class MyComponent extends ScopedElementsMixin(LitElement) {
  private userService = Inject(UserService);

  render() {
    return html`<p>Hello, ${this.userService.getUser().name}</p>`;
  }
}

API

Dependency Injection

@Injectable()

Class decorator that marks a class as injectable. Instances are created lazily on first Inject() call.

@Injectable()
class ConfigService {
  constructor() {}
}

Inject<T>(token:构造函数): T

Injects an instance of the specified injectable class. Creates a singleton on first call.

const configService = Inject(ConfigService);

createMicrofrontendLifecycle(options): MicrofrontendLifecycle

Creates a lifecycle handler for microfrontend mounting/unmounting (similar to single-spa).

import { createMicrofrontendLifecycle } from '@vydra-js/core';

export const lifecycle = createMicrofrontendLifecycle({
  rootTag: 'my-mf-root',
  rootComponent: MyComponent,
  onMount: async ({ mountPoint, rootConfig }, outlet) => {
    mountPoint.appendChild(outlet);
    return () => {
      /* cleanup */
    };
  },
});

Microfrontend Registration

MicrofrontendRegistry

Registry for managing microfrontend applications.

import { createMicrofrontendRegistry } from '@vydra-js/core';

const registry = createMicrofrontendRegistry();

// Register a microfrontend
registry.register('app1', {
  bootstrap: () => import('./bootstrap'),
  mount: (props) => Promise.resolve(),
  unmount: () => Promise.resolve(),
});

Navigation Service

VydraNavigationService

Service for programmatic navigation, integrated with @vydra-js/router.

import { VydraNavigationService } from '@vydra-js/core';

const nav = new VydraNavigationService();
nav.navigate('/about');

Base Classes

VydraOutletBase

Base class for outlet components that render microfrontends.

class MyOutlet extends VydraOutletBase {
  // Provides outlet functionality for rendering routes
}

Concepts

Why Dependency Injection?

The DI system enables:

  • Loose coupling: Services depend on abstractions, not concrete implementations
  • Testability: Easy to mock dependencies in tests
  • Lazy initialization: Instances are created only when needed

Scoped Elements

ScopedElementsMixin provides shadow DOM isolation for components:

  • Styles don't leak
  • Element names can be reused across microfrontends
  • Full encapsulation

Usage Examples

Basic Component with DI

import { Injectable, Inject, ScopedElementsMixin } from '@vydra-js/core';
import { LitElement, html, css } from 'lit';

@Injectable()
class CounterService {
  count = 0;
  increment() {
    this.count++;
  }
  getCount() {
    return this.count;
  }
}

class CounterComponent extends ScopedElementsMixin(LitElement) {
  static styles = css`
    p {
      font-size: 1.5rem;
    }
  `;

  private counter = Inject(CounterService);

  render() {
    return html`
      <p>Count: ${this.counter.getCount()}</p>
      <button @click=${() => this.counter.increment()}>+</button>
    `;
  }
}

Microfrontend Lifecycle

// my-mf/bootstrap.ts
import { createMicrofrontendLifecycle } from '@vydra-js/core';
import { MyComponent } from './my-component';

export const lifecycle = createMicrofrontendLifecycle({
  rootTag: 'my-mf-root',
  rootComponent: MyComponent,
  onMount: async ({ mountPoint, rootConfig }, outlet) => {
    const component = document.createElement(MyComponent.is);
    mountPoint.appendChild(outlet);

    // Initialize your router here

    return () => {
      component.remove();
    };
  },
});

Best Practices

  1. Use @Injectable() for shared services

    • Don't instantiate services directly with new
    • Let DI manage lifecycle
  2. Prefer composition over inheritance

    • Use mixins like ScopedElementsMixin for common behavior
  3. Keep components focused

    • Single responsibility
    • Delegate business logic to services
  4. Use lifecycle properly

    • Clean up resources in unmount
    • Handle async initialization

Type Definitions

interface MicrofrontendConfig {
  mountPoint: HTMLElement;
  rootConfig?: Record<string, unknown>;
  basePath?: string;
}

interface MicrofrontendLifecycle {
  bootstrap: () => Promise<void>;
  mount: (props: MicrofrontendConfig) => Promise<() => void>;
  unmount: () => Promise<void>;
}

See Also