Web Loom logo
Published PackagesPackage Roadmap

Package Roadmap

The full Web Loom package ecosystem — core packages implemented in this monorepo but not yet published to npm (HTTP, Storage, Router, i18n, Notifications, Error handling, Platform detection, Typography), plus the framework adapters and charting library maintained in the sibling web-loom-extensions repo.

Package Roadmap

Web Loom is a larger ecosystem than what is currently on npm from this repo. The infrastructure packages below are implemented in this monorepo (with their own tests) but have not yet been published to the npm registry; of them, only router-core is currently used by a demo app (mvvm-vanilla and the template-core apps). The code samples below use each package's real exports. They follow the same architecture principles as the published core packages: framework-agnostic, zero coupling between layers.

Forms and Media adapters, and the charting library, are a separate case: their framework-specific code and the still-unstable chart library live in the sibling web-loom-extensions repo, which consumes this monorepo's @web-loom/* core packages as published npm dependencies. @web-loom/forms-core itself is already published from this repo — see the Forms section below.


Forms

@web-loom/forms-core

Framework-agnostic form state management built on Zod. Manages field values, validation errors, dirty/touched tracking, field arrays, and submission state — without importing anything from a UI framework. Published from this repo (npm install @web-loom/forms-core zod).

Key features

  • Type-safe form state derived from a Zod schema
  • Field-level and form-level validation on change, blur, or submit
  • Nested objects and field arrays (add, remove, move, swap)
  • Subscription model — subscribe to any field or the whole form
  • Runtime dependencies: @web-loom/event-emitter-core and rxjs (used internally for dirty tracking); zod is a peer dependency
import { FormFactory } from '@web-loom/forms-core';
import { z } from 'zod';
 
const schema = z.object({
  email:    z.string().email(),
  password: z.string().min(8),
});
 
const form = FormFactory.create({
  schema,
  defaultValues: { email: '', password: '' },
  onSubmit: (values) => api.login(values),
});
 
form.setFieldValue('email', 'user@example.com');
const stop = form.subscribeToField('email', (field) => {
  console.log(field.value, field.error, field.touched);
});
 
await form.submit(); // validates, then calls onSubmit when valid
stop();
form.destroy();

Framework adapters (in web-loom-extensions)

@web-loom/forms-react, @web-loom/forms-vue, and @web-loom/forms-vanilla bind forms-core to a specific rendering target. They use the same @web-loom/* package names but live in web-loom-extensions and aren't on npm yet:

// React
import { useForm, useField } from '@web-loom/forms-react';
 
// Vue 3
import { useForm, useField } from '@web-loom/forms-vue';
 
// Vanilla TypeScript
import { bindForm } from '@web-loom/forms-vanilla';

Media (in web-loom-extensions)

@web-loom/media-core, @web-loom/media-react, and @web-loom/media-vue are a framework-agnostic media player engine plus React/Vue adapters, maintained in web-loom-extensions (not yet on npm). media-core mounts native <video>/<audio>/<img> elements, manages playback state, and exposes a typed plugin and event system:

import { MediaCore } from '@web-loom/media-core';
 
const player = new MediaCore({ src: 'https://example.com/video.mp4', autoPlay: false, muted: true });
player.mount(document.getElementById('video-container')!);
player.on('timeupdate', (currentTime, duration) => {
  progressBar.style.width = `${(currentTime / duration) * 100}%`;
});
player.play();

The React and Vue adapters wrap this in a useMediaPlayer hook/composable — see the web-loom-extensions repo for details.


Infrastructure

@web-loom/http-core

TypeScript-first HTTP client with no runtime dependencies, built on fetch.

Key features

  • Request/response/error interceptor pipeline
  • Automatic retries with configurable exponential backoff
  • Request deduplication — concurrent identical requests are collapsed into one
  • Cancellation support via AbortController
  • Mock adapter for unit testing without a real server
  • Full generic typings on request and response bodies

API

import { createHttpClient } from '@web-loom/http-core';
 
const http = createHttpClient({
  baseURL: 'https://api.example.com',
  timeout: 10_000,
  retry: { maxRetries: 3, backoffMultiplier: 2, jitter: true },
  deduplicate: true,
});
 
// Interceptors — use() returns an id you can pass to eject()
http.interceptors.request.use((config) => ({
  ...config,
  headers: { ...config.headers, Authorization: `Bearer ${getToken()}` },
}));
 
// Typed requests resolve to an HttpResponse<T>
const users = await http.get<User[]>('/users');
const created = await http.post<User>('/users', newUser);

@web-loom/storage-core

Unified storage abstraction over IndexedDB, localStorage/sessionStorage, and in-memory backends. All backends share the same async API, so you can swap storage strategies without changing application code.

Key features

  • Backends: 'indexeddb', 'localstorage', 'sessionstorage', 'memory' (pass an array for fallback order)
  • Versioned migrations for schema evolution between releases
  • Change subscriptions by key pattern, with optional cross-tab sync
  • Per-key TTL with lazy or eager expiration
  • Namespace isolation to prevent key collisions between features

API

import { createStorage } from '@web-loom/storage-core';
 
const storage = await createStorage({
  backend: ['indexeddb', 'localstorage'], // first available wins
  name: 'my-app',
  namespace: 'user-prefs',
  crossTab: true,
});
 
await storage.set('theme', 'dark');
const theme = await storage.get<string>('theme'); // → 'dark'
 
const unsubscribe = storage.subscribe('theme', (event) => {
  applyTheme(event.newValue);
});

@web-loom/router-core

Framework-agnostic routing with declarative route definitions, nested routes, dynamic segments, and a full navigation guard lifecycle.

Key features

  • History mode and hash mode behind a unified interface
  • Nested route hierarchies
  • Dynamic segments (:id) and wildcard routes
  • Navigation guards: global beforeEach/afterEach, per-route beforeEnter/canActivate
  • Query string utilities
  • router.subscribe() for reactive navigation state (plain callback-based pub-sub, no RxJS dependency)

API

import { createRouter } from '@web-loom/router-core';
 
const router = createRouter({
  mode: 'history',
  routes: [
    { path: '/',          component: HomePage },
    { path: '/users',     component: UserListPage },
    { path: '/users/:id', component: UserDetailPage },
  ],
});
 
// Guards return true/void to continue, false to cancel, or a path to redirect
router.beforeEach((to) => {
  if (to.path.startsWith('/admin') && !auth.isAuthenticated) return '/login';
});
 
// Navigation state via plain callbacks — returns an unsubscribe function
const stop = router.subscribe((route) => {
  analytics.page(route.path);
});
 
await router.push({ path: '/users/42' });

@web-loom/notifications-core

Browser notification management: system notifications, toast/snackbar integration, permission tracking with cross-tab events, and push subscription management.

Key features

  • Request and track Notification permission state
  • Send system notifications, with grouping via group(name)
  • Toast adapter hook — plug in any toast library via showToast
  • Callbacks for permission changes, notification clicks/closes and push messages
  • Push subscription management and service worker registration

API

import { createNotifications } from '@web-loom/notifications-core';
 
const notifications = createNotifications(); // a NotificationManager
 
await notifications.requestPermission();
 
await notifications.notify('New message', {
  body: 'You have 3 unread messages.',
  icon: '/icon.png',
  tag:  'messages',
});
 
notifications.showToast('File saved', { duration: 3000 }); // forwarded to your toast adapter
 
const stop = notifications.onPermissionChange((state) => {
  showNotificationButton.hidden = state === 'denied';
});

@web-loom/i18n-core

Type-safe internationalization built from small composable pieces: locale detection, a locale store, a translation registry and loader, and Intl-based formatters.

Key features

  • Type-safe translation keys — TypeScript errors on missing or misspelt keys
  • Locale detection from browser, URL, or a custom resolver
  • Lazy loading and caching of translation JSON files
  • RTL detection per locale
  • Number, date, list, and plural formatters via the native Intl API
  • Interpolation and nested key support

API

import {
  LocaleStore,
  TranslationRegistry,
  createTranslator,
  NumberFormatter,
  detectBrowserLocale,
} from '@web-loom/i18n-core';
 
const locales = new LocaleStore(detectBrowserLocale());
const registry = new TranslationRegistry();
registry.register('fr-FR', { 'user.greeting': 'Bonjour, {name}' });
 
locales.setLocale('fr-FR');
const t = createTranslator(registry, locales.getLocale());
t('user.greeting', { name: 'Alice' }); // → "Bonjour, Alice"
 
new NumberFormatter().format(12345.67, 'fr-FR', { style: 'currency', currency: 'EUR' });

@web-loom/error-core

Centralised error handling, structured logging, and resilience patterns. No runtime dependencies.

Key features

  • Domain-specific error classes: NetworkError, ValidationError, BusinessError, CompositeError
  • ErrorHandler — central registry for routing errors to the right handlers
  • Structured logging with pluggable transports (console, remote, silent)
  • Retry strategies: fixed delay, exponential backoff, jitter
  • Circuit Breaker pattern — open after N failures, half-open after a cooldown
  • Fallback Manager — define fallback values or functions for failed operations
  • Context management for attaching request IDs, user IDs, etc. to error reports

API

import { ErrorHandler, CircuitBreaker, isNetworkError } from '@web-loom/error-core';
 
const handler = ErrorHandler.initialize(); // singleton
 
const stop = handler.onError((captured) => {
  if (isNetworkError(captured.error)) toast.show(`Network error: ${captured.error.message}`);
});
 
// Circuit breaker around an unstable API
const breaker = new CircuitBreaker({
  failureThreshold: 5,      // open after 5 failures
  resetTimeout:     30_000, // try half-open after 30s
  halfOpenMaxAttempts: 3,
});
 
const data = await breaker.execute(() => fetch('/api/data'));

@web-loom/platform-core

Device, operating system, browser, and feature detection backed by RxJS observables for dynamic state like network status, battery, and viewport changes.

Key features

  • Device type: mobile, tablet, desktop
  • Platform/OS: iOS, Android, Windows, macOS, Linux
  • Browser: Chrome, Firefox, Safari, Edge
  • Feature detection: touch, WebGL, geolocation, notifications, service workers
  • Reactive (RxJS observables): network status$/online$, battery status$, viewport size$/width$/height$/orientation$

API

import { platform, networkObservable, viewportObservable } from '@web-loom/platform-core';
 
// Static detection (platform is a ready-made PlatformDetector)
console.log(platform.deviceType()); // 'mobile' | 'tablet' | 'desktop'
console.log(platform.os());
console.log(platform.features());
 
// Reactive (RxJS)
networkObservable.online$.subscribe((online) => {
  offlineBanner.hidden = online;
});
 
viewportObservable.size$.subscribe(({ width, height }) => {
  console.log(`Viewport: ${width}×${height}`);
});

UI & Typography

@web-loom/typography-core

Typography calculations, color manipulation, web font management, accessibility presets, and advanced text animation utilities.

Key features

  • Modular type scales (Major Third, Perfect Fourth, Golden Ratio, etc.)
  • Fluid typography — CSS clamp() values from viewport range and scale
  • Vertical rhythm utilities
  • Color manipulation: LAB, HSL, RGB color spaces; contrast ratio calculation (WCAG AA/AAA)
  • Web font manager with performance helpers (preconnect, preload, display strategies)
  • Accessibility presets: dyslexia-friendly, low-vision, motion-safe
  • Readability analytics and estimated reading time
  • Text animations: typewriter, fade-in by word/character, 3D reveal effects
  • RTL support and multilingual helpers

API

import { generateModularScale, createFluidType, validateTextAccessibility } from '@web-loom/typography-core';
 
// Modular scale: base size, ratio, number of steps
const scale = generateModularScale(16, 1.25, 4);
 
// Fluid type: min/max font size and min/max viewport width (px) → a CSS clamp() string
const fluid = createFluidType(16, 20, 375, 1440);
 
// Accessibility report for a rendered element (includes WCAG contrast ratio and AA pass/fail)
const report = validateTextAccessibility(document.querySelector('p'));

Charts (in web-loom-extensions)

@web-loom/charts-core

A D3-based, configuration-driven charting toolkit, maintained in web-loom-extensions (not yet on npm). Supports line, area, and scatter series with interactive legends, crosshair overlays, tooltip management, a zoom/pan plugin, and a deep-mergeable theme system.

Features

  • Line, area, and scatter series with marker and curve customisation
  • Time and linear D3 scales via ScaleRegistry
  • Configurable axes (top/bottom/left/right) and annotation layers
  • Shared and per-point tooltips with follow/fixed strategies
  • Interactive legend with toggle and hover
  • Crosshair overlay
  • Built-in light theme with deep-merge ChartTheme overrides
  • AdaptiveRenderStrategy switching to Canvas above 10 000 data points
  • ChartPlugin interface with built-in ZoomPanPlugin
  • Config validation via validateChartConfig

When Will the Infrastructure Packages Be Published?

There is no fixed release schedule for the still-unpublished infrastructure packages above (http-core, storage-core, router-core, notifications-core, i18n-core, error-core, platform-core, typography-core). They're published when:

  1. The public API is considered stable.
  2. Test coverage is sufficient.
  3. The package has been exercised in at least one real demo application.

Watch the GitHub repository and the npm @web-loom scope for new releases. If you need one of these packages before it ships, its source is available in this monorepo and can be used directly via the workspace protocol.

Other packages in this monorepo that are also not yet on npm: @web-loom/mvvm-patterns, @web-loom/embed-core, @web-loom/view, and the @web-loom/template-core family (template-core, -vite, -vite-ssr, -router, -lint, -tooling).

The Forms adapters, Media packages, and charts-core live in the web-loom-extensions repo and aren't on npm yet; use them from source until they're released.

Was this helpful?
Web Loom logo
Copyright © Web Loom. All rights reserved.