Skip to Content
Documentation13. Advanced Topics

Advanced Topics

Techniques and patterns for building sophisticated Hyperclay applications.

Multi-Page Applications

While each Hyperclay document is self-contained, you can create multi-page experiences.

Create a consistent navigation structure across multiple HTML files:

<!-- navigation.html --> <nav id="global-nav"> <a href="https://myhomepage.hyperclay.com">Home</a> <a href="https://myaboutpage.hyperclay.com">About</a> <a href="https://mycontactpage.hyperclay.com">Contact</a> </nav> <script> // Highlight current page const currentPath = window.location.pathname; document.querySelectorAll('#global-nav a').forEach(link => { if (link.getAttribute('href') === currentPath) { link.classList.add('active'); } }); </script>

Sharing State Across Pages

Using URL parameters:

// Page 1: Set user preference const params = new URLSearchParams(); params.set('theme', 'dark'); params.set('user', 'john'); window.location.href = `/page2.html?${params}`; // Page 2: Read preference const params = new URLSearchParams(window.location.search); const theme = params.get('theme'); const user = params.get('user');

Using localStorage:

// Shared state manager const appState = { save(key, value) { localStorage.setItem(`myapp_${key}`, JSON.stringify(value)); }, load(key) { const data = localStorage.getItem(`myapp_${key}`); return data ? JSON.parse(data) : null; }, clear(key) { localStorage.removeItem(`myapp_${key}`); } }; // Usage across pages appState.save('user', { name: 'John', role: 'admin' }); const user = appState.load('user');

Creating a Site Map

Build an index page that links to all your documents:

<div class="site-map"> <h2>My Applications</h2> <div class="app-grid"> <a href="/todo.html" class="app-card"> <h3>Todo List</h3> <p>Manage daily tasks</p> </a> <a href="/notes.html" class="app-card"> <h3>Notes</h3> <p>Quick note-taking</p> </a> <a href="/budget.html" class="app-card"> <h3>Budget Tracker</h3> <p>Personal finance</p> </a> </div> </div>

Complex State Management

For applications with intricate state requirements, implement patterns that work with the DOM.

State Machines in the DOM

Use attributes to track complex states:

<div id="app" state="loading" user-role="guest" view="dashboard"> <!-- Show loading --> <div option:state="loading">Loading...</div> <!-- Show error --> <div option:state="error"> <p>Error: <span error-message></span></p> <button onclick="this.val.state = 'loading'; retryLoad()">Retry</button> </div> <!-- Show content --> <div option:state="ready"> <div option:view="dashboard" option:user-role="admin">Admin Dashboard</div> <div option:view="dashboard" option:user-role="user">User Dashboard</div> <div option:view="settings">Settings Panel</div> </div> </div> <script> // State transitions function setState(newState, data = {}) { const app = document.getElementById('app'); app.setAttribute('state', newState); // Update related attributes Object.entries(data).forEach(([key, value]) => { app.setAttribute(key.replace(/([A-Z])/g, '-$1').toLowerCase(), value); }); } // Usage setState('ready', { userRole: 'admin', view: 'dashboard' }); setState('error', { errorMessage: 'Network timeout' }); </script>

Computed Properties

Create reactive computed values using MutationObserver:

<div id="calculator"> <input type="number" name="price" value="100" persist> <input type="number" name="quantity" value="1" persist> <div>Total: $<span computed-total>100</span></div> </div> <script> // Watch for changes and update computed values const observer = new MutationObserver(() => { const calc = document.getElementById('calculator'); const price = parseFloat(calc.querySelector('[name="price"]').value) || 0; const quantity = parseFloat(calc.querySelector('[name="quantity"]').value) || 0; calc.querySelector('[computed-total]').textContent = (price * quantity).toFixed(2); }); observer.observe(document.getElementById('calculator'), { attributes: true, childList: true, subtree: true, attributeFilter: ['value'] }); // Trigger on input document.querySelectorAll('#calculator input').forEach(input => { input.addEventListener('input', () => observer.takeRecords()); }); </script>

Performance Optimization

Build fast applications even with large amounts of data.

Custom Edit Interfaces

Build sophisticated editing experiences tailored to your application.

Visual Page Builder

Create a drag-and-drop interface for page construction:

<div id="page-builder" option:editmode="true"> <div class="toolbar"> <button onclick="addComponent('heading')">Add Heading</button> <button onclick="addComponent('text')">Add Text</button> <button onclick="addComponent('image')">Add Image</button> </div> <div id="canvas" sortable> <!-- Components will be added here --> </div> </div> <script> function addComponent(type) { const components = { heading: '<h2 edit-mode-contenteditable>New Heading</h2>', text: '<p edit-mode-contenteditable>New paragraph text...</p>', image: '<img edit-mode-resource src="/placeholder.jpg" alt="Click to upload">' }; const wrapper = document.createElement('div'); wrapper.className = 'component'; wrapper.innerHTML = components[type]; wrapper.innerHTML += '<button class="delete" onclick="this.parentElement.remove()">�</button>'; document.getElementById('canvas').appendChild(wrapper); } </script>

Inline Property Editor

Build contextual editing panels:

<style> .property-panel { position: absolute; background: white; border: 1px solid #ccc; padding: 10px; display: none; } </style> <div class="property-panel" id="prop-panel"> <label>Background Color: <input type="color" onchange="currentElement.style.background = this.value"> </label> <label>Padding: <input type="range" min="0" max="50" onchange="currentElement.style.padding = this.value + 'px'"> </label> <label>Font Size: <input type="number" min="8" max="72" onchange="currentElement.style.fontSize = this.value + 'px'"> </label> </div> <script> let currentElement; // Show property panel on element click in edit mode document.addEventListener('click', (e) => { if (!window.editMode) return; const panel = document.getElementById('prop-panel'); if (e.target.hasAttribute('editable-properties')) { currentElement = e.target; panel.style.display = 'block'; panel.style.left = e.pageX + 'px'; panel.style.top = e.pageY + 'px'; // Load current values panel.querySelector('[type="color"]').value = getComputedStyle(currentElement).backgroundColor; } }); </script>

Integration with External Services

Connect your Hyperclay apps to the broader web ecosystem.

Webhooks and Automation

Trigger external services on save:

document.addEventListener('beforesave', async () => { // Notify external service await fetch('https://hooks.zapier.com/hooks/catch/...', { method: 'POST', body: JSON.stringify({ app: document.title, timestamp: new Date().toISOString(), stats: { elements: document.querySelectorAll('*').length, todos: document.querySelectorAll('[task]').length } }) }); });

Real-time Data Sync

Sync with external databases:

// Periodic sync with external service setInterval(async () => { if (!window.editMode) return; const tasks = Array.from(document.querySelectorAll('[task]')).map(el => ({ id: el.getAttribute('task-id'), text: el.textContent, status: el.getAttribute('status') })); await fetch('https://api.yourservice.com/sync', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ tasks }) }); }, 30000); // Every 30 seconds

Embedding Third-Party Widgets

Integrate external tools seamlessly:

<!-- Calendar widget --> <div id="calendar-widget"></div> <script src="https://cdn.calendly.com/widget.js"></script> <script> Calendly.initBadgeWidget({ url: 'https://calendly.com/yourname', anchor: document.getElementById('calendar-widget') }); </script> <!-- Analytics --> <script async src="https://www.googletagmanager.com/gtag/js?id=GA_ID"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'GA_ID'); </script>

Future-Proofing Your Apps

Build applications that will continue to work as Hyperclay evolves.

Progressive Enhancement

Start simple and layer features:

// Check for Hyperclay features const features = { editMode: typeof window.editMode !== 'undefined', autoSave: typeof window.triggerSave === 'function', persistence: document.querySelector('[persist]') !== null }; // Add features conditionally if (features.editMode) { // Add edit mode UI } if (!features.autoSave) { // Provide manual save button }
Last updated on