# Hyperclay > Experience the Zen of making, hosting, and sharing great software in a single, portable, malleable, vanilla HTML file. Build interactive applications like you're sculpting clay, not managing infrastructure. The worst of modern web development forces you through layers of abstraction: config files, build steps, magical framework abstractions, deployment pipelines. Hyperclay returns to a simple model: your app is a single HTML file you can manipulate directly. Edit the file through its visual UI and it persists its own state. The web should be as simple to edit as a document. Hyperclay makes it possible: UI, logic, and data live in a single malleable HTML file. You can edit it live, share it, or download it and use it locally. It's Google Docs for interactive code. Shareable, portable, malleable HTML files. You fully control the document, what it looks like, and how it works. **Direct Manipulation** — Edit your app while it's running. No compile step, no refresh needed. Changes happen instantly, like editing a document. Share a URL and users see your page as it updates. **Your Frontend is the App** — The UI is the app itself. When you modify the interface or edit the source code in DevTools, you're directly changing the file itself. There's no abstraction layer. **True Portability** — Download your file and run it offline using our free local app or on any server. On our platform or locally, we take a backup on every save so you don't lose work. The coolest part? It's just an HTML file. Nothing special. Change it, it serializes its DOM, and sends it to a /_/save endpoint. Nothing magic about it. ## Documentation The sections below contain the full Hyperclay platform documentation. --- # Overview - Have you ever tried editing a website directly in your browser and wished your changes would stick? - Do you enjoy simple, self-contained projects where everything can fit in your head? - Are you curious about how to share an interactive HTML project that others can see — and maybe even edit? --- **Meet Hyperclay™ — A Single-File Approach to Web Dev** Hyperclay lets you get personal software out the door and launched so people can actually use it instead of it sitting in a folder on your desktop. It does this by allowing you to pack up all your frontend functionality into a single HTML file and release it as a standalone, lightweight app. * All markup, styles, scripts, and admin UI live in one HTML file * Download and open locally for an instant working app * Drop the same file on any server so others can view or even edit it --- **How it works** Hyperclay hosts single HTML files that you can edit anywhere — locally, in a cloud editor, or directly in the page’s own UI. When you’re the page owner, your changes persist. If you’re not, you’ll only see the view mode of the page, and any tweaks you make won’t save. When you’re ready to share your creation, you can host it on Hyperclay or any server you prefer. Until then, it’ll work right on your desktop. --- **Why This Matters** Imagine if your browser could write to your computer’s file system. You’d open an HTML file, change stuff, and it would stay changed. That’s the essence of Hyperclay: one small file with everything you need to create simple, persistent apps. It's just an HTML file + HyperclayJS — using the `.html` or `.htmlclay` extension, no framework required. --- **What You Can Build** Want to track your workouts? Make a personal devlog? Record voice memos? You can do all this (and so much more) with Hyperclay. It’s still just front-end HTML + CSS + JS, so anything you can normally do on a static website is possible — just packed into a single, server-persisted file. --- **"Why not just use localStorage?"** localStorage only saves changes on your own machine. If you want others to see your work, you need a server to store those changes and keep track of who can edit what. Hyperclay handles that for you, syncing your edits so everyone sees the same final page. --- **“Why not just build a small React app?”** Sure, React/Vue/Svelte are great when you’re working on larger projects or you need complex state management. But even with the simplest React app, you’re usually spinning up Node, installing dependencies, configuring bundlers, and publishing to a hosting service. Hyperclay cuts through that. It’s literally one HTML file you open in a browser and edit. --- **How about user accounts and saving data?** Hyperclay has its own approach. By default, everyone views the same read-only page. You only see editing controls if you’re the page owner (logged in via the Hyperclay service). As the owner, your edits automatically save and sync to the server so the new version you made loads for everyone else. Owning a page is as simple as creating a Hyperclay account and picking a password, so it’s easy to manage without messing around with complex server configs. --- **View vs. Edit Mode** Hyperclay pages have two modes. Most people see the view mode: a static page that works like any website. Owners see edit mode: special controls to rearrange components, update text, or add new features. Owners can log in, edit the page, and save changes so others see the updated version. Special controls get stripped out or hidden again when you save, so regular visitors keep seeing a clean, read-only page. HyperclayJS comes with built-in admin attributes (`editmode:contenteditable`, `viewmode:disabled`, `editmode:resource`, etc.) that make elements editable for admins and persist those changes to the DOM. On save, the `contenteditable` and `onclick` admin attributes are stripped so the page is view-only for regular visitors. `editmode:resource` elements are instead made inert: their style, link, or script `type` is set to `inert/...`, and they are re-activated for owners on page load. --- **HyperclayJS** HyperclayJS can automatically handle persisting form inputs, toggling admin attributes, and saving whenever changes occur. It also has lots of other utilities and special attributes, e.g. hooks like `onbeforesave` for final cleanup before you commit your changes. --- **Offline Editing/Local Apps** These are your apps. Hyperclay retains no ownership over them. Once you download them locally, you can use them on your own machine offline. Want to sync them back up? Publish your changes later when you're back online. --- **How It Works** All the editing code lives in the same HTML file as the read-only code. Whenever you save, Hyperclay strips out the admin interface so visitors just see the finished product. If you’re the owner, scripts re-inject the editing tools when you reload the page. --- **DOM as Database** The concept of letting the DOM itself store your data is central. You can use `contenteditable` elements or toggled checkboxes as state, so you don’t have to rely on separate JSON files or a “real” database. For more complex data, you can store JSON in a `
``` This is a basic, fully-working Hyperclay app. You don't technically need HyperclayJS or the `editmode:contenteditable` attribute, but here's what they handle for you: 1. Save the page when the DOM changes (or when the save keyboard shortcut is pressed) 2. Disables the `contenteditable` attribute before saving (so regular viewers can't edit the page) 3. Enables the `contenteditable` attribute if a page owner loads this page --- **Forking and Sharing** Anyone can download your Hyperclay file and run it on their own computer/server to become the new owner. The single HTML file is entirely self-contained. --- **The Basic Cycle** 1. Load the page in view mode 2. If you’re the owner, edit mode is enabled and loads up your editing controls 3. When you save, everything reverts to view mode before being stored --- **Who is Hyperclay for?** - Beginners: If you’ve only dabbled in HTML/CSS but want to publish interactive apps without diving into a full-blown framework - Tinkerers/Hackers: If you like exploring the edge of what's possible on the front-end web and hate fussing with layers of tooling - Micro-app Creators: If you have a small idea and want a self-contained solution that isn’t spread across a complex stack **Where’s the Catch?** Of course, Hyperclay isn’t the best option if you’re building a giant e-commerce site or need super-sophisticated routing, databases, or user groups. But for personal projects, prototypes, or simple tools, it’s refreshing and powerful. It feels simple, like writing a Google Doc. **Why I Built This** I love the idea of minimal friction. Most web dev stacks these days involve scaffolding, deployments, and a bunch of dependencies. Hyperclay strips all that away, leaving you with a single file and a server that “just works.” It’s a fun return to simpler times, without sacrificing the best parts of modern web dev. Hyperclay is truly frictionless—no installation steps, no bundlers, and no config. Just one file. Period. **It feels like the web’s original vision.** > “The Web was designed as an interactive space where everyone can edit.” — Tim Berners-Lee Back in the early days of the web, some of its creators imagined it as a place where you could “View Source” on any page, tweak it, then re-publish. In practice, you usually need hosting, version control, SSH keys, and a million dev tools. Hyperclay tries to bring back the playful part of the web: open an HTML file, make a change, and see it reflected immediately—no complicated pipeline. **Get Started** Hyperclay doesn’t replace React or Next.js or your favorite stack. It’s a different way of publishing small, interactive HTML files that feel alive the moment you open them. If that resonates with you, give it a spin. Try making your own devlog or a mini to-do list as your first Hyperclay project — just open a blank .html file, add your markup, and watch it work with little effort from you. I’d love to hear your questions or see what you build. Hyperclay might look small, but it unlocks a world of possibilities in just one file. Enjoy—and, as always, happy hacking! --- # Get Started with Hyperclay With a new baby due in September, I wanted to bank some extra hours at my contracting job and needed a way to track them for my boss. "Wouldn't it be great," I thought, "if I could just slap some checkboxes representing my hours on a page and call it a day?" Unfortunately, there's no easy stack for something that simple — unless I used this new platform I'd just deployed. So I opened a page, added a beautiful classless stylesheet and threw on a few dozen checkboxes. Try it here: https://panphora.hyperclay.com/core/hours.html?editmode=true ## What You'll Build A time tracking app that: - Saves checkbox state and notes without any database - Has different views for the owner (interactive) and visitors (read-only) - Lets you add new weeks with a button click - Works as a single, portable HTML file ## Step-by-Step Build Process ### Step 1: Create Your App 1. Go to [hyperclay.com](https://hyperclay.com) 2. Choose a name for your app (e.g., "hours") 3. Click "Create Site" ### Step 2: Add the Basic HTML Structure Click "Edit Code" in your app's menu and replace the default HTML with this: ```html Hours

Hours

``` That single script tag gives you auto-saving, edit/view modes, and DOM persistence — everything you need to make a page that can modify itself and save the changes. ### Step 3: Add Styling Include Pico CSS for instant beautiful styling: ```html ``` ### Step 4: Create the Time Tracking Interface Add checkboxes for each hour, organized by week: ```html
Week 1
``` ### Step 5: Make It Persistable and Admin-Only Add the magic Hyperclay attributes: - `persist` - Saves checkbox state to the DOM - `viewmode:disabled` - Only admins can check/uncheck ```html ``` ### Step 6: Add Editable Notes Each week could use a notes section for context — maybe you stayed late for a deploy, or left early on Friday. Add a heading and paragraph inside each week's container: ```html
Weekly Notes

``` - **`editmode:contenteditable`**: Makes the element editable only for the page owner. Visitors see the text as static content. When the owner clicks the paragraph, they can type freely — and their changes persist on save just like the checkboxes. This is different from `viewmode:disabled` (which enables/disables form controls). `editmode:contenteditable` turns any element into a rich text field for owners only. ### Step 7: Add a New Week Button After four weeks, I needed a fifth. Then a sixth. Instead of editing the HTML every time, I added a button that clones the last week and resets it: ```html ``` **`option:editmode="true"`** makes this button visible only to the page owner. Visitors never see it — it's completely removed from the page in view mode. Any element can use `option:` attributes to toggle visibility based on the page's state. But there's a problem: cloning a week copies its checked boxes and typed notes. Each element needs to reset itself when cloned. That's what `onclone` is for: ```html
Week 1

``` **`onclone`** runs on the newly cloned element (not the original). Each element knows how to reset itself — the heading calculates the next week number, the checkboxes uncheck themselves, and the notes clear back to placeholder text. `All.week.length` counts every element with class `week` on the page. Since the clone hasn't been inserted into the DOM yet when `onclone` runs, we add 1 to get the correct number. Now the "Add Week" button is a single line, and all the reset logic lives on the elements that own it. ## Understanding the Key Attributes - **`persist`**: This attribute tells Hyperclay to save the checkbox's checked state directly to the DOM. When you check a box and save (Ctrl+S), the `checked` attribute is added to the HTML. - **`viewmode:disabled`**: This makes the input only interactive for the site owner. Visitors see a disabled checkbox. - **`option:editmode="true"`**: Hides the element from visitors entirely. Only the page owner sees it. Useful for admin controls like add/delete buttons. - **`onclone`**: Runs code on a newly cloned element. `this` refers to the clone, so each element can reset itself independently. ## View Mode vs Edit Mode **As a visitor**, you see: - Read-only checkboxes showing hours worked - Clean, professional time tracking display - No ability to modify the data **As the owner**, you see: - Fully interactive checkboxes - Ability to check/uncheck hours - The "+ Add Week" button for adding new weeks - Changes save automatically with Ctrl+S ## Try Your Live App 1. Visit `https://panphora.hyperclay.com/core/hours.html` (or the URL for the app you created) 2. Check some boxes, type some notes, then refresh — your changes persist 3. Open an incognito window to see the clean, read-only visitor view 4. Toggle edit mode with `?editmode=true` in the URL to see both views ## Complete Code ```html Hours

Hours

Week 1
Weekly Notes

Week 2
Weekly Notes

``` ## What's Next? - **[Core Concepts](/docs/core-concepts)** — deeper patterns like DOM as database, save-strip-restore, and state machines - **[Example Apps](/docs/example-apps)** — more real-world Hyperclay apps to learn from --- # How Hyperclay Works ## The Big Idea I got tired of how many steps are required to put a malleable page on the internet, so I decided to build a simple solution: Hyperclay is a platform that lets you host HTML pages that can overwrite themselves. We call these "malleable HTML files". Malleable HTML files can be modified in Hyperclay's code editor or even from your browser's DevTools, and changes you make to them from anywhere will be persisted. Meanwhile, visitors to your page will see the read-only version, so they'll see your changes but won't be able to modify your page themselves. Where things get really powerful is when you layer an editable UI on top of your page — then you don't have to go to the code editor or open DevTools, you can just open up your site and start modifying it right there. It feels like magic: to have a malleable, persistently online object that you can shape in real-time. That's what Hyperclay is all about: the feeling of shaping the internet, as easy as opening and modifying a Google Doc. ## HTML as DB Since each page's HTML is its own source of truth, the process it uses to update itself is important. Here's how it works: 1. You load the page with edit-mode off 2. Hyperclay checks to make sure you're the owner of the page 3. If you're the owner, edit-mode is turned on This means you get all the powerful admin-editing tools layered on top of the page if you're the owner. But regular viewers just see a static website. ## Authentication Hyperclay uses cookie-based authentication to identify site owners. When you create a site or log in, Hyperclay sets a secure cookie that identifies you as the owner. This cookie is checked on every page load to determine if edit mode should be enabled. The authentication is handled entirely by Hyperclay's servers - you don't need to implement any auth logic in your HTML. ## The Save Cycle is Very Important The save cycle is the most important thing to understand about how Hyperclay works. Here's how it works: 1. You, as the owner, load the page 2. Hyperclay detects that you're the owner and helps you make things editable 3. You modify the page using the editable UI you built 4. You save the page 5. Hyperclay strips out all the editable UI and saves the page To make this save cycle easier to handle, we have a script you can use: ## HyperclayJS `` I recommend using this on all Hyperclay projects. It does a few things really well. 1. It persists all form input values that have a special `persist` attribute (e.g. `` will persist its `checked` state to the DOM) 2. It saves the page whenever I press the keyboard shortcut `Ctrl + s` 3. Before saving 1. It strips all admin attributes marked with `edit-mode` (`editmode:onclick`, `editmode:contenteditable`, `viewmode:disabled`) 2. It renders all admin resources inert if they have a special `[editmode:resource]` attribute (think: disables admin-only JS/CSS) 3. It hides all admin UI with an `[option:editmode="false"]` attribute on it and shows any admin UI with an `[option:editmode="true"]` attribute 4. It runs any function inside of an `onbeforesave` attribute (e.g. `onbeforesave="this.remove()"`) 5. It runs all callbacks passed to `hyperclay.beforeSave(cb)`, so you can do more advanced cleaning here (e.g. `hyperclay.beforeSave(documentElement => documentElement.querySelectorAll(".remove-this").forEach(el => el.remove()))` 4. After the page load, it adds back all admin attributes and UI elements if the user is the owner It's a simple and easy way to make HTML editable and persistent without having to build a saving library yourself. ## The Goal: Portable, Single-File Malleable HTML Malleable HTML files should be self-contained and portable. Any user should be able to download a malleable HTML file and use it themselves in `edit-mode` locally, just as if they were the original author. This means: 1. Always use fully-qualified URLS (use `https://cdn.jsdelivr.net/npm/hyperclayjs@latest/src/hyperclay.js?preset=smooth-sailing` not a relative path) 2. It's often simpler to leave `edit-mode` HTML in the DOM and hide it for non-owners — instead of removing it and recreating it every time --- # Core Concepts We encourage thinking differently about how you build a hyperclay app than you would a regular app. The idea behind Hyperclay is that you have a new kind of document. It's a web document, but it's dynamic, portable, fungible. You can pass it around to your friends. Or host it anywhere. It's portable, light, easy-to-think about. Many of these patterns are handled automatically by HyperclayJS — the JavaScript library that turns a plain HTML file into a self-saving, editable app. ## Traditional Web App vs Hyperclay | Traditional Web App | Hyperclay App | |-------------------|---------------| | Separate frontend/backend | Single HTML file | | Database queries | DOM as database | | API endpoints | Direct DOM manipulation | | Build process | No build needed | | Multiple files | Self-contained document | | Complex state management | DOM attributes as state | Regular apps have lots of moving pieces, lots of parts to integrate together from different areas of the stack. For this reason, principles like DRY and separation of concerns matter a lot more. But with Hyperclay, it's the opposite. You want to mush everything together. Keep locality of concern. If you look at a piece of your HTML later, even just a small piece, you should understand how it functions in itself and as part of the wider project within a few seconds. ### Example: Traditional vs Hyperclay Toggle Traditional approach: ```javascript // script.js document.getElementById('toggle').addEventListener('click', () => { fetch('/api/toggle-setting') .then(res => res.json()) .then(data => updateUI(data)); }); // Separate API endpoint, database update, etc. ``` Hyperclay approach: ```html
Settings content here...
``` Your document should look and behave simpler than an app, where behaviors and UI and state are so separate and so different from each other. A hyperclay document should feel more like a state machine. Something flat and grokable. Declarative is the word I'm looking for. It's not like a regular web app, with a bunch of GOTO-like syntax, like AJAX calls that trigger backend functionality, that sends a response, that ends up in some other piece of higher-level state in your app. No, it's just a DOM tree. You change state somewhere, just once, and the behavior and UI change appropriately. It's no big deal. ## DOM as Database In traditional web apps, data lives in a separate database. In Hyperclay, the DOM itself is your database. **Traditional approach:** ```javascript // Data in JavaScript let tasks = [{id: 1, text: "Buy milk", done: false}]; // Sync to DOM function renderTasks() { tasksContainer.innerHTML = tasks.map(t => `
${t.text}
` ).join(''); } ``` **Hyperclay approach:** ```html
Buy milk
``` The DOM element is the single source of truth. No synchronization needed. For most cases, the DOM will act as a natural database, which means you don't have to worry about anything. The user will edit the text of an element and that element will not be modified. The user will move an element somewhere else, and now that element will be permanently moved. The fun thing about using the DOM as your database is the DOM's tree structure. Since it has cascading nodes and branches, each level of those nodes and branches is a natural component. It only needs to be tagged to create a natural encapsulation of functionality and state. Another neat feature is the way attributes and their values can be used to simultaneously store behavior, information, and appearance. This makes it a state machine and a hierarchical declarative UI/UX model. This is a powerful combination, allowing you to encode a lot of cascading options and functionality in the toggle of a single attribute value. ### Using JSON for Complex Data But for special cases, you may want to store data as JSON or another special format. In this case, I'd recommend using a ` ``` ## Malleable Documents Hyperclay documents can modify and save themselves. This isn't just editing content—it's the document rewriting its own source code. **How it works:** 1. User interacts with the page 2. JavaScript modifies the DOM 3. Save captures the entire DOM state 4. The modified HTML becomes the new document **Example self-modification:** ```html ``` When saved, the new section becomes part of the permanent document. ## View vs Edit Mode Every Hyperclay document operates in two distinct modes: ### View Mode - Default state for all visitors - Interactive but read-only - No editing controls visible - Forms and buttons work normally ### Edit Mode - Available only to document owners - Editing controls appear - Elements become modifiable - Save functionality enabled **Mode-specific elements:** ```html

Page Title

``` It's much preferable to hide admin controls instead of removing them from the page entirely. This gives us less to worry about dynamically adding when the page loads and sticks to the model of a hypermedia application, where state and associated functionality is fully loaded into the page at all times. For conditionally showing/hiding UI, we have the excellent `option:` attributes. ### Using option: Attributes ```html

Admin Panel

``` ## Save-Strip-Restore Cycle The three-phase cycle that enables clean separation between editing and viewing: ### 1. Save Phase When you trigger save: - `onbeforesave` callbacks fire for cleanup - Admin resources marked with `editmode:resource` (style, link, script) are made inert by prefixing their `type` with `inert/`, so they don't run for visitors - Admin and view attributes are colon-namespaced (`editmode:contenteditable`, `editmode:onclick`, `editmode:resource`, `viewmode:disabled`, `viewmode:readonly`) - The cleaned DOM is serialized to HTML and sent to the server ```javascript // The actual save mechanism const html = document.documentElement.outerHTML; const cleanedHtml = handleEditModeElements(html); fetch('/_/save', { method: 'POST', body: cleanedHtml, headers: { 'Page-URL': location.href } }); ``` ### 2. Strip Phase The server stores the cleaned HTML: - No editing interfaces remain - No admin-only code exists - Just the pure application ### 3. Restore Phase When an editor loads the page: - Edit permissions are detected - Admin resources marked with `editmode:resource` are re-enabled by stripping the `inert/` prefix from their `type` - Hidden admin interfaces appear - Save functionality activates ### When Saves Trigger **Automatic triggers:** - DOM mutations (structure changes) - Attribute changes - Text content changes - Form value changes (with `persist`) **Manual triggers:** - Keyboard: Cmd/Ctrl+S - Elements with `trigger-save` - Calling `hyperclay.savePage()` **What doesn't trigger saves:** - Elements with `no-trigger-autosave` (saved, but edits don't mark the page dirty) - Elements with `no-save` (stripped from the saved file) - Elements with `no-watch` (invisible to the mutation system) or `freeze` (saved as authored) - Transient UI states (hover, focus) - CSS-only changes Legacy aliases `save-ignore`, `save-remove`, `mutations-ignore`, and `save-freeze` still work. ### The onbeforesave Attribute If you need to do more complex operations to prepare a page for viewing by anonymous web visitors, you can use `onbeforesave` attributes. These are powerful because you can run any arbitrary JS inside them you can think of. ```html
Temporary message
``` For application-wide cleanup, use the global hook: ```javascript hyperclay.beforeSave(function(doc) { // Remove all temporary elements doc.querySelectorAll('[data-temp]').forEach(el => el.remove()); // Add save timestamp doc.body.dataset.lastSaved = new Date().toISOString(); }); ``` ## Locality of Concern Unlike traditional web development that separates HTML, CSS, and JavaScript into different files, Hyperclay embraces locality—keeping related code together. **Everything in one place:** ```html

Counter: 0

``` Structure, styling, and behavior unite in a single, understandable unit. ## Don't Be Afraid to Inline Code When you want people to administrate your page, I highly recommend using the `onclick`, `oninput`, `onsubmit` attributes. Inline event handlers are great at encapsulating bite-size pieces of functionality and they live local to where the activity is happening. It's easy to design an app that's simple, where everything can fit into your head. ```html New task ``` **Add button:** ```html ``` The template provides structure. Cloning creates instances. The DOM provides its own component system. ## Event Delegation Since content can be added dynamically, use event delegation to handle events on future elements: ```html ``` New elements automatically inherit behavior based on their classes and position in the DOM. ## Progressive Enhancement Start simple, add complexity only when needed: ```html

My App

My App

My App

``` Each attribute adds one specific capability. Build up functionality incrementally. ## State Machines in the DOM For applications with intricate state requirements, use attributes to track complex states: ```html
Loading...

Error:

Admin Dashboard
User Dashboard
Settings Panel
``` ### Computed Properties Create reactive computed values using MutationObserver: ```html
Total: $100
``` ## Single File Philosophy Everything lives in one HTML file: - **Markup**: The structure - **Styles**: The appearance - **Scripts**: The behavior - **Data**: The state - **Editor**: The development environment When everything is in one place, you can understand the entire application at once. No hidden dependencies. No configuration files. No build process. Your HTML file is simultaneously: - The source code - The deployed application - The development environment - The data storage To build an app on Hyperclay, you build your front-end how you'd normally build it, using whatever vanilla JS libraries you want. Add all the admin controls and editable areas you want, but try to keep them supplemental to the page, so removing or hiding them won't affect the flow of the page that much. --- # Example Apps These are all working apps that persist their state on Hyperclay - they change the DOM and the DOM saves itself automatically. Every example below uses HyperclayJS — a single script tag that gives your HTML file the ability to save itself, toggle between admin and visitor modes, and persist DOM changes automatically. We include jQuery versions as a familiar, easy-to-understand first example, but encourage you to explore the often much simpler Hyperclay-native syntax. ## Counter ### With jQuery ```html

Counter: 0

``` ### With HyperclayJS ```html

Counter: 0

``` ## Todo List ### With jQuery ```html

My Todos

``` ### With HyperclayJS ```html

My Todos

``` ## Note Pad ### With jQuery ```html

My Notes

``` ### With HyperclayJS ```html

My Notes

``` ## Timer ### With jQuery ```html

00:00

``` ### With HyperclayJS ```html

00:00

``` ###### "These aren't apps, they're just HTML pages you can modify!!" Yes :) # Advanced Example Apps Ready-to-use applications that demonstrate Hyperclay's full potential. Each can be cloned and customized for your needs. ## [Dev Log](https://panphora.hyperclay.com/core/devlog.html?editmode=true) A software developer's work log for tracking daily progress and debugging sessions. - **Features**: Sortable entries, project categorization, monospace aesthetic - **Use case**: Technical journaling, development notes, team updates - **Key patterns**: DOM-based data storage, sortable lists, inline editing, category toggling ## [Writer](https://panphora.hyperclay.com/core/writer.html?editmode=true) A beautiful WYSIWYG editor for creating formatted documents. - **Features**: Rich text editing, image imports, syntax highlighting - **Use case**: Blog posts, documentation, formatted notes - **Key patterns**: Script as JSON database ## [Kanban](https://panphora.hyperclay.com/core/kanban.html?editmode=true) A Trello-style project management board with drag-and-drop functionality. - **Features**: Draggable cards and columns, inline editing - **Use case**: Project tracking, workflow management, task organization - **Key patterns**: Template cloning ## [Landing](https://panphora.hyperclay.com/core/landing.html?editmode=true) A professional landing page template that's ready to customize. - **Features**: Responsive design, markdown content, fill-in-the-blanks - **Use case**: Product launches, marketing pages, startups - **Key patterns**: Edit-mode popovers, undo/redo support --- # Hyperclay.com Platform ## Platform Features Hyperclay provides essential tools for creating and managing malleable HTML files without the complexity of traditional web development infrastructure. ### Code Editor The code editor is available by prefixing your app's path with `/_/edit/` (e.g., `{your-username}.hyperclay.com/_/edit/{your-app}.html`). **Features:** - Syntax highlighting for HTML, CSS, and JavaScript - Auto-indentation and bracket matching - Line numbers and search functionality **Alternative: Browser DevTools** Many developers prefer using the browser's built-in Developer Tools as their editor: 1. Open your malleable HTML file in view mode 2. Press F12 to open DevTools 3. Navigate to the Elements panel 4. Edit HTML directly by double-clicking elements 5. Changes persist when you save — but only if the page has HyperclayJS autosave loaded (owner + edit mode) ### Upload Files and Images Hyperclay supports file uploads directly within your malleable HTML files. ```js hyperclay.uploadFile(eventOrFile); // Uploads a file from either a file input event or File object, showing progress toasts and copying the URL on completion ``` **File limits:** - Maximum file size: 10MB (free) / 20MB (Personal) / 100MB (Maker) per upload - Supported formats: Images (JPG, PNG, GIF), documents, and other common file types - Files are organized by path in your dashboard for easy management **Using uploads in your app:** ```html My uploaded image ``` **Upload with progress tracking:** ```javascript await hyperclay.uploadFileBasic(file, { onProgress: (percent) => { progressBar.style.width = percent + '%'; }, onComplete: (result) => { console.log('Uploaded:', result.url); gallery.innerHTML += ``; }, onError: (error) => { console.error('Upload failed:', error); } }); ``` **Drag and drop:** ```html
Drag files here
``` **Creating files programmatically:** ```javascript const result = await hyperclay.createFile({ fileName: 'backup.json', fileBody: JSON.stringify(data) }); ``` **Batch upload:** ```javascript const uploads = files.map(file => hyperclay.uploadFile(file) ); const results = await Promise.all(uploads); ``` **Mobile camera capture:** ```html ``` ### Form Submissions Handle form submissions from users without a backend using the `sendMessage` method. ```js hyperclay.sendMessage(eventOrObj, successMessage, successCallback?) ``` Sends a message from an anonymous viewer to the app owner — stored in their Hyperclay dashboard and emailed to them — but only if the sender is likely to be human and not a bot. If passing in a submit `event`, all form fields will be sent. Otherwise, object will be converted to JSON and sent. **Contact form example:** ```javascript async function handleSubmit(form) { const data = getDataFromForm(form); await hyperclay.sendMessage(data, 'Message sent successfully!', () => form.reset() ); } ``` **Form with attachments:** ```javascript const attachments = []; for (const file of files) { const result = await hyperclay.uploadFile(file); attachments.push(result.url); } formData.attachments = attachments; await hyperclay.sendMessage(formData); ``` ### URLs & Domains Your Hyperclay account is a namespace. Every app you create lives inside it at `{your-username}.hyperclay.com/{app-name}.html`. Folders reflect in the URL — an app at `/projects/todo.html` lives at `{your-username}.hyperclay.com/projects/todo.html`. Three ways to reach your apps: - **Default namespace URL** — `{your-username}.hyperclay.com/{app-name}.html` - **Promoted subdomain** (paid) — claim a dedicated subdomain like `{app-name}.hyperclay.com` for a flagship app - **Custom domain** (paid): - Connect your own domain (e.g., `myapp.com`) - Automatic SSL certificates - Minimal DNS setup — add a CNAME/A record at your registrar ### Hosting Locally Run Hyperclay apps on your own machine for development or offline use. **Option 1: Direct file access** 1. Download your malleable HTML file 2. Open it in a web browser 3. Works immediately (though without save persistence) **Option 2: Hyperclay Local** - Desktop application for full local hosting - Maintains save/edit functionality - Perfect for development and testing - See the [Hyperclay Local documentation](/docs/hyperclay-local-app) for details ### Hosting on Your Own Server Hyperclay apps are just HTML files, so they work on any web server. **Basic hosting:** 1. Download your malleable HTML file 2. Upload to any static file host (GitHub Pages, Netlify, Vercel, etc.) 3. The app works immediately in view mode **Advanced hosting with persistence:** To enable edit/save functionality on your own server, you'll need: - A simple backend to handle save requests - Basic authentication for edit permissions - File write capabilities ### Integrate with Other Services Hyperclay apps can connect to external services and APIs. **Using fetch for API calls:** ```html ``` **Function-as-a-Service integration:** Services like Val.town let you add backend functionality without managing servers: ```html ``` **CORS considerations:** When integrating external services, ensure they support CORS or use services designed for client-side access. ### Tailwind CSS Hyperclay automatically generates Tailwind CSS for your apps. No build tools, no config files required. Add this to your ``: ```html ``` Replace `YOUR-APP-NAME` with your HTML filename (without `.html`). For a file named `my-app.html`: ```html ``` If your app lives in a folder, the Tailwind URL mirrors that path. For an app at `/projects/todo.html`: ```html ``` Then use Tailwind classes anywhere in your HTML: ```html ``` The CSS regenerates on save (and on first request if missing) with only the utilities you use. Works on hyperclay.com and Hyperclay Local. ### Multi-Tenant Apps After enabling signups on your app (click "Enable Signups" in your app's menu), make sure your users know about these URLs (i.e. link to them from your app's UI): For app at `{your-username}.hyperclay.com/{app-name}.html`: | Action | URL | What it does | |--------|-----|--------------| | **Sign up** | `{your-username}.hyperclay.com/_/signup/{app-name}.html` | Create new account & get personal instance | | **Login** | `{your-username}.hyperclay.com/_/login/{app-name}.html` | Access their instance | | **Forgot password** | `{your-username}.hyperclay.com/_/forgot-password/{app-name}.html` | Reset password via email | **What happens after signup:** 1. They create an account with username, email, and password 2. They automatically get their own instance at: `{their-username}.hyperclay.com/{app-name}.html` 1. Each instance lives in the signer-upper's own namespace — it's theirs, not yours 2. If you're using a custom domain, it'll be `{their-username}.customdomain.com/{app-name}.html` 3. They're redirected to their personal instance after signup 4. Each instance is a complete copy of your app that they can edit As the developer, you can access and edit the app from your dashboard. **Billing & Limits:** There are no limits right now on the number of end users who can sign up to your multi-tenant app. We may introduce limits in the future. Note that this is about end-user signups into a multi-tenant app, which is separate from the apps you create yourself: free account owners are capped at 10 self-created app instances, after which Hyperclay returns "Free accounts are limited to 10 app instances. Upgrade for unlimited." Upgrading to a paid plan removes that cap. ### Multi-Page Applications While each Hyperclay document is self-contained, you can create multi-page experiences. **Navigation between documents:** Create a consistent navigation structure across multiple HTML files: ```html ``` This example assumes your apps live at your namespace root (e.g., `/home.html`). For apps in subfolders, compare the pathname tail instead of the full pathname. **Sharing state across pages:** Using URL parameters: ```javascript // 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: ```javascript // 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'); ``` --- # Collections Mark any folder as a collection and Hyperclay turns it into a place to gather submissions: a public form anyone can fill out, and a private dashboard only you can see. Every submission is saved as a JSON record inside your own folder, so the data is yours and travels with your account. Hyperclay seeds a working form and dashboard for you, but they are just plain HTML files. You can edit them, swap them out, or build your own from scratch against the same API. This page is that API. ## Mark a folder as a collection In your file manager, open a folder's menu and choose **Mark as Collection**. Hyperclay adds three things inside it: - `submission-form.html`, a public form, - `dashboard.html`, an owner-only dashboard, - a `records/` folder, where submissions are stored as JSON. To build your own pages you need two values. Open the collection's menu and choose **Collection info**: - **Collection ID** (looks like `col_a1b2c3xy`): the public id for the API. It is stable, so it never changes even if you rename or move the folder. - **Submit token**: the credential a public form sends to create a submission. You only need this if you build your own form. ## The API Every endpoint is JSON over the same origin as your site. Send and read `application/json`. A plain HTML form post will not work, you submit with `fetch`. | Method | Path | Who | Purpose | |---|---|---|---| | POST | `/_/collection//records` | anyone with the token | create or update a submission | | GET | `/_/collection//records?limit=&offset=` | owner only | list submissions | | GET | `/_/collection//records/` | depends on the record | read one submission | | PUT | `/_/collection//records/` | owner or the record's owner | update one submission | | DELETE | `/_/collection//records/` | owner only | delete one submission | `` is the Collection ID from the modal. In a list (the owner GET that returns `records`), each record comes back as: ```json { "id": "...", "data": { }, "modifiedAt": "2026-06-01T...", "size": 128 } ``` A single-record read returns `{ "id": "...", "data": { }, "modifiedAt": "2026-06-01T..." }`, without `size`. In both cases `data` is whatever JSON you submitted. Success responses are `{ "ok": true, ... }`. Failures return a non-2xx status with `{ "ok": false, "error": "..." }`. Limits: 1MB per submission, 30 requests per minute per IP, and 10,000 records per collection. Records count toward your account's file storage. ## Build your own form The simplest public form collects some fields and POSTs them as `data` with the submit token. Hyperclay gives each submission an unguessable id and remembers it in a cookie, so the same browser can come back and edit its own submission later. ```html
``` `data` is just an object. You decide its shape. There is no server-side schema to define. ### Let submitters come back and edit (optional) Pass a `key` you choose (an email, a phone number) plus a `code` (a secret the submitter picks). The record is then identified by the key and protected by the code: the submitter can reload it from any device by re-sending the key and code, and nobody else can read or change it. The code is never stored, only a hash of it. ```js body: JSON.stringify({ token: TOKEN, key: email, code: secret, data }) ``` To load an existing keyed record back into a form, GET it with the code in a header so it stays out of the URL: ```js const res = await fetch(`/_/collection/${ID}/records/${encodeURIComponent(email)}`, { headers: { 'x-collection-code': secret } }) const { ok, data } = await res.json() ``` ## Build your own dashboard A dashboard is even simpler, because when you (the owner) view a page on your own site, your login cookie rides along automatically. No token, no auth code: ```html
``` Editing and deleting are one call each: ```js // update a record's data await fetch(`/_/collection/${ID}/records/${encodeURIComponent(key)}`, { method: 'PUT', headers: { 'content-type': 'application/json' }, body: JSON.stringify({ data: updated }) }) // delete a record await fetch(`/_/collection/${ID}/records/${encodeURIComponent(key)}`, { method: 'DELETE' }) ``` A PUT replaces the whole `data` object. If you are only changing some fields, read the current record first, merge your changes, and send the result back. ## Live updates (optional) To make a dashboard update itself as submissions arrive, subscribe to the live-sync stream and listen for `collection-record` events. Open the stream only after a successful owner load, so a visitor who lands on the page never tries to connect. ```js const es = new EventSource('/_/live-sync/stream?page-url=' + encodeURIComponent(location.href)) es.addEventListener('collection-record', (e) => { const { op, id, data, modifiedAt } = JSON.parse(e.data) // op is 'create', 'update', or 'delete'. Update your list in place. }) ``` ## Pausing and unmarking The folder menu also lets you **pause submissions** (the form starts returning a "not accepting" error) and **unmark** the collection (the form and dashboard stop working, but your files and records are kept, and you can re-mark anytime). If you hand out a form link, remember that the link is just the page's file URL. Renaming or moving the file, or unmarking the collection, breaks that link. The Collection ID itself never changes, but the page URL is whatever you have named the file. ## Working with the data elsewhere Records are ordinary JSON files in your `records/` folder, so anything else you build on Hyperclay can read them, and they sync to the desktop app like the rest of your files. The `extractData` and `applyData` helpers from [the JSON API](/docs/every-page-a-json-api) are a convenient way to move values between a form and a record object, but they are optional. A record is just JSON you control. --- # CMS Hyperclay has a built-in CMS that turns any page into something a non-technical person can edit. You describe what counts as content with a single tag, add one button, and clicking it slides in an editing sidebar. As the editor types, the changes are written straight back into the page, and saving the page writes them into the file. There is no database, no admin backend, and no separate content store. The page is the content. The mental model is a two-way loop with the page as the source of truth. The CMS reads a JSON object out of your page using rules you define, builds a form bound to that object, and writes every edit back onto the page as you make it. ## Turn it on The CMS ships in the `smooth-sailing` and `everything` presets of HyperclayJS, so on most apps it is already loaded. Use one of those presets: ```html ``` If you build a custom feature list instead of a preset, add `&features=hypercms`. ## Describe your content Add one rules tag to the page. It is a small JSON map from a field name to a CSS selector, and it tells the CMS what on the page is editable. Prefer not to hand-write this? See [Let AI add it for you](#let-ai-add-it-for-you) below. ```html

My Site

The tagline goes here

``` `data-rules-version` must be `"1"`. The selector grammar is small: | Rule | Reads / writes | |---|---| | `".title"` | the element's text | | `".price@data-cents"` | an attribute or property | | `"img@src"`, `"a@href"` | attributes | | `".agree@checked"` | a checkbox | | `".tag[]"` | a list of plain values (a scalar array) | | `[".post", { "heading": ".post-title" }]` | a list of cards (an object array) | | `{ "author": { "name": ".name" } }` | a nested group | ## Open the editor Add a button that calls `open()`. The CMS builds the form from your rules and mounts it as a sidebar. ```html ``` That is the entire integration. Every field in your rules becomes an input, and editing it updates the page live. ## What editors see Your button slides a panel in from the right. The page reflows to make room rather than covering content. The panel has a title, a close button, and a scrolling list of fields, one labeled control per rules field: | Content | Control | |---|---| | Text | Input; long text gets a resizable text area | | Attribute (price, link) | Input | | Checkbox | Checkbox or toggle switch | | Image, file | Upload widget with preview and button; a crop window opens after picking if the page requests one | | List | Stack of items: drag handle to reorder, remove button, add button at the bottom | Edits are live: typing updates the page instantly. Removing a list item confirms first. Nothing saves on its own. The close button keeps your edits; save with Cmd+S as usual. Closing clears `?cms=true` from the URL so reload or share does not reopen the editor. ## Editable lists For a list of repeating items, use the `[selector, shape]` form. The editor gets add, remove, and drag-to-reorder controls automatically. ```html
  • First post

    Hello world.

``` So that a list can grow from empty, mark a hidden seed element with `cms-template`. The CMS ignores it when reading and writing data, and clones it when the editor adds the first item. ```html
``` ## Saving, and what gets saved This is the important part. The CMS only changes the live page. It never saves on its own. You save the page the normal Hyperclay way, with Cmd+S or autosave, and that writes the current DOM into the `.html` file. The sidebar itself is never part of the saved file. It marks itself so the save system skips it, and the editing state is stripped on the way out, so the file on disk only ever contains your content. Open the saved file anywhere and it is just clean HTML with your latest edits baked in. ## Undo and live editing come for free Because the CMS edits the real page, the rest of the platform cooperates with it automatically: - **Undo** works on CMS edits. Each add, remove, and reorder is a labeled, undoable step, and Cmd+Z steps back through them. See [Undo and Redo](/docs/undo-and-redo). - **Live-sync** keeps the form fresh. If the page changes from another device or collaborator, the sidebar re-syncs to match, and it preserves whatever field you are currently typing in. ## Customize the form The default inputs are generated for you, so you usually write no form markup at all. When you want control over how a field or a card renders, add a `