Docs
Read and write your file as JSON
Add a rules tag to read parts of your HTML file as JSON and post changes back from a program on your computer.
Let's say your file is a task list that has a heading and two tasks. A program on your computer can read the heading and tasks as JSON and write new ones back.
The file holds the data. A rules tag maps CSS selectors to JSON keys. HTML Clay reads the matching parts of the file and returns their values. To write, send JSON with the same keys. HTML Clay writes each value into the part of the file its rule selects and saves a version. Open tabs pick up the change through the ClayJS sync plugin.
The page shows this list:
Today
1. Buy milk
2. Book ticketsA request to /_/api/todo.htmlclay returns these values. Responses here are formatted for reading:
{
"title": "Today",
"items": ["Buy milk", "Book tickets"]
}You need HTML Clay running on macOS, Linux or Windows. The terminal examples use curl in Bash or Zsh. On Windows, use a Bash terminal for these commands. If you have not opened an HTML Clay file yet, start with Get started.
Add the rules tag
Two rules give the file its JSON shape: title reads the heading, and items reads the tasks.
Save this as todo.htmlclay in your home folder, then open it with HTML Clay:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Tasks</title>
<script type="application/json" data-rules-name="api" data-rules-version="1">
{
"title": "h1",
"items": ".todo[]"
}
</script>
</head>
<body>
<h1>Today</h1>
<ol>
<li class="todo" data-done="no">Buy milk</li>
<li class="todo" data-done="no">Book tickets</li>
</ol>
<script src="https://clayjs.com/v1/clay.js?plugins=sync"></script>
</body>
</html>/_/api/ reads the tag named api. The [] collects every matching task's text. The ClayJS script enables live updates.
Read the file
The read returns the JSON shown above. Replace PORT with the port in your open tab's address. Your tab's address looks like http://127.0.0.1:PORT/todo.htmlclay. Put /_/api/ between the port and the file name.
Run this in your terminal:
base='http://127.0.0.1:PORT'
api="$base/_/api/todo.htmlclay"
curl "$api"Keep that terminal open for the following examples.
To pass the rules in the request instead of using the tag, ask for just the heading:
curl --get "$base/todo.htmlclay" \
--data-urlencode 'data={"title":"h1"}'The data parameter carries the rules, which curl encodes for the URL. The response contains only title:
{"title":"Today"}Write changes back
The next request changes the heading to "Tomorrow" and the first task to "Buy bread".
A key you leave out is left alone. An array you send becomes the whole list: a task missing from it is removed, and a new task is a copy of the first task's element, with your text inside it. Keep at least one task in the list because once the list is empty, a write cannot add tasks back. New text replaces what was inside the selected element. Each write that changes the file is saved as a version.
Send JSON with the same shape as the read:
curl "$api" \
-H 'Content-Type: application/json' \
--data '{"title":"Tomorrow","items":["Buy bread","Book tickets"]}'The --data option makes this a POST. HTML Clay returns the updated values:
{
"title": "Tomorrow",
"items": ["Buy bread", "Book tickets"]
}Open todo.htmlclay in your text editor. The heading now contains Tomorrow, and the first task contains Buy bread. The open tab updates too.
Writes reach only the elements the rules tag selects, and only their content. They cannot write scripts, styles or event handlers. HTML you send is saved as plain text. A key the rules tag does not define causes a 400 response. Keep the JSON body under 1 MB.
Write only if the file is unchanged
Change the second task only if the file still matches your read. First, read with response headers:
curl -i "$api"The Etag header identifies the file you read. Its value looks like this:
Etag: 8f02c16e7b4d9a30Replace the sample value below with your exact Etag, then change the second task:
curl "$api" \
-H 'Content-Type: application/json' \
-H 'If-Match: 8f02c16e7b4d9a30' \
--data '{"title":"Tomorrow","items":["Buy bread","Book train tickets"]}'If the file still matches, the response shows the changed task:
{
"title": "Tomorrow",
"items": ["Buy bread", "Book train tickets"]
}If the file has changed, HTML Clay returns 412 and writes nothing. Read the file again before deciding what to send. Without If-Match, the write skips this check.
Rules reference
Each rule selects a value from the file. These forms work in the rules tag or data parameter:
| Form | Example | Value read |
|---|---|---|
sel |
"h1" |
Text of the first match |
sel[] |
".todo[]" |
Text of every match, as an array |
sel@attr |
".todo@data-done" |
An attribute on the first match |
[sel, {...}] |
[".todo", {"text": ".", "done": "@data-done"}] |
One object per match |
To read text and completion together, replace the rules tag's contents:
{
"title": "h1",
"items": [".todo", {"text": ".", "done": "@data-done"}]
}Inside each task, . reads its text and @data-done reads its attribute. The next read returns:
{
"title": "Tomorrow",
"items": [
{"text": "Buy bread", "done": "no"},
{"text": "Book train tickets", "done": "no"}
]
}Use that object shape for subsequent writes too. To mark the first task done, send this body:
{
"items": [
{"text": "Buy bread", "done": "yes"},
{"text": "Book train tickets", "done": "no"}
]
}Who can read and write
A program on your computer can read and write through this API. If you can open the page in your browser, you can read it through the API.
A trusted folder is one you have allowed HTML Clay to save files in. Writes require an opened file or a .htmlclay file in a trusted folder.
A save token is the identifier HTML Clay gives a page to let it save its file. A browser page sends the target file's token in a Save-Token header. A program on your computer needs no token.
Other websites cannot read the API through your browser. HTML Clay sends no CORS permission headers and refuses requests from other websites that try to write. A page HTML Clay serves on the same port can read it.
Troubleshooting
400for an unknown key: the key is not in the rules tag. Use a key the tag defines.403on a write: open the file in HTML Clay or put it in a trusted folder. A browser request also needs the file's save token.412on a write: read the latest file, then revise your change and retry with its newEtag.- The file changed but the tab did not: check that the ClayJS script loads the
syncplugin.
Where next
For how open tabs receive file changes, see Live updates. To send a request from the page to a program, see Programs. Agent editing walks through attaching a program from your terminal. The wire protocol reference covers that connection in detail.