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

isomorphic-form

v0.1.0

Published

Isomorphic HTML form that works on the client and the server

Readme

Universal Form

Many modern web-apps combine javascript and form controls to process user input within the browser. This is all well and good, but what if your code breaks or your user is on an unsupported browser?

Wouldn't it be great if you could gather your form data either through javascript or through traditional form submission, and only write the code to process it once?

Universal Form takes care of this for you. Once it's set up it will send submitted form data to your router, and you don't need to care whether that data came from an HTTP submission or from a javascript submit event.

Benefits of this:

  • Support old browsers without supporting their old javascript
  • Do less transpilation
  • Put IE11 out of your mind

Status

This project is in working order, but it's not pretty and the API may not be stable. The main things left before publishing v1.0.0 are to improve the tests and documentation. Help with road testing and improvements would be greatly appreciated!

Name

I'm not sure the name isomorphic-form is a great idea, but universal-form and universal-form-data were taken and I'm not feeling very creative.

How to use

The package contains two functions, one for the client and one for the server, who expose the form data as an instance of a FormData subclass.

Once you have this data, along with the form method (GET or POST) and the action (the destination url) you can pass it to your universal router or other code to handle it. You no longer have to care if your code is running on client or server.

The FormData sublcass has a toString method which returns the data as a query string in case you want to do something like append it to a url. It also has a toJSON method and a fromString static method.

On the server, FormData is from JSDOM. On the client it's the native implementation.

In the browser

const isoForm = require("isomorphic-form/dist/form");

const onSubmit = (data, method, action) => {
  // This is where you pass the data to your router
};

const formEl = document.querySelector("form.myForm");

// This sets up the listeners and plugs in your callback
const remover = isoForm(onSubmit)(formEl);

// When you're ready to remove the listeners:
remover();

On the server

const app = require("express")();
const parseFormData = require("isomorphic-form/dist/server");

// Make sure you're not using any form-data body-parser plugins before here
app.use("*", async (req, res) => {
  const data = await parseFormData(req);
  const method = req.method;
  const action = req.originalUrl;

  // This is where you pass the data to your router.
});