Decision: use* Composable API (Vanilla JS)

Decision

Expose every protection module as a use* function that starts its protection on call and returns a () => void cleanup function. No framework dependency. No React, Vue, or Svelte adapters.

// Drop-in (existing apps, zero restructure)
WebShield.init({ domains: [...], protections: { devtools: true } })

// Composable (any framework or vanilla)
const stop = useDomainLock({ domains: ['techiediaries.com'] })
const stop2 = useDevtools()

// Compose into a single teardown
function useShield(config) {
  const stops = [useDomainLock(config), useDevtools(config), useAntiDebug(config)]
  return () => stops.forEach(s => s())
}

Why

Why use* naming? Convention signals “stateful, has lifecycle, returns cleanup” — same pattern as vanilla JS utilities like useLocalStorage. Readers understand it without documentation.

Why vanilla JS only, not React hooks? Ahmed explicitly ruled out React. The use* pattern is a naming convention for organization, not a framework primitive. Works identically in React, Vue, Svelte, or plain script tags — no adapter needed. Adding framework-specific exports would add complexity with no architectural benefit since each use* is just a function.

Why return a cleanup function instead of an object? Simplest possible interface. One call to start, one call to stop. No .start()/.stop() method pairs, no event emitters. Composing multiple stops is one forEach.

Why dual API (init + use*)?

Both read from the same shared config if init() was called. use* functions also accept local config overrides for per-module customisation.

What was rejected

Single monolithic init only: Would prevent per-module teardown and selective activation. Rejected — composability is a core goal.

Framework-specific adapters (React hooks, Vue composables): Unnecessary. The use* functions work as-is in any environment. Adapters would add maintenance surface for no functional gain.

Class-based API (new WebShield(config).start()): More verbose, no benefit over the function approach. Rejected.