Skip to main content
Enhanced Fetch

fetchJSON with retry, dedup, timeout. fetchOffline queues when offline.

Ready...
import { enhance } from 'weblisk';
import { fetchJSON, fetchOffline } from 'weblisk/net/fetch.js';

enhance('#demo-fetch', (el, { $ }) => {
  $('#btn-fetch').addEventListener('click', async () => {
    $('#output-fetch').textContent = 'Fetching...';
    try {
      const data = await fetchJSON(
        'https://jsonplaceholder.typicode.com/posts?_limit=5',
        { timeout: 5000 }
      );
      $('#output-fetch').textContent =
        `Loaded ${data.length} posts:\n` +
        data.map(p => p.title).join('\n');
    } catch (err) {
      $('#output-fetch').textContent = `Error: ${err.message}`;
    }
  });

  $('#btn-fetch-offline').addEventListener('click', async () => {
    try {
      const result = await fetchOffline('/api/analytics', {
        method: 'POST',
        body: JSON.stringify({ event: 'demo', timestamp: Date.now() })
      });
      $('#output-fetch').textContent = result.queued
        ? 'Request queued for when back online'
        : `Sent (status ${result.status})`;
    } catch (err) {
      $('#output-fetch').textContent = `Queued: ${err.message}`;
    }
  });
});
WebSocket

Reactive WebSocket with auto-reconnect, heartbeat, and message buffering.

Disconnected
import { effect, enhance } from 'weblisk';
import { socket } from 'weblisk/net/ws.js';

enhance('#demo-ws', (el, { $ }) => {
  let conn = null;

  $('#btn-ws').addEventListener('click', () => {
    if (conn) { conn.close(); conn = null; }

    conn = socket('wss://echo.websocket.org', {
      reconnect: false,
      heartbeat: 0
    });

    effect(() => {
      const s = conn.state();
      let text = `State: ${s}\n`;
      const msgs = conn.messages();
      if (msgs.length) {
        text += `Messages: ${msgs.length}\n`;
        text += msgs.slice(-3)
          .map(m => `  → ${JSON.stringify(m)}`)
          .join('\n');
      }
      $('#output-ws').textContent = text;
    });
  });
});
Server-Sent Events

Reactive SSE with named event channels and auto-reconnect.

No events
import { effect, enhance } from 'weblisk';
import { stream, latest } from 'weblisk/net/sse.js';

enhance('#demo-sse', (el, { $ }) => {
  let conn = null;

  $('#btn-sse').addEventListener('click', () => {
    if (conn) { conn.close(); conn = null; }

    conn = stream('/api/events');
    const last = latest(conn.events);

    effect(() => {
      const s = conn.status();
      let text = `Status: ${s}\n`;
      const evts = conn.events();
      if (evts.length) {
        text += `Events: ${evts.length}\n`;
        const recent = last();
        if (recent)
          text += `Latest: ${JSON.stringify(recent.data)}`;
      }
      $('#output-sse').textContent = text;
    });
  });
});
Real-Time Transport

Unified WebTransport (HTTP/3) → WebSocket fallback. Multiplexed channels, auto-reconnect.

Ready...
import { effect, enhance } from 'weblisk';
import { transport } from 'weblisk/net/transport.js';

enhance('#demo-transport', (el, { $ }) => {
  $('#btn-transport').addEventListener('click', () => {
    const hasWT = typeof WebTransport !== 'undefined';
    const hasWS = typeof WebSocket !== 'undefined';

    const conn = transport('wss://echo.websocket.org', {
      reconnect: false,
      heartbeat: 0
    });

    effect(() => {
      const s = conn.state();
      let text = `WebTransport: ${hasWT ? 'Yes' : 'No'}\n`;
      text += `WebSocket: ${hasWS ? 'Yes' : 'No'}\n`;
      text += `State: ${s}\n`;
      text += `Using: ${hasWT ? 'WebTransport' : 'WebSocket'}`;
      $('#output-transport').textContent = text;
    });
  });
});