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

roxul

v1.1.28

Published

Lightweight static site generator.

Readme

Roxul

roxul is a lightweight static site generator.
Tired of rewriting vanilla HTML, CSS, or JS every time you dynamically insert content — only to deal with flickering?
This is the solution.

Components are resolved at build time — the output is plain HTML with zero JavaScript overhead and no flickering.


Install

npm install -g roxul
# or
pnpm add -g roxul
# or use directly with npx
npx roxul build

CLI Usage

roxul <command> [options]

Commands

| Command | Description | |---------|-------------| | roxul build | Build the project (default command) | | roxul serve | Start dev server with live reload | | roxul dev | Alias for serve | | roxul init [dir] | Scaffold a new roxul project |

Options

| Option | Description | |--------|-------------| | --input <dir> | Input directory (default: src or from config) | | --output <dir> | Output directory (default: output or from config) | | --port <port> | Port for dev server (default: 3000) | | --host <host> | Host for dev server (default: localhost) | | --no-clean | Don't clean output directory before build | | --force | Overwrite existing files on init | | -h, --help | Show help | | -v, --version | Show version |

Examples

# Build the project
roxul build

# Start dev server on port 8080
roxul serve --port 8080

# Scaffold a new project
roxul init my-project

# Custom directories
roxul build --input src --output dist

Project Structure

my-project/
├── components/        ← Your reusable HTML components
│   └── example/
│       └── hello.html
├── src/               ← Your source pages and assets
│   ├── index.html
│   ├── main.js
│   └── main.css
├── output/            ← Build output (generated)
├── config.cfg         ← roxul configuration
└── package.json       ← Your project (add "roxul" as dependency)

How Components Work

Place a <component> tag in your HTML:

<component src="example/hello" />

At build time, roxul resolves the tag and inlines the component content:

<!-- Before (source) -->
<component src="example/hello" />

<!-- After (output) -->
<div class="hello-component">
    <h2>Hello from component!</h2>
</div>

No flickering — the content is already in the HTML when the browser loads it.


Component Attributes (Placeholders)

You can make your components dynamic by inserting %%variable%% or __variable__ placeholders anywhere in their HTML, and then passing values via attributes on the <component> tag.

Example

Component file components/greeting.html:

<div class="greeting">
    <h1>%%title%%</h1>
    <p>%%message%%</p>
</div>

Usage in your page:

<component src="greeting" title="Welcome!" message="This content was injected at build time." />

Output (built):

<div class="greeting">
    <h1>Welcome!</h1>
    <p>This content was injected at build time.</p>
</div>

%%variable%% vs __variable__

Both syntaxes work identically — you can use whichever you prefer:

| Syntax | Example | Best for | |--------|---------|----------| | %%nombre%% | %%title%% | General use in text content, attributes, CSS | | __nombre__ | __func__ | Inside JavaScript attributes like onclick="__func__" — valid JS syntax, no editor errors |

The __name__ syntax is just a valid JavaScript identifier, so editors and linters won't mark it as an error when used inside onclick, onmouseover, or similar event handler attributes:

<!-- ✅ No editor errors with __name__ syntax -->
<button onclick="__handler__">Click me</button>
<div onmouseover="__onHover__(event)">Hover me</div>

<!-- ⚠️ %%name%% works too, but editors may flag %% as invalid JS -->
<button onclick="%%handler%%">Click me</button>

Behavior

  • If a placeholder has a matching attribute (e.g. title="value"), it is replaced with the attribute value.
  • If no matching attribute exists, the placeholder is left unchanged in the output.
  • Placeholders work with any attribute except src, which is reserved for component resolution.
  • Attribute names map directly to placeholder names: alt-text="Logo"%%alt-text%% or __alt-text__.

Component Internal Files (CIF) — <script> and <css> Tags

Components can optionally include JavaScript and CSS directly inside their HTML file using <script> and <css> tags. At build time, roxul extracts these blocks, saves them as separate files in the output/cif/ folder, and automatically injects them into the <head> of any page that uses the component.

How It Works

  1. Write your component with optional <script> and <css> blocks:
<!-- components/card.html -->
<div class="card">
    <h2>%%title%%</h2>
    <p>%%content%%</p>
</div>

<css>
.card {
    border: 1px solid #ddd;
    border-radius: 8px;
    padding: 16px;
    max-width: 300px;
    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
</css>

<script>
document.querySelectorAll('.card').forEach(card => {
    card.addEventListener('click', () => {
        console.log('Card clicked:', card.querySelector('h2').textContent);
    });
});
</script>
  1. Use the component in your page as usual:
<component src="card" title="Hello" content="World!" />
  1. At build time, roxul:
    • Extracts the <js> content → saves to output/cif/card.js
    • Extracts the <css> content → saves to output/cif/card.css
    • Removes the <js> and <css> tags from the component HTML
    • Injects <link rel="stylesheet" href="cif/card.css"> and <script src="cif/card.js"></script> into the page's <head>

The /cif Folder (Component Internal Files)

The output/cif/ directory is created automatically during build and contains:

  • componentName.css — Extracted styles from <css> tags
  • componentName.js — Extracted scripts from <js> tags

These files are internal to roxul's build process — you don't need to reference them manually. They are automatically linked in the HTML output.

Key Features

| Feature | Description | |---------|-------------| | Optional | Components can be pure HTML — <js> and <css> tags are completely optional | | Auto-injection | CSS is injected as <link rel="stylesheet">, JS as <script src=""> in <head> | | Deduplication | If a component is used multiple times on a page, its CSS/JS is only injected once | | No flickering | Styles and scripts are in the HTML at load time — no runtime injection | | Scoped by component | Each component gets its own .css and .js file named after the component |

Example Output

Source page:

<component src="card" title="First" content="Hello" />
<component src="card" title="Second" content="World" />

Built output (output/index.html):

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="cif/card.css" data-roxul-component="card">
    <script src="cif/card.js" data-roxul-component="card"></script>
</head>
<body>
    <div class="card"><h2>First</h2><p>Hello</p></div>
    <div class="card"><h2>Second</h2><p>World</p></div>
</body>
</html>

Notice:

  • Only one <link> and one <script> for card despite two usages
  • The data-roxul-component attribute identifies which component the asset belongs to
  • The component HTML has no <js> or <css> tags — they were stripped at build time

Source Paths Reference

| Prefix | Path Resolution | Use Case | |--------|----------------|----------| | src="route/to/comp" | components/route/to/comproxul/BIComponents/route/to/comp | Standard & built-in components | | src="#route/to/comp" | src/route/to/comp | Referencing a page as component | | src="%route/to/comp" | route/to/comp (project root) | Absolute project path |

Built-in components (shipped with roxul) are resolved from the package's roxul/BIComponents/ directory as a final fallback.


Programmatic API

import { build, serve, initProject } from 'roxul';

// Build programmatically
await build({ input: 'src', output: 'dist', root: process.cwd() });

// Start dev server
const { server, close } = await serve({ port: 3000 });

// Scaffold a project
initProject('./my-project');

License

MIT