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

reski

v4.0.0

Published

Reski is a declarative UI definition format that uses a structured, hierarchical syntax to describe component-based user interfaces.

Readme

Reski

Installation

npm install reski

Why Reski?

Reski reimagines component-based UI development with a compact, intuitive syntax that both developers and content creators can master. It brings the structured power of programming to markup while remaining human-readable:

  • 🚀 Minimal & Intuitive - A clean, concise syntax that's easier to read and write than JSX or HTML
  • 🔄 Database-Friendly - Store entire UI components and layouts directly in databases as strings
  • 🧩 Content Creator Empowerment - Enable non-developers to build interactive components without coding knowledge
  • 📦 Framework Independence - Works seamlessly with React, Vue, vanilla JS, or any modern framework
  • 🔌 Dynamic Data Integration - Built-in expressions, transformations, and filtering capabilities
  • 🎯 Reusable Templates - Define component patterns once, use them anywhere in your codebase
  • 🔁 Powerful Iteration - Elegant syntax for rendering collections with advanced mapping

Reski isn't just another template language—it's a bridge between developers and content creators, enabling true collaboration on interactive UIs without sacrificing power or flexibility.

Please note that Reski is developed by a single individual, therefore it can include bugs and unexpected errors that were not tested. Please report in GitHub Issues if you come across any issue.

Reski gets regular updates on dev-side and is updated publicly once in a while.

Usage

import Reski from 'reski';

// Parse a Reski string into a component object
const component = Reski.parse('[Button:primary:["Click me"]]');

// Convert a component object back to Reski string
const reskiString = Reski.reskify(component);

// Evaluate dynamic expressions in a string
const engraved = Reski.engrave('Hello, [(user.name)]!', { user: { name: 'World' } });
// Result: 'Hello, World!'

Integration

React Integration

Reski provides a React context provider for easy integration with React applications:

import { ReskiProvider, useReski } from 'reski/adapters/react';

// Wrap your app with the provider
function App() {
  return (
    <ReskiProvider>
      <YourComponents />
    </ReskiProvider>
  );
}

// Use Reski in your components
function YourComponent() {
  const { Render, parse, reskify } = useReski();
  
  return (
    <div>
      {/* Render a Reski string */}
      <Render 
        string="[Card::[Header::['Title']].[Body::['Content']]]" 
        data={{ /* your data */ }}
        parseOptions={{ /* options */ }}
      />
    </div>
  );
}

The React adapter automatically:

  • Loads components from your project's components directory
  • Handles styling with Twind (Tailwind in JS)
  • Provides convenient parsing and rendering utilities

Examples

Basic Component

// Reski Notation
const buttonString = '[Button:primary.large:["Click me"]]';

// Parsed Result
const button = Reski.parse(buttonString);
/* 
{
  name: "Button",
  classes: ["primary", "large"],
  children: [{ name: "text", content: "Click me" }]
}
*/

Nested Components

// Reski Notation
const cardString = '[Card::[Header::["Title"]].[Body::["Content"]].[Footer::[Button:primary:["OK"]]]]';

// Parsed Result
const card = Reski.parse(cardString);
/*
{
  name: "Card",
  children: [
    {
      name: "Header",
      children: [{ name: "text", content: "Title" }]
    },
    {
      name: "Body",
      children: [{ name: "text", content: "Content" }]
    },
    {
      name: "Footer",
      children: [
        {
          name: "Button",
          classes: ["primary"],
          children: [{ name: "text", content: "OK" }]
        }
      ]
    }
  ]
}
*/

With Properties and Dynamic Content

// Reski Notation
const formString = '[Form::[Input:required::{"type":"text","placeholder":"Enter your name"}].[Button::["Submit"]]:{"onSubmit":"handleSubmit()"}]';

// Parse with data
const form = Reski.parse(formString);
/*
{
  name: "Form",
  children: [
    {
      name: "Input",
      classes: ["required"],
      props: { type: "text", placeholder: "Enter your name" }
    },
    {
      name: "Button",
      children: [{ name: "text", content: "Submit" }]
    }
  ],
  props: { onSubmit: "handleSubmit()" }
}
*/

Dynamic Content

// Template with dynamic expressions
const template = '[User::["Hello, "].[(user.name)].["!"]]';

// Data to inject
const data = {
  user: {
    name: "Sarah"
  }
};

// Parse the template with data
const component = Reski.parse(template, data);
// Component will contain processed dynamic expressions

Templates and Parameters

// Define a template
const templateString = '=[Card<title,content>: Card<"string","string">: [Title::[(title)]].[Content::[(content)]]]';

// Create an instance using the template
const instanceString = '[Card<"Welcome","This is a demo">]';

// Parse both
const parsed = Reski.parse(templateString + instanceString);
// The result will use the template with the given parameters

Mapping with Array Data

// Using map to iterate over an array
const listString = '[List::[Item[items]]]';

// Parse with data
const list = Reski.parse(listString, {
  items: [
    { name: "First item" },
    { name: "Second item" },
    { name: "Third item" }
  ]
});

Syntax

Basic Format

[Name:Classes:Children:Props]

Where:

  • Name: Component identifier (required)
  • Classes: CSS classes (dot-separated)
  • Children: Nested components or text (dot-separated)
  • Props: Component properties (JSON)

Each section is separated by colons and is position-sensitive.

Text Content

["Static text"]       // Static text
[(expression)]        // Dynamic text expression (evaluated during parsing)
[@(expression)]       // Dynamic text expression (evaluated during rendering)

Parameters

[Button<"primary","Click me">]   // Parameters as strings
[Card<title,content>]            // Parameters as variables

Mapping with Arrays

[Component[arrayReference]]      // Map over array

Data Blocks

=<key: value>                    // Define data

Template Blocks

=[TemplateName<param1,param2>: definition]   // Define template

API

Reski.parse(string, initialData?, options?)

Parses a Reski string into a component object.

  • string: Reski notation string
  • initialData (optional): Initial data object for variable substitution
  • options (optional): Configuration options
    • restrictOverwrite: Array of data keys that shouldn't be overwritten (default: ["user", "auth", "token"])
    • debug: Enable debug logging (default: false)
    • convertTemplatesToDivs: Convert template components to divs with data-template attribute (default: true)
    • keepParams: Keep params in the output (default: false)

Returns:

{
  data: Object,      // Parsed data blocks
  templates: Object, // Parsed template definitions
  layout: Object     // The component structure
}

Reski.reskify(component, options?)

Converts a component object back to a Reski string.

  • component: Component object
  • options (optional): Configuration options
    • debug: Enable debug logging (default: false)
    • restrictOverwrite: Array of data keys that shouldn't be included (default: ["user", "auth", "token"])

Reski.engrave(expression, data?)

Evaluates a JavaScript expression within a given data context.

  • expression: JavaScript expression as string
  • data: Data object for evaluation context

React Integration

ReskiProvider

React context provider for Reski.

<ReskiProvider>
  {children}
</ReskiProvider>

useReski()

React hook to access Reski functionality.

Returns:

{
  Render: Component,  // Component to render Reski strings
  parse: Function,    // Parse function
  reskify: Function   // Reskify function
}

License

MIT