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

@gomani/dsl

v0.12.0

Published

The .goma authoring DSL: a compile-time template + TypeScript signals, with provable zero-JS-outside-islands and template-level type safety.

Readme

@gomani/dsl

The .goma authoring DSL. A compile-time template for structure, TypeScript signals for logic, and the island boundary as a compiler-owned keyword — so Gomani's core guarantees (zero-JS-by-default, island isolation) are provable, not inferred (thesis §6.8). The compiler lowers into the already-proven island/signals runtime — one runtime, not two — so constrained JSX remains a permanent fallback.

This package ships the complete .goma DSL: the parser + compiler (with the zero-JS proof), template-level type safety, editor tooling (a formatter + a language service + a reference VS Code extension in tooling/gomani-vscode), coexistence (the .goma bundler seam shared by gomani build and gomani dev), and first-class routes (a .goma route is a route module with a co-located loader, and @gomani/bench proves a .goma build ships ≤ the JSX build's client JS).

The .goma file

Frontmatter (a TypeScript logic block, with an optional island directive) delimited by ---, then a template:

---
interface Props { data: { title: string; items: string[] } }
const { data } = props;
---
<main class="sv-container">
  <h1>{data.title}</h1>
  <ul>{#each data.items as item}<li>{item}</li>{/each}</ul>
</main>

An island (interactive) declares itself with the island keyword; it is the only source of client JavaScript:

---
island counter interaction
import { signal } from '@gomani/signals';
const count = signal(0);
---
<button class="sv-btn" onClick={() => count.value++}>Tapped {count} times</button>

A route is a first-class route module: a frontmatter export const loader (or staticPaths) is hoisted to module scope, so it co-locates its server data exactly like a .tsx route — fetched on the server, rendered into the HTML, never a client waterfall:

---
interface Props { data: { items: string[] } }
export const loader = () => ({ items: ['drum', 'cloth'] });
const { data } = props;
---
<ul>{#each data.items as item}<li>{item}</li>{/each}</ul>

What the compiler guarantees

  • compile(source) lowers a .goma to a TypeScript module calling @gomani/core's jsx()/island() — the exact runtime a hand-written constrained-JSX component uses (proven by byte-identical render output). {#if}/{#each} become reactive-region thunks inside an island, static expressions in a route.
  • analyze(source) → the zero-JS proof. A route (no island directive) that contains an on* event handler is rejected — interactivity is dead on a static page. A route that passes ships zero client JavaScript, guaranteed (not inferred). This is the machine-checkable report.
  • check(source) → template-level type safety (a hard requirement). Template expressions are type-checked against the logic block and props: {data.titel} when the field is title fails with a precise diagnostic located in the .goma file, at the template line. Correct usage type-checks.

Editor tooling

  • formatGomani(source) — deterministic, idempotent formatting: the template is reprinted from the AST with consistent indentation (all-inline runs on one line, empty elements self-closed), and the frontmatter is reassembled.
  • createGomaniLanguageService() — the brains an editor/LSP calls: getDiagnostics (type errors + zero-JS violations, located in the .goma), getCompletions and getHover that work inside template expressions (the cursor is mapped through the source map to TypeScript, which answers). It keeps a persistent LanguageService, so it is fast across edits.
  • tooling/gomani-vscode — the reference VS Code extension: the TextMate grammar (embeds TypeScript in the frontmatter and {…}), the language configuration, and a thin LSP server that adapts the service. The intelligence stays framework-side and unit-tested; the editor shell is replaceable.

Coexistence with constrained JSX

.goma and hand-written constrained JSX lower to the same @gomani/core VNodes, so the two surfaces mix in one project — adopt .goma file by file, keep JSX as a real fallback.

  • transformGomani(source, filename) + GOMANI_FILTER — the one place a bundler turns a .goma import into a jsx()/island() module. gomani build (esbuild) and gomani dev (Vite) each wrap it in a ~12-line plugin (gomaniEsbuildPlugin from @gomani/build, gomaniVitePlugin from @gomani/dev), so both paths compile .goma identically. Routes, layouts, islands, and components can be either surface.

  • A .goma using a JSX island just works: import it in the frontmatter and use <Counter/> — a Capitalised tag lowers to the imported identifier.

  • A .tsx using a .goma component needs the ambient module once, so the import type-checks:

    /// <reference types="@gomani/dsl/gomani-env" />

    Then import Card from './Card.goma' resolves as a component. See examples/coexist for an app that exercises every direction and builds within budget.