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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@qtagon/typhon-ui

v1.8.1

Published

Strongly typed dynamic ui generator

Readme

Typhon UI - Strongly Typed UI Generator

Complex user interfaces via code 🎨

Documentation

Check typedocs here, generated via typedoc.

💥 Motivation

As a developer, have you ever noticed that all projects with user interface elements are repetitive?

Such as user profile, article page, forms, modal, cards, layouts, every damn thing, you name it, it's all repetitive !

All coding become repetitive when you understand you're just writing functions that read, write or display data of some APIs.

💡 Purpose

So, what's Typhon UI all about ?

Well, Typhon UI makes an attempt to ease to workload off your shoulders in defining every user interface.

A good example might be the article page, you've created your shiny new articles pages which displays articles as list of elements, but what would you do if a new requirement comes that articles pages needs to be displayed as a grid of cards with some forms and another layout ?

Not again ! you have to create a different layout, create forms, create cards, so much things for the same jittery stuff !

But here comes your savior (maybe), Typhon UI.

You define your components once, and Typhon UI will make sure to display them dynamically.

You have to implement your JSON renderer of Typhon UI's response in your Front-end application.

🗃️ API

Typhon UI defines UI components, well thank you Sherlock 🧐.

It is composed of ColumnRowsContainerComponent

The final implementation of rendering and components design, and i mean (real) design (visually) is up to you.

CoreColumnRowContainerComponents


🧱 Installation

Typhon UI uses TypeScript, you may install this library in any TypeScript enabled project via npm or yarn.

You can use this library server side with Node.js

npm i @qtagon/typhon-ui or yarn add @qtagon/typhon-ui


🔍️ Usage Example

! Looks scary, at first. ⚗️

This example was handwritten in svelte check full example here

import { Typhon } from '@qtagon/typhon-ui';

/** Declare TyphonUI */
let dynamic = new Typhon('movies-ui')
  .setColumn('content-menu') /** Attach column for menu */
  .setColumn('content'); /** Attach column for page content */

/** Menu */
const cmenu = dynamic
  .onColumn('content-menu')
  .setClassified('flex-auto') /** CSS classes */
  .setRow('content-menu-row') /** Attach row */
  .setContainer('content-menu-container'); /** Attach container to row */

/** Indexing content-menu column and content-menu-row row*/
dynamic.ixColumn('content-menu').ixRow('content-menu-row');

/** Attach menu component to menu contianer */
const menu = cmenu.setMenu();

/** Attach option to menu component, then icon to option, then width and height of icon */
menu.setOption().setIcon('home').setWidth(18).setHeight(18);
menu.setOption().setIcon('calendar').setWidth(18).setHeight(18);
menu.setOption().setIcon('message').setWidth(18).setHeight(18);
menu.setOption().setIcon('user').setWidth(18).setHeight(18);
menu.setOption().setIcon('logout').setWidth(18).setHeight(18);

/** Page Content */
const content = dynamic
  .onColumn('content')
  .setScroll(true) /** Make column scrollable */
  .setStyle('padding: 0.938rem 0.938rem 0.938rem 1.938rem;') /** Raw CSS style */
  .setRow('search') /** Attach row  for search bar */
  .setContainer('search'); /** Attach container to row */

dynamic
  .onColumn('content')
  .setRow('data') /** Attach row for cards */
  .setContainer('data') /** Attach container to row */
  .setClassified('display-grid') /** CSS classes */
  .setStyle(
    `grid-template-columns: repeat(auto-fill, minmax(15.750rem, 1fr)); grid-gap: 1.875rem;`,
  ); /** Raw CSS style */

/** Indexing content column and content-menu-row row*/
dynamic.ixColumn('content').ixRow('search').ixRow('data');

content.setSubject('Search').setClassified('h1'); /** Set container (title) */
content.setSearch('Search movies ...').setEvent('search', {
  type: 'query',
}); /** Attach search component with search event */

/** Attach tabs component with options and events */
const tabs = content.setTabs('Movies');
tabs.setOption('Popular').setEvent('search', { type: 'popular' });
tabs.setOption('Now Playing').setEvent('search', { type: 'now_playing' });
tabs.setOption('Upcoming').setEvent('search', { type: 'upcoming' });
tabs.setOption('Top Rated').setEvent('search', { type: 'top_rated' });

/** Reference to data container which contains cards */
const container_data = dynamic.onContainer('data');

/** Attach cards by external logic , currently fetching movies from themoviedb API */
const setMovieCard = (data, poster = 'https://image.tmdb.org/t/p/w500') => {
  /** Attach card component */
  const card = container_data
    .setCard(data.title, data.overview) /** Set title and description of card */
    .setClassified('background-white round padding-default single-line'); /** CSS classes */

  /** Attach image component to card with title */
  card.setImage(`${poster}${data.poster_path}`).setTitle(`${data.title} Poster`);

  /** Attach button component to card with title, event and icon */
  card
    .setButton('Read More')
    .setEvent('element', data) /** Attach event */
    .setClassified('transparent bordered') /** CSS classes */
    .setIcon('check'); /** Attach icon component */

  dynamic = dynamic; /** Rerender UI, just svelte's way ... */
};

📄 Open source license

If you are creating an open source application under a license compatible with the GNU GPL license v3, you may use typhon-ui under the terms of the GPLv3.

👥 Contributing

Bugs, PR are always appreciated.

Typhon UI is an GPLv3-licensed open source project with its ongoing development made possible thanks to the support by the community, substantial contributors may get a GPLv3 free license.

Flow:

  1. Fork it
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Test your changes to the best of your ability.
  4. Update the documentation to reflect your changes if they add or changes current functionality.
  5. Commit your changes (git commit -am 'Added some feature').
  6. Push to the branch (git push origin my-new-feature)
  7. Create new Pull Request

📝 MIT license

If you are looking for a GPLv3 free license, contact me.