Every React codebase grows the same little folder. useLocalStorage.ts. useDebounce.ts. A useMediaQuery that's subtly broken on the server. A click-outside hook copied from a Stack Overflow answer. You write them, they mostly work, and you write them again on the next project.
@lacspace/hooks is that folder — done once, done properly. Twenty-eight hooks, typed, SSR-safe, and dependency-free.

A few you'll use today
useLocalStorage — persisted state that also syncs across tabs via the storage event:
const [theme, setTheme] = useLocalStorage("theme", "system");
// change it in one tab, every tab updates
useDebounce — the search-box classic, without the setTimeout dance:
const [q, setQ] = useState("");
const debounced = useDebounce(q, 300);
useEffect(() => { search(debounced); }, [debounced]);
useMediaQuery — responsive logic in JS, SSR-safe:
const isDesktop = useMediaQuery("(min-width: 1024px)");
useOnClickOutside — close a menu or modal when the user clicks away:
const ref = useRef(null);
useOnClickOutside(ref, () => setOpen(false));
useCopyToClipboard — a copy button with feedback state:
const [copied, copy] = useCopyToClipboard();
<button => copy(code)}>{copied ? "Copied!" : "Copy"}</button>
The full set, by theme
- State & storage — useLocalStorage, useSessionStorage, usePrevious, useToggle, useCounter, useDefault.
- Timing — useDebounce, useThrottle, useInterval, useTimeout, useUpdateEffect, useIsMounted.
- DOM & events — useEventListener, useOnClickOutside, useHover, useWindowSize, useMediaQuery, useIntersectionObserver, useScrollLock.
- Browser — useCopyToClipboard, useNetworkState, useDocumentTitle, useIdle, usePageVisibility.
- Utility — useEventCallback, useMountEffect, useUnmountEffect.
Correct on the server, too
The tricky ones are the browser hooks. useMediaQuery and useWindowSize can't call matchMedia or read window during a server render — so they don't. They return a sensible default on the server and subscribe in an effect on the client, which means no hydration mismatch and no "window is not defined" crash. That correctness is the whole reason to use a library instead of the copy-pasted version.
Import one, ship one
The package is tree-shakeable — sideEffects: false, dual ESM + CJS, full types — so importing useDebounce doesn't drag the other twenty-seven into your bundle.
npm i @lacspace/hooks
@lacspace/hooks anchors the Lacspace React Kit and ships inside every create-lacspace-app project. Full list and signatures at lacspace.com/docs/hooks.
Frequently asked questions
What is @lacspace/hooks?
A single package of 28 essential, everyday React hooks — the ones most projects re-implement from scratch — such as useLocalStorage, useDebounce, useMediaQuery, useOnClickOutside and useCopyToClipboard. Zero dependencies, fully typed, SSR-safe and tree-shakeable.
Are the hooks SSR-safe?
Yes. They never read window, document or matchMedia during render; browser access happens in effects with sensible server fallbacks, so they work in the Next.js App Router without hydration mismatches.
Does importing the package pull in all 28 hooks?
No. The package is tree-shakeable (sideEffects: false, dual ESM + CJS), so your bundle only includes the hooks you actually import.
What makes useLocalStorage "cross-tab"?
It listens to the storage event, so when the value changes in another browser tab, every tab updates in sync — useful for things like theme, auth state or a cart.
Is it free for commercial use?
Yes, under the Lacspace Free Licence (MIT-equivalent freedoms).

