Open source collection · Est. 2026

Everything frontend needs

A curated collection of micro-utilities for the web.
Each one solves exactly one frontend problem —
perfectly, with zero dependencies.

Packages published
02 and growing
Total bundle size
~4kB gzip
Dependencies
0 always
#
Package
Keywords
Size
Deps
01
hotkey-hint New
Keyboard shortcut manager with a beautiful overlay. Register hotkeys, press ? to reveal. Supports sequences, groups, themes.
keyboard shortcuts overlay
~3kB
zero
02
form-dirty New
Unsaved changes detection. Snapshot form state, expose isDirty + changedFields, handle beforeunload. Framework agnostic.
forms state ux
~1.0kB
zero
03
paste-rich Soon
Smart clipboard paste handler. Normalizes paste events into typed payloads: image, file, html, text. No more clipboardData parsing.
clipboard paste files
~1.1kB
zero
04
viewport-units-fix Soon
Reliable --vh and --vw CSS variables that actually work on mobile Safari. One script, stops the 100vh problem forever.
css mobile safari
~0.5kB
zero
01 — Rule

One problem.
One package.

No feature creep. No "while we're at it."
Each utility does exactly one thing
and does it better than a 5-minute
StackOverflow copy-paste ever could.

02 — Rule

Zero deps.
Always.

No lodash. No moment. No anything.
You install the package — not the package
plus a hundred transitive dependencies
you didn't ask for.

03 — Rule

Ships typed.
Works everywhere.

TypeScript-first. ESM + CJS output.
Every package works in React, Vue,
Svelte, vanilla JS, and anywhere
else you're building.

Start with
form-dirty

The latest package in the collection.
Unsaved changes detection — snapshot
form state, expose isDirty + changedFields,
handle beforeunload. In 3 lines.

View documentation
View on npm
Quick start
// 1. Install
npm install form-dirty

// 2. Import & init
import FormDirty from 'form-dirty';
const fd = new FormDirty({
  form: '#my-form',
  beforeUnload: true,
});

// 3. Check anytime
console.log(fd.isDirty);        // true / false
console.log(fd.changedFields);  // [{ name, original, current }]

// After saving, re-baseline ✦
fd.snapshot();