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

@swissjs/core

v0.1.11

Published

The SwissJS runtime. Component model, reactivity, virtual DOM renderer, context system, security gateway, devtools bridge, and JSX runtime.

Readme

@swissjs/core

The SwissJS runtime. Component model, reactivity, virtual DOM renderer, context system, security gateway, devtools bridge, and JSX runtime.


Exports Overview

import {
  // App mounting
  SwissApp, SwissFramework, mount,

  // Component base
  SwissComponent,            // primary base class for all components
  BaseComponent,             // low-level base (SwissComponent extends this)

  // Reactivity
  Signal,                    // standalone reactive value
  reactive,                  // Proxy-based reactive object
  createEffect,              // run a function reactively
  batch,                     // batch multiple signal writes

  // Hooks
  onMount, onUnmount, onEffect,

  // Context
  SwissContext,

  // Renderer
  renderToDOM, renderToString, hydrate,

  // VNode utilities
  html, css, classNames, escapeHTML, unsafe,

  // Security gateway
  setSecurityGateway, evaluateCapability, audit, auditPlugin,

  // Error boundaries
  ErrorBoundary, createErrorBoundary,

  // Devtools
  getDevtoolsBridge, setDevtoolsBridge,

  // Fenestration (portals)
  // ...

  // JSX
  jsx, jsxs, JSXFragment,
} from '@swissjs/core';

Component Model

SwissComponent

All components ultimately extend SwissComponent (which extends BaseComponent). When writing Swiss syntax, the compiler generates this extension automatically.

import { SwissComponent } from '@swissjs/core';
import type { VNode } from '@swissjs/core';

interface State { count: number }

export class Counter extends SwissComponent<{}, State> {
  override handleMount(): void {
    this.setState({ count: 0 });
  }

  override handleDestroy(): void {
    // cleanup
  }

  increment(): void {
    this.setState(s => ({ count: s.count + 1 }));
  }

  override render(): VNode {
    return html`<button onclick="${() => this.increment()}">${this.state.count}</button>`;
  }
}

Lifecycle methods

| Method | When it runs | |---|---| | handleMount() | After the component is inserted into the DOM | | handleUpdate() | After any state change triggers a re-render | | handleDestroy() | Before the component is removed from the DOM | | captureError(error, phase) | When an error is thrown during any phase |

setState()

Accepts either an updater function or a partial state object. Only changed keys trigger re-renders — unchanged keys are skipped.

this.setState({ count: 5 });
this.setState(s => ({ count: s.count + 1 }));

State is a reactive() Proxy — mutations to nested objects also trigger updates.

Static class fields

| Field | Purpose | |---|---| | static requires: string[] | Capability requirements checked at mount time | | static contextType?: symbol | Context type for automatic injection | | static isErrorBoundary: boolean | Mark component as error boundary | | static propTypes | Prop type metadata (set by compiler from props = {}) |


Reactivity

Signal<T>

Standalone reactive value with automatic effect tracking.

import { Signal } from '@swissjs/core';

const count = new Signal(0);

// Reading inside an effect tracks the dependency
count.value;

// Writing notifies all subscribers
count.value = 5;

// Options
const named = new Signal(0, { name: 'count', equals: Object.is });
const secured = new Signal(0, { capability: 'admin' });

Signal is also what the compiler generates for state { let x: T = v } blocks — the Signal is private to the component, accessed via generated getter/setter.

reactive(obj)

Wraps a plain object in a Proxy that notifies all active effects on any property write. Used internally by BaseComponent for the state object.

import { reactive } from '@swissjs/core';

const state = reactive({ count: 0, name: 'Swiss' });
state.count = 1; // triggers any active effects

createEffect(fn)

Runs fn immediately and re-runs it any time a Signal or reactive property read inside fn changes.

import { createEffect, Signal } from '@swissjs/core';

const count = new Signal(0);
createEffect(() => {
  console.log('count is', count.value);
});
count.value = 1; // logs "count is 1"

batch(fn)

Defers signal notifications until fn completes — prevents multiple re-renders when updating multiple signals.

import { batch } from '@swissjs/core';

batch(() => {
  signalA.value = 1;
  signalB.value = 2;
}); // renders once

Context

import { SwissContext } from '@swissjs/core';

// Define
export interface ThemeCtx { theme: 'light' | 'dark' }
export const ThemeContext = new SwissContext<ThemeCtx>('theme');

// Provide (inside a render method)
return ThemeContext.provide({ theme: 'dark' }, children, this);

// Consume (inside a render method)
const { theme } = ThemeContext.use(this);

Rendering

SwissApp.mount(Component, element)

Entry point for mounting a component tree to the DOM.

import { SwissApp } from '@swissjs/core';
import { App } from './App.ui';

SwissApp.mount(App, document.querySelector('#app')!);

renderToDOM(vnode, element)

Low-level DOM renderer. Used internally by SwissApp.mount.

renderToString(vnode)

SSR: serializes a VNode tree to an HTML string.

hydrate(vnode, element)

SSR: attaches event listeners to server-rendered HTML without re-creating DOM nodes.

html tagged template

Produces a VNode from a template literal. Handles nested VNodes, event bindings, and arrays.

render() {
  return html`
    <div class="card">
      <h1>${this.title}</h1>
      ${this.items.map(item => html`<li>${item.name}</li>`)}
    </div>
  `;
}

Security Gateway

@swissjs/core does not implement security — it holds a gateway slot that @swissjs/security fills at app startup.

import { setSecurityGateway, evaluateCapability } from '@swissjs/core';
import { InMemorySecurityEngine } from '@swissjs/security';

setSecurityGateway(new InMemorySecurityEngine());

// Check capability (returns true if no gateway is set)
evaluateCapability('admin', { layer: 'component', componentName: 'Dashboard' });

The @requires('capability') decorator (or static requires = ['capability']) causes evaluateCapability to be called at mount time, blocking the component if the capability is absent.


Error Boundaries

import { ErrorBoundary } from '@swissjs/core';

// As a base class
class MyBoundary extends ErrorBoundary {
  renderError(error: unknown): VNode {
    return html`<div class="error">Something went wrong</div>`;
  }
}

Devtools Bridge

import { setDevtoolsBridge, InMemoryBridge } from '@swissjs/core';

// Enable devtools in development
if (import.meta.env.DEV) {
  setDevtoolsBridge(new InMemoryBridge());
}

The bridge emits component lifecycle events consumed by the SwissJS devtools browser extension.


JSX Runtime

.uix files compile with jsxImportSource: '@swissjs/core'. The JSX runtime exports are at:

  • @swissjs/core/jsx-runtime — production (jsx, jsxs, Fragment)
  • @swissjs/core/jsx-dev-runtime — development