A modern demonstration of HTTP streaming with HTML5-compliant Custom Elements and Declarative Shadow DOM using Deno and Hono.js. This demo showcases how to create fast-loading web applications that progressively enhance content while maintaining full HTML5 validation compliance.
- HTTP Streaming: Content loads progressively as data becomes available
- Custom Elements: Semantic, reusable HTML5 components
- Declarative Shadow DOM: Style encapsulation without JavaScript
- HTML5 Compliant: Passes W3C validation with zero errors
- Progressive Enhancement: Works without JavaScript, enhanced with it
- Modern Web Standards: Uses cutting-edge APIs with graceful fallbacks
- Real-time Logging: HTTP chunk timing in both browser and server
-
Start the development server:
cd streaming-demo deno task dev -
Open your browser to
http://localhost:8000 -
Watch the progressive loading:
- Initial page structure loads instantly
<header-section>loads after 2 seconds (blue theme)<content-section>loads after 4 seconds (purple theme)<footer-section>loads after 6 seconds (green theme)
The server uses Hono's stream() functionality to send content progressively:
- Initial HTML structure with loading placeholders is sent immediately
- Custom elements are generated and streamed at timed intervals
- Each chunk replaces a loading placeholder using modern
setHTMLUnsafe()API - Real-time chunk logging shows exactly when each piece arrives
<header-section>
<template shadowrootmode="open">
<style>
/* Styles are encapsulated within this shadow root */
.header-content {
background: #e3f2fd;
border-radius: 8px;
padding: 20px;
}
</style>
<div class="header-content">
<h2>π° Header Section</h2>
<slot></slot>
</div>
</template>
<p>This content goes into the slot</p>
</header-section>- 0ms: Page structure and loading placeholders
- 2000ms:
<header-section>with blue styling - 4000ms:
<content-section>with purple styling - 6000ms:
<footer-section>with green styling
- Hono.js web server with streaming support
- Custom element generators with embedded Shadow DOM
setHTMLUnsafe()API for proper Declarative Shadow DOM parsing- IIFE pattern to avoid variable redeclaration in streamed scripts
- Comprehensive logging with millisecond-precision timing
- Custom Elements: Valid HTML5 semantic components
<style>in<template>: Fully compliant per HTML5 spec- Declarative Shadow DOM: Official Web Components standard
- Progressive Enhancement: Works without JavaScript registration
- Fallback Styles: Support for browsers without custom element support
setHTMLUnsafe(): Proper Shadow DOM parsing (Chrome 124+, Safari 17.4+, Firefox 123+)- Declarative Shadow DOM: Auto-parsing shadow roots (93% browser support)
- Custom Elements: Semantic HTML components (96% browser support)
- HTTP Streaming: Universal browser support
- Chrome 90+: Full feature support including
setHTMLUnsafe() - Safari 16.4+: Complete functionality with all modern APIs
- Edge 90+: Full support for all features
- Firefox 123+: Recently added Declarative Shadow DOM support
- Older browsers: Fallback to
outerHTMLwithout Shadow DOM parsing - Unsupported custom elements: Fallback CSS styling applied
- No JavaScript: Base functionality still works via server-side rendering
- Network Tab: Watch HTTP chunks stream in real-time
- Console: See server-side timing logs
- Elements Tab: Inspect shadow roots and encapsulated styles
- Performance Tab: Measure First Contentful Paint and progressive loading
Run the generated HTML through the W3C Validator:
- β Zero validation errors
- β Custom elements recognized as valid HTML5
- β Declarative Shadow DOM compliant
- β
All
<style>tags properly placed in<template>elements
- DevTools β Network β Throttling
- Select "Slow 3G" or "Fast 3G"
- Observe: Initial structure loads immediately, content streams progressively
- First Contentful Paint: < 100ms (immediate structure)
- Time to Interactive: Immediate for visible content
- Progressive Enhancement: Each section enhances as it loads
- Bandwidth Efficiency: Only sends content when ready
- Server-side rendered: All content is in HTML source
- Semantic markup: Custom elements provide meaningful structure
- Screen reader friendly: Progressive content doesn't disrupt reading flow
- Search engine optimized: Complete content available in source
- Content escaping: All dynamic content properly escaped
- CSP compatible: No inline scripts in final output
- XSS protection: Template-based content generation
- Modern APIs: Uses secure
setHTMLUnsafe()over dangerous alternatives
-
Create element generator:
const generateNewSection = () => ` <new-section> <template shadowrootmode="open"> <style> .new-content { background: #fff3e0; } </style> <div class="new-content"> <slot></slot> </div> </template> <p>New section content</p> </new-section>`
-
Add to streaming sequence:
await delay(3000) await stream.write(generateNewSection())
Edit delays in main.ts:
await delay(2000) // Header at 2s
await delay(2000) // Content at 4s (2s + 2s)
await delay(2000) // Footer at 6s (4s + 2s)Uncomment the custom element definitions in the <head> to add:
- Lifecycle methods:
connectedCallback(),disconnectedCallback() - Attribute watching:
observedAttributesandattributeChangedCallback() - Custom behaviors: Animations, interactions, data fetching
- Event handling: Click handlers, form submissions, etc.
This architecture is perfect for:
- Progressive dashboards with mixed data loading speeds
- Content feeds where some content loads faster than others
- E-commerce pages with real-time inventory and pricing
- Analytics platforms with different data source response times
- News sites with priority content loading
- SaaS applications with modular component loading
- CDN setup: Serve static assets from CDN
- Caching strategy: Appropriate cache headers for streaming responses
- Error boundaries: Handle chunk loading failures gracefully
- Monitoring: Track streaming performance and Shadow DOM support
- Fallback testing: Verify behavior in older browsers
- Input validation: Sanitize all dynamic content
- CSP headers: Content Security Policy for additional protection
- HTTPS only: Secure transport for all content
- Regular updates: Keep Deno and dependencies current
Potential additions:
- Real-time data: WebSocket integration for live updates
- Offline support: Service Worker for progressive web app features
- Lazy loading: Intersection Observer for viewport-based loading
- Micro-frontends: Multiple independent custom element applications
- State management: Shared state between custom elements
Custom elements not styling correctly:
- Verify
setHTMLUnsafe()support in browser - Check console for Shadow DOM parsing warnings
- Ensure
<template shadowrootmode="open">syntax is correct
Validation errors:
- Confirm all
<style>tags are inside<template>elements - Verify custom element names contain hyphens
- Check that Declarative Shadow DOM syntax is proper
JavaScript errors:
- Look for variable redeclaration issues in streamed scripts
- Verify IIFE pattern is wrapping script chunks
- Check that element IDs exist before manipulation
Enable detailed logging:
console.log('Streaming custom element:', elementName, 'at', Date.now())Built with β€οΈ using modern web standards, Deno, and Hono.js