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

lex-press

v3.0.1

Published

Minimalist framework for HTML and JSX with LEX, built as an Express wrapper with automatic routing and server-side props

Readme

Lex-Press

This is my framework for working with HTML or JSX files with LEX. It follows a minimalist philosophy with full user control. It integrates utility functionalities from frameworks like Next.js but integrated into an Express wrapper.

Note: This framework includes body-parser and cookie-parser configured by default to facilitate request and cookie handling.

Installation

Use npm i lex-press or npx create-lex-press-app

The second option simply adds a small initial configuration.

Initialization

To get started, import lex-press with require and then instantiate an app just like you would in Express:

const lexpress = require("lex-press");

const app = lexpress();

Now you'll have access to all Express methods since this framework only extends Express:

const lexpress = require("lex-press");

const app = lexpress();

app.get("/", (req, res) => res.send("Hello world"));

app.listen(3000, () => {
    console.log("Listening on port 3000");
});

Public

It's a utility method for serving public directories. You pass it the folder path and you're done:

app.public("public");

HTML

It's a method that declares a route and an HTML file to be served. In development and build mode, it compiles the HTML before serving it. In production, it expects the build to have already been done:

app.html("/home", "./pages/index.html");

If the HTML includes src or inline scripts, it will be automatically compiled resulting in a single HTML with inline scripts.

This method returns an object with the serverProps method. This is a method that allows us to declare a function (sync or async) for serverProps:

app.html("/home", "./pages/index.html").serverProps((req) =>
{
    return {
        title: "Hello world from server"
    };
});
<!--./pages/index.html-->
<body>
    <h1>__SERVER_PROPS.title__</h1>
</body>

This will replace the placeholder __SERVER_PROPS.title__ with the (return value of the serverProps function).title:

<!--Final result-->
<body>
    <h1>Hello world from server</h1>
</body>

This is useful for preprocessed content. Obviously, it should be used carefully to not send sensitive information to the client.

The text will be automatically escaped, so HTML cannot be injected, only plain text.

The function receives req in case you want to use it.

JSX

Similar to app.html but receives route, page, and layout:

app.jsx("/home", "./pages/layout.jsx", "./pages/page.jsx");

Layout must export a Layout component and Page must export a Page component:

const Layout = ({ children }) =>
{
    return <html>
        <head>
            <title>My App</title>
        </head>
        <body>
            {children}
        </body>    
    </html>;
};
export default Layout;
const Page = () =>
{
    return <h1>Hello world</h1>;
};
export default Page;

This method, like the previous one, returns an object with the serverProps method:

app.jsx("/home", "./pages/layout.jsx", "./pages/page.jsx").serverProps((req) =>
{
    return {
        title: "Hello world from server"
    };
});
const Page = () =>
{
    return <h1>__SERVER_PROPS.title__</h1>;
};
export default Page;

Views

The views method declares an automatic routing folder in the style of Vite or Next.js:

app.views("./views");
views/
├── layout.jsx
├── home/
│   └── page.jsx
├── about/
│   └── page.html
└── contact/
    ├── page.jsx
    └── server-props.js

A schema like this would serve the page elements.

  • If we have page.html, it's served directly
  • If it's .jsx, the closest layout is used by going back through the directories
  • If a server-props.js file is included, that code will be used server-side as server props argument:
const serverProps = (req) =>
{
    return {
        title: "Hello world from server"
    };
};
module.exports = serverProps;

The page and layout files use ES modules and server-props.js use CommonJS.

Listen

This wraps Express's listen but with a previous step. In development mode, it will precompile and serve the resulting files. In production mode, it will serve the files assuming they are already compiled.

Important

The html, jsx, and views methods are not dynamic, so after listen they will no longer have an effect. This is because in production there is no build for security reasons.

If you want to create or remove routes after listen, you must do it as you would with Express.

Development

The default mode of the framework is development, so you can run the development server simply with:

node index.js

I'll soon include the hot-reload function for frontend and backend. For now, the best option is to use nodemon:

nodemon --watch ./ --ext js,jsx,ts,tsx,json,html,css --exec "node index.js"

Build

To compile the server, all you need to do is add the --build flag to the main process:

node index.js --build

This will compile the production server into .lexpress-server.js.

If your project uses non-bundleable libraries (whether because they use binaries or any other reason), we can pass a list of external dependencies:

node index.js --build --external external-module1 external-module2

Important

Be careful using __dirname. This compiles everything into a bundle so relative paths would change... use process.cwd().

Production

Once bundled, you can run your server from the .lexpress-server file:

node .lexpress-server

This is a standalone file (unless external modules have been set), so you can isolate it in a container. No other file is needed except the public folder. If you use the public method, you must keep this folder accessible.