spark_web

Server-safe Web API abstraction for Dart, mirroring the MDN Web API naming exactly.

Overview

spark_web provides a cross-platform Web API layer that works on both the Dart VM (server) and dart2js/dart2wasm (browser).

  • On the browser, types wrap the real package:web DOM objects.
  • On the server, types are no-ops or provide Dart-native fallbacks (e.g., Storage backed by a Map, Crypto.randomUUID() via dart:math).

Because the naming matches MDN exactly, developers can look up any type or method on MDN Web Docs and apply the same knowledge.

Installation

dependencies:
  spark_web:
    path: ../spark_web  # or from pub

Usage

import 'package:spark_web/spark_web.dart' as web;

void main() {
  // DOM — same API as MDN
  final el = web.document.querySelector('#app');
  el?.classList.add('ready');
  el?.setAttribute('data-loaded', 'true');

  // Window
  web.window.localStorage.setItem('key', 'value');
  final uuid = web.window.crypto.randomUUID();

  // Events
  el?.addEventListener('click', (event) {
    print('Clicked: ${event.type}');
  });

  // Clipboard
  web.window.navigator.clipboard.writeText('Hello!');

  // Timers
  web.window.setTimeout(() => print('delayed'), 1000);
}

Accessing the native package:web object

On the browser, every spark_web type wraps a native package:web object. Use .raw to access it:

final sparkElement = web.document.querySelector('div');
final nativeElement = sparkElement?.raw; // web.Element from package:web (null on server)

Permissions

final status = await web.window.navigator.permissions.query(
  const web.PermissionDescriptor(name: web.PermissionName.camera),
);
print(status.state); // PermissionState(prompt)

Platform detection

if (web.kIsBrowser) {
  // Browser-only code
}

Architecture

spark_web/lib/
├── spark_web.dart              # Barrel export + global singletons (window, document)
└── src/
    ├── api.dart                # Conditional import pivot (server ↔ browser)
    ├── core.dart               # EventTarget, Event, Node, NodeList, MutationObserver
    ├── dom.dart                # Element, HTMLElement, Document, ShadowRoot, Text, Comment
    ├── collections.dart        # DOMTokenList, NamedNodeMap, Attr
    ├── css.dart                # CSSStyleSheet, CSSStyleDeclaration
    ├── canvas.dart             # CanvasRenderingContext2D, TextMetrics, ImageData
    ├── file.dart               # Blob, File, FileList
    ├── geolocation.dart        # Geolocation, GeolocationPosition, GeolocationCoordinates
    ├── notification.dart       # Notification, NotificationOptions, NotificationAction
    ├── permissions.dart        # Permissions, PermissionStatus, PermissionDescriptor
    ├── window.dart             # Window, Storage, Location, History, Navigator, Console, ...
    ├── server/                 # Server implementations (no-ops / Dart-native fallbacks)
    │   ├── factory.dart
    │   ├── dom.dart
    │   ├── collections.dart
    │   ├── css.dart
    │   ├── canvas.dart
    │   ├── file.dart
    │   ├── geolocation.dart
    │   ├── notification.dart
    │   ├── permissions.dart
    │   └── window.dart
    └── browser/                # Browser implementations (wrap package:web)
        ├── factory.dart
        ├── dom.dart
        ├── collections.dart
        ├── css.dart
        ├── canvas.dart
        ├── file.dart
        ├── geolocation.dart
        ├── notification.dart
        ├── permissions.dart
        └── window.dart

API Coverage

The table below tracks what percentage of the MDN Web API is implemented. Contributions welcome!

DOM Core

API Status Notes
EventTarget ✅ Done addEventListener, removeEventListener, dispatchEvent
Event ✅ Done type, target, currentTarget, bubbles, cancelable, preventDefault, stopPropagation, stopImmediatePropagation
MouseEvent ✅ Done clientX/Y, pageX/Y, screenX/Y, button, buttons, modifier keys
KeyboardEvent ✅ Done key, code, repeat, location, modifier keys
InputEvent ✅ Done data, inputType, isComposing
FocusEvent ✅ Done relatedTarget
WheelEvent ✅ Done deltaX, deltaY, deltaZ, deltaMode
TouchEvent ✅ Done touches, targetTouches, changedTouches, modifier keys
PointerEvent ✅ Done pointerId, width, height, pressure, tangentialPressure, tiltX/Y, twist, pointerType, isPrimary
DragEvent ✅ Done dataTransfer
AnimationEvent ✅ Done animationName, elapsedTime, pseudoElement
TransitionEvent ✅ Done propertyName, elapsedTime, pseudoElement
CustomEvent ✅ Done detail
Node ✅ Done Full tree traversal, appendChild, removeChild, cloneNode, etc.
NodeList ✅ Done length, item()
MutationObserver ✅ Done observe, disconnect, takeRecords
MutationRecord ✅ Done type, target, addedNodes, removedNodes, attributeName
TreeWalker ❌ TODO
NodeIterator ❌ TODO
Range ❌ TODO
Selection ❌ TODO

DOM Elements

API Status Notes
Element ✅ Done tagName, id, className, innerHTML, classList, querySelector, etc.
HTMLElement ✅ Done innerText, hidden, title, style, shadowRoot, attachShadow
HTMLDivElement ✅ Done
HTMLSpanElement ✅ Done
HTMLParagraphElement ✅ Done
HTMLInputElement ✅ Done value, type, placeholder, disabled, checked, name
HTMLTextAreaElement ✅ Done value, placeholder, disabled, rows, cols
HTMLButtonElement ✅ Done disabled, type
HTMLSelectElement ✅ Done value, selectedIndex, disabled
HTMLOptionElement ✅ Done value, text, selected
HTMLAnchorElement ✅ Done href, target
HTMLImageElement ✅ Done src, alt, width, height
HTMLFormElement ✅ Done action, method, submit(), reset(), reportValidity()
HTMLLabelElement ✅ Done htmlFor
HTMLTemplateElement ✅ Done content
HTMLCanvasElement ✅ Done getContext(), toDataURL(), width, height
HTMLMediaElement ✅ Done src, currentTime, duration, paused, volume, play(), pause(), load(), etc.
HTMLVideoElement ✅ Done width, height, videoWidth, videoHeight, poster, playsInline
HTMLAudioElement ✅ Done Inherits all from HTMLMediaElement
HTMLDialogElement ✅ Done open, returnValue, show(), showModal(), close()
HTMLDetailsElement ✅ Done open, name
HTMLSlotElement ✅ Done name, assignedNodes(), assignedElements()
HTMLIFrameElement ✅ Done src, name, allow, allowFullscreen, width, height, loading, referrerPolicy
HTMLTableElement ✅ Done caption, tHead, tFoot, createTBody(), insertRow(), deleteRow()
HTMLTableSectionElement ✅ Done insertRow(), deleteRow()
HTMLTableRowElement ✅ Done rowIndex, sectionRowIndex, insertCell(), deleteCell()
HTMLTableCellElement ✅ Done colSpan, rowSpan, cellIndex
HTMLHeadingElement ✅ Done h1–h6
HTMLUListElement ✅ Done
HTMLOListElement ✅ Done reversed, start, type
HTMLLIElement ✅ Done value
HTMLPreElement ✅ Done
HTMLHRElement ✅ Done
HTMLBRElement ✅ Done
HTMLProgressElement ✅ Done value, max, position
HTMLMeterElement ✅ Done value, min, max, low, high, optimum
HTMLOutputElement ✅ Done value, defaultValue, name, type, htmlFor

Document & Fragments

API Status Notes
Document ✅ Done createElement, createTextNode, querySelector, getElementById, etc.
DocumentFragment ✅ Done querySelector, querySelectorAll
ShadowRoot ✅ Done host, mode, adoptedStyleSheets, querySelector
Text ✅ Done data, wholeText
Comment ✅ Done data
DOMParser ❌ TODO parseFromString()
XMLSerializer ❌ TODO serializeToString()

Collections

API Status Notes
DOMTokenList ✅ Done add, remove, toggle, contains, replace
NamedNodeMap ✅ Done item, getNamedItem, removeNamedItem
Attr ✅ Done name, value
HTMLCollection ❌ TODO namedItem()
DOMStringMap ❌ TODO dataset access
DOMRect ❌ TODO x, y, width, height, top, right, bottom, left
DOMRectReadOnly ❌ TODO

CSS

API Status Notes
CSSStyleSheet ✅ Done replaceSync, replace
CSSStyleDeclaration ✅ Done getPropertyValue, setProperty, removeProperty, display, visibility, opacity
CSSRule ❌ TODO
CSSStyleRule ❌ TODO
CSSMediaRule ❌ TODO
CSSKeyframesRule ❌ TODO
CSSKeyframeRule ❌ TODO
MediaQueryList ❌ TODO matches, media, addListener()
StyleSheetList ❌ TODO

Window & Globals

API Status Notes
Window ✅ Done document, localStorage, setTimeout, requestAnimationFrame, btoa/atob, etc.
Storage ✅ Done getItem, setItem, removeItem, clear, key, length
Location ✅ Done href, protocol, host, pathname, search, hash, origin, etc.
History ✅ Done pushState, replaceState, back, forward, go, state
Navigator ✅ Done userAgent, language, languages, onLine, clipboard
Console ✅ Done log, warn, error, info, debug
Crypto ✅ Done randomUUID()
Performance ✅ Done now()
CustomElementRegistry ✅ Done define, get, upgrade, whenDefined
Clipboard ✅ Done readText, writeText
Screen ❌ TODO width, height, availWidth, availHeight, orientation
VisualViewport ❌ TODO width, height, offsetLeft, offsetTop, scale
BarProp ❌ TODO visible

Async & Networking

API Status Notes
fetch() ❌ TODO Global fetch function
Request ❌ TODO
Response ❌ TODO
Headers ❌ TODO
AbortController ❌ TODO signal, abort()
AbortSignal ❌ TODO aborted, reason
URL ❌ TODO href, origin, protocol, host, pathname, search, hash
URLSearchParams ❌ TODO get, set, append, delete, entries
WebSocket ❌ TODO send(), close(), readyState
EventSource ❌ TODO Server-sent events
XMLHttpRequest ❌ TODO Legacy — consider skipping
FormData ❌ TODO append, get, set, entries
Blob ✅ Done size, type, text(), arrayBuffer(), slice(), stream()
File ✅ Done name, lastModified (extends Blob)
FileList ✅ Done length, item()
FileReader ❌ TODO readAsText(), readAsDataURL(), result

Observers

API Status Notes
MutationObserver ✅ Done observe, disconnect, takeRecords
IntersectionObserver ❌ TODO observe, disconnect, unobserve
ResizeObserver ❌ TODO observe, disconnect, unobserve
PerformanceObserver ❌ TODO

Canvas & Graphics

API Status Notes
CanvasRenderingContext2D ✅ Done Full 2D drawing: rect, path, arc, bezier, text, image, pixel manipulation, transforms, state save/restore, line dash, compositing
TextMetrics ✅ Done width, actualBoundingBoxLeft/Right/Ascent/Descent, fontBoundingBoxAscent/Descent
ImageData ✅ Done width, height, data
OffscreenCanvas ❌ TODO
Path2D ❌ TODO
WebGLRenderingContext ❌ TODO Consider out of scope
WebGL2RenderingContext ❌ TODO Consider out of scope

Media

API Status Notes
MediaStream ❌ TODO
MediaRecorder ❌ TODO
MediaDevices ❌ TODO getUserMedia()
AudioContext ❌ TODO Web Audio API

Web Workers

API Status Notes
Worker ❌ TODO postMessage(), terminate()
SharedWorker ❌ TODO
ServiceWorkerContainer ❌ TODO
BroadcastChannel ❌ TODO postMessage(), close()
MessageChannel ❌ TODO
MessagePort ❌ TODO

Geometry & Layout

API Status Notes
Element.getBoundingClientRect() ❌ TODO Returns DOMRect
Element.getClientRects() ❌ TODO
Element.scrollIntoView() ❌ TODO
Element.scrollTo() ❌ TODO
Element.scroll properties ❌ TODO scrollTop, scrollLeft, scrollWidth, scrollHeight
Element.client properties ❌ TODO clientWidth, clientHeight, clientTop, clientLeft
Element.offset properties ❌ TODO offsetWidth, offsetHeight, offsetTop, offsetLeft, offsetParent

Miscellaneous

API Status Notes
Crypto.getRandomValues() ❌ TODO Typed array crypto
SubtleCrypto ❌ TODO encrypt, decrypt, sign, verify, digest
TextEncoder ❌ TODO encode()
TextDecoder ❌ TODO decode()
structuredClone() ❌ TODO
queueMicrotask() ❌ TODO
Notification ✅ Done title, body, icon, tag, close(), NotificationOptions, NotificationAction, requestPermission()
Geolocation ✅ Done getCurrentPosition, watchPosition, clearWatch, GeolocationPosition, GeolocationCoordinates, PositionOptions
Permissions ✅ Done query(), PermissionStatus, PermissionState, PermissionName, PermissionDescriptor (+ Push, Midi, Device variants)
FullScreen API ❌ TODO requestFullscreen(), exitFullscreen()

Legend: ✅ Done — ❌ TODO

Not all MDN Web APIs are equally relevant for server-safe rendering. The coverage plan prioritizes APIs commonly used in component code (DOM, events, forms, CSS) over niche APIs (WebGL, Web Audio, WebRTC).

Libraries

spark_web
Server-safe Web API for Dart.