Tutorial — your first session
Observe browser state first — install, start a session, subscribe to events, read the snapshot, dispose. Optional session intelligence and DX come later (zero-cost until you ask).
Progressive path: Basic (this page) → Concepts → Visibility / Events.
Previous: Core concepts · Next: Visibility
Playground
Visibility explorer — switch tabs and observe event order.
Prerequisites: Node 20+, browser or SSR-aware bootstrap.
Learning path
| Level | Doc | Playground |
|---|---|---|
| Basic | This tutorial | Visibility |
| Intermediate | Events · Session core | Events · Lifecycle |
| Production | Core infrastructure · Usage | Configuration |
Step 1 — Install
npm install @jayoncode/browser-lifecycleOutcome: Package available for import.
Step 2 — Create a session
import { createBrowserLifecycle } from "@jayoncode/browser-lifecycle";
const lifecycle = createBrowserLifecycle({ autoStart: true });Outcome: Session in running phase with modules attached per configuration.
Step 3 — Subscribe to events
lifecycle.on("page:visible", () => {
resumePolling();
});
lifecycle.on("page:hidden", () => {
pausePolling();
});Outcome: Handlers run on normalized visibility transitions. Unsubscribe via returned function.
Step 4 — Read snapshot
const snapshot = lifecycle.getSnapshot();
console.log(snapshot.visibility); // "visible" | "hidden" | "unknown"Outcome: Readonly view of current session state without manual listener bookkeeping.
UI structure (framework shell)
Browser Lifecycle has no form markup — mount one shared session and dispose on unmount.
React JSX
import { useEffect, useMemo } from "react";
import { createBrowserLifecycle } from "@jayoncode/browser-lifecycle";
export function AppShell({ children }: { children: React.ReactNode }) {
const lifecycle = useMemo(() => createBrowserLifecycle({ autoStart: true }), []);
useEffect(() => {
const offVisible = lifecycle.on("page:visible", () => resumeWork());
const offHidden = lifecycle.on("page:hidden", () => pauseWork());
return () => {
offVisible();
offHidden();
lifecycle.dispose();
};
}, [lifecycle]);
return <>{children}</>;
}Vanilla HTML + module script
<body>
<main id="app"><!-- your UI --></main>
<script type="module">
import { createBrowserLifecycle } from "@jayoncode/browser-lifecycle";
const lifecycle = createBrowserLifecycle({ autoStart: true });
lifecycle.on("page:hidden", () => console.log("tab hidden"));
window.addEventListener("pagehide", () => {
lifecycle.dispose();
});
</script>
</body>Step 5 — Dispose
lifecycle.dispose();Outcome: Listeners removed (sync); instance must not be reused.
Recap
| Step | API | Result |
|---|---|---|
| 1 | npm install | Dependency installed |
| 2 | createBrowserLifecycle() | Active session |
| 3 | on(event, handler) | Typed subscriptions |
| 4 | getSnapshot() | Current state |
| 5 | dispose() | Clean teardown |
Pitfalls
| Issue | Mitigation |
|---|---|
| Multiple sessions per tab | Single shared instance |
| Missing teardown | Call dispose() on unmount |
| SSR access | Guard typeof window !== "undefined" |
Continue
| Topic | Guide | Playground |
|---|---|---|
| Visibility module | Visibility | Visibility |
| Event patterns | Events | Events |
| Config & SSR | Core infrastructure | Configuration |
