# 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 =>
`
```
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
Modal content
Item C
Item A
Item B
```
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