Skip to content

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) → ConceptsVisibility / 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

LevelDocPlayground
BasicThis tutorialVisibility
IntermediateEvents · Session coreEvents · Lifecycle
ProductionCore infrastructure · UsageConfiguration

Step 1 — Install

bash
npm install @jayoncode/browser-lifecycle

Outcome: Package available for import.


Step 2 — Create a session

ts
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

ts
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

ts
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

tsx
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

html
<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

ts
lifecycle.dispose();

Outcome: Listeners removed (sync); instance must not be reused.


Recap

StepAPIResult
1npm installDependency installed
2createBrowserLifecycle()Active session
3on(event, handler)Typed subscriptions
4getSnapshot()Current state
5dispose()Clean teardown

Pitfalls

IssueMitigation
Multiple sessions per tabSingle shared instance
Missing teardownCall dispose() on unmount
SSR accessGuard typeof window !== "undefined"

Continue

TopicGuidePlayground
Visibility moduleVisibilityVisibility
Event patternsEventsEvents
Config & SSRCore infrastructureConfiguration

Quick start · FAQ

An ecosystem of independent, headless TypeScript libraries engineered for modern web development. Every package includes interactive playgrounds and documentation that evolves alongside the code.