AnyLog Dashboard Generation Guide
Overview
This guide explains how to ask an LLM (Claude) to generate an HTML dashboard that queries data from an AnyLog node. Four connection modes are supported:
| Mode | Description | Use When |
|---|---|---|
| Direct HTTP | Command embedded in the URL, called directly from the browser | Node is accessible over HTTP on the local network |
| Direct POST | AnyLog headers and command delivered as JSON in the POST body, called directly from the browser | Node is accessible over HTTP and POST |
| POST to Flask Proxy | Browser POSTs to a local Flask proxy which forwards to AnyLog using Mutual TLS | Node requires mTLS certificates or HTTPS |
| CLI | Returns the native AnyLog command string for manual testing | Verifying a query before building a dashboard |
How to Ask for a Dashboard
Minimum Required Information
Every dashboard request must include all the following:
| Information | Why It’s Needed | Example |
|---|---|---|
| Connection type | Determines how the dashboard calls AnyLog | direct HTTP, direct POST, or Flask proxy |
| Node address | The IP and port of the AnyLog node | 24.5.219.50:7849 |
| Database name | The AnyLog database (dbms) to query | agg_anotherpeak |
| Table name | The table to query | battery_pack_logs_gcurrent |
| What data to show | The SQL query intent | last 10 rows |
| Response format | Tells the LLM how to parse the response | json:list |
| Editable node | Whether the user can change the node at runtime | yes / no |
Prompt Template
Create a client-side HTML dashboard that connects directly to an AnyLog node at <IP>:<PORT>.
Response formats:
For data queries, the AnyLog response is in json:list format, meaning an array of JSON objects.
For metadata queries (for example, UNS queries), the response is a list of JSON objects.
Requirements:
1) The dashboard must allow the user to edit the AnyLog node address (IP:PORT) in the UI.
2) Prefer an increment query over a SQL query whenever the requested data can be retrieved that way.
3) If multiple values or projections can be retrieved in one SELECT, use a single statement instead of one statement per field.
4) Log every request sent to AnyLog and every response received in a section of the dashboard.
5) If a request fails, display in a section of the dashboard:
a. the full cURL equivalent of the request,
b. the returned error value,
c. the returned error message.
Generate the full dashboard code and include the AnyLog request construction and response-handling logic.
Recommended Workflow — Test Before You Build
Before building a dashboard, verify the query works by testing it step by step.
Step 1 — Test on the AnyLog CLI
Ask the LLM for the native CLI command and paste it directly into the AnyLog CLI:
Show me the AnyLog CLI command to query the last 10 rows from dbms agg_anotherpeak
and table battery_pack_logs_gcurrent.
Returns:
sql agg_anotherpeak format = json:list and stat = false SELECT * FROM battery_pack_logs_gcurrent ORDER BY timestamp DESC LIMIT 10
Other CLI examples:
| What to say | CLI command returned |
|---|---|
"Show me the CLI command to get node status" |
get status where format = mcp |
"Show me the CLI command to list all tables in dbms agg_anotherpeak" |
blockchain get (table) where dbms = agg_anotherpeak bring.json.unique [*][name] |
"Show me the CLI command to count rows in battery_pack_logs_gcurrent" |
sql agg_anotherpeak format = json:list and stat = false SELECT COUNT(*) FROM battery_pack_logs_gcurrent |
Step 2 — Verify via HTTP in the browser
Ask the LLM for the HTTP URL and paste it into a browser address bar to confirm the response:
Show me the HTTP URL to query the last 10 rows from dbms agg_anotherpeak
and table battery_pack_logs_gcurrent against node 24.5.219.50:7849.
Step 3 — Build the dashboard
Once the query is confirmed to return the right data, ask for the dashboard using one of the connection types below.
Connection Types
1. Direct HTTP
The browser calls the AnyLog node directly. The AnyLog headers and command are embedded in the URL as query parameters.
- Say: “use a direct HTTP call”
URL format:
http://<IP>:<PORT>/?User-Agent=AnyLog/1.23?destination=network?command=<command>
JavaScript fetch call:
const cmd = `sql agg_anotherpeak format = json:list and stat = false SELECT * FROM battery_pack_logs_gcurrent ORDER BY timestamp DESC LIMIT 10`;
const url = `http://24.5.219.50:7849/?User-Agent=AnyLog/1.23?destination=network?command=${encodeURIComponent(cmd)}`;
const res = await fetch(url);
const text = await res.text();
const rows = JSON.parse('[' + text.trim().replace(/,\s*$/, '') + ']');
Example prompt:
Create an HTML dashboard using a direct HTTP call to AnyLog node 24.5.219.50:7849.
Show the last 10 rows from dbms agg_anotherpeak and table battery_pack_logs_gcurrent.
The response is in json:list format.
Allow the user to change the node address.
2. Direct POST to AnyLog
The browser sends a POST request directly to the AnyLog node. The AnyLog headers and command are delivered as a JSON object in the message body. No proxy is needed.
- Say: “use a direct POST to AnyLog”
POST body format:
{
"User-Agent": "AnyLog/1.23",
"destination": "network",
"command": "sql agg_anotherpeak format = json:list and stat = false SELECT * FROM battery_pack_logs_gcurrent ORDER BY timestamp DESC LIMIT 10"
}
JavaScript fetch call:
const res = await fetch("http://24.5.219.50:7849", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
"User-Agent": "AnyLog/1.23",
"destination": "network",
"command": "sql agg_anotherpeak format = json:list and stat = false SELECT * FROM battery_pack_logs_gcurrent ORDER BY timestamp DESC LIMIT 10"
})
});
const text = await res.text();
const rows = JSON.parse('[' + text.trim().replace(/,\s*$/, '') + ']');
Important: The node URL must include the scheme —
http://orhttps://. A bareIP:PORTwithout a scheme will cause anInvalidSchemaerror.
Example prompt:
Create an HTML dashboard using a direct POST to AnyLog node 24.5.219.50:7849.
Show the last 10 rows from dbms agg_anotherpeak and table battery_pack_logs_gcurrent.
The response is in json:list format.
Allow the user to change the node address.
3. POST to Flask Proxy (anylog_proxy.py)
The browser POSTs to a local Flask proxy (anylog_proxy.py), which holds the mTLS certificates and forwards the request to the AnyLog node over HTTPS. The proxy is not generated by the LLM — it must already be running before the dashboard is opened.
- Say: “use the AnyLog Flask proxy”
Starting the proxy
pip install flask flask-cors requests
python anylog_proxy.py \
--cert /path/to/server-acme-inc-public-key.crt \
--key /path/to/server-acme-inc-private-key.key \
--cacert /path/to/ca-anylog-public-key.crt \
--port 5000
The proxy runs at http://localhost:5000 by default.
How the proxy works
The proxy exposes a single endpoint — POST /api/query — that:
- Accepts a JSON body containing the node URL and the full AnyLog headers and command
- Forwards the request to the AnyLog node using the mTLS certificates
- Returns the parsed JSON response to the dashboard
POST body sent from the dashboard to the proxy
{
"url": "https://24.5.219.50:7849",
"User-Agent": "AnyLog/1.23",
"destination": "network",
"command": "sql agg_anotherpeak format = json:list and stat = false SELECT * FROM battery_pack_logs_gcurrent ORDER BY timestamp DESC LIMIT 10"
}
Important: The
urlfield must include the scheme —http://orhttps://. A bareIP:PORTwithout a scheme will cause anInvalidSchemaerror in the proxy.
JavaScript fetch call:
const PROXY = 'http://localhost:5000';
const NODE = 'https://24.5.219.50:7849'; // must include https://
const command = 'sql agg_anotherpeak format = json:list and stat = false SELECT * FROM battery_pack_logs_gcurrent ORDER BY timestamp DESC LIMIT 10';
const res = await fetch(`${PROXY}/api/query`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
url: NODE,
"User-Agent": "AnyLog/1.23",
destination: "network",
command: command
})
});
const data = await res.json();
const rows = Array.isArray(data) ? data : (data.raw ? [] : [data]);
Note: The proxy parses the AnyLog response and returns it as JSON — the dashboard does not need to handle raw text parsing.
Proxy health check
GET http://localhost:5000/api/health
{
"status": "ok",
"cert": "/path/to/cert.crt",
"key": "/path/to/key.key",
"cacert": "/path/to/ca.crt"
}
Example prompt
Create an HTML dashboard using the AnyLog Flask proxy at http://localhost:5000.
The AnyLog node is at https://24.5.219.50:7849.
Show the last 10 rows from dbms agg_anotherpeak and table battery_pack_logs_gcurrent.
The response is in json:list format.
Allow the user to change both the proxy address and the node address.
4. CLI Only
Returns the native AnyLog command string for manual execution on the node CLI. Used for testing before building a dashboard — see the Recommended Workflow section above.
- Say: “show me the AnyLog CLI command”
AnyLog Response Format
AnyLog SQL queries using format = json:list return rows as JSON objects separated by commas and newlines, wrapped in [ ]:
[{"row_id": 11, "timestamp": "2026-03-11 21:27:41", "avg_val": -0.125, "events": 8},
{"row_id": 10, "timestamp": "2026-03-11 21:26:32", "avg_val": -0.125, "events": 8},
{"row_id": 9, "timestamp": "2026-03-11 21:25:24", "avg_val": -0.125, "events": 8}]
Direct HTTP and Direct POST dashboards must read the response as text and parse manually:
const text = await res.text();
const rows = JSON.parse('[' + text.trim().replace(/,\s*$/, '') + ']');
Flask proxy dashboards receive already-parsed JSON from the proxy — no manual text parsing needed.
Always include "json:list format" in your prompt so the LLM generates the correct parsing logic.
Optional Dashboard Features
| Feature | What to say |
|---|---|
| Editable node address | "allow the user to change the node address" |
| Editable proxy address | "allow the user to change the proxy address" |
| Auto-refresh | "auto-refresh every 30 seconds" |
| Debug panel | "include a debug panel showing the request sent, the raw response, and any errors" |
| Summary statistics | "show summary statistics above the table" |
| Specific columns only | "show only the timestamp, avg_val and events columns" |
| Time filter | "show data from the last 24 hours" |
| Multiple tables | "show data from table A and table B side by side" |
Common Mistakes and How to Avoid Them
Query returns wrong data or no data
Cause: The SQL query or dbms/table names are wrong.
Fix: Always test with the CLI command first. Ask "Show me the AnyLog CLI command for <your query>", run it on the CLI, and confirm data is returned before asking for the dashboard.
Direct HTTP or POST dashboard fails to parse the response
Cause: The LLM used res.json() directly, which fails because AnyLog’s json:list response has leading whitespace or non-standard formatting.
Fix: Always mention "json:list format" in the prompt so the LLM reads the response as text first and wraps it in [ ] before parsing.
Node address is hardcoded and cannot be changed
Cause: The LLM hardcoded the node address without making it editable.
Fix: Always include "allow the user to change the node address" in your prompt.
Flask proxy returns 405 Method Not Allowed
Cause: The dashboard is POSTing to the wrong URL on the proxy — e.g. POST / instead of POST /api/query. The proxy root / only handles GET requests (it serves the dashboard HTML page).
Fix: Specify "use the AnyLog Flask proxy" in your prompt. The proxy endpoint is always POST /api/query. Verify the dashboard is calling the correct endpoint with the full body:
{
"url": "https://<node>",
"User-Agent": "AnyLog/1.23",
"destination": "network",
"command": "<anylog command>"
}
Flask proxy returns InvalidSchema error
Cause: The url field in the POST body is missing the scheme — e.g. 24.5.219.50:7849 instead of https://24.5.219.50:7849. The Python requests library requires a full URL with http:// or https://.
Fix: Always include the scheme in the node URL. The dashboard should ensure it before sending:
const nodeURL = node.startsWith('http') ? node : `https://${node}`;
The same applies to the Direct POST mode — the fetch URL must also include http:// or https://.
Dashboard shows an error but it’s unclear why
Cause: No visibility into what was sent or received.
Fix: Add "include a debug panel" to your prompt. The debug panel shows the exact URL or POST body sent, the raw response received, the parse result, and the full error message — making it straightforward to identify the failure point.
Full Example Prompts
Step 1 — Test on CLI
Show me the AnyLog CLI command to query the last 10 rows from dbms agg_anotherpeak
and table battery_pack_logs_gcurrent.
Step 2 — Verify in browser
Show me the HTTP URL to query the last 10 rows from dbms agg_anotherpeak
and table battery_pack_logs_gcurrent against node 24.5.219.50:7849.
Step 3a — Direct HTTP dashboard
Create an HTML dashboard using a direct HTTP call to AnyLog node 24.5.219.50:7849.
Show the last 10 rows from dbms agg_anotherpeak and table battery_pack_logs_gcurrent.
The response is in json:list format.
Allow the user to change the node address.
Include a debug panel showing the URL sent, the raw response, and any errors.
Step 3b — Direct POST dashboard
Create an HTML dashboard using a direct POST to AnyLog node 24.5.219.50:7849.
Show the last 10 rows from dbms agg_anotherpeak and table battery_pack_logs_gcurrent.
The response is in json:list format.
Allow the user to change the node address.
Include a debug panel showing the POST body sent, the raw response, and any errors.
Step 3c — Flask proxy dashboard
Create an HTML dashboard using the AnyLog Flask proxy at http://localhost:5000.
The AnyLog node is at https://24.5.219.50:7849.
Show the last 10 rows from dbms agg_anotherpeak and table battery_pack_logs_gcurrent.
The response is in json:list format.
Allow the user to change both the proxy address and the node address.
Include a debug panel showing the POST body sent to the proxy, the raw response, and any errors.
Quick Reference Card
✅ Recommended workflow:
1. Ask for the CLI command → test on AnyLog CLI
2. Ask for the HTTP URL → verify in a browser
3. Ask for the dashboard → build with confidence
✅ Always specify in the prompt:
- Connection type: "direct HTTP", "direct POST", or "Flask proxy"
- Node address: IP:PORT (e.g. 24.5.219.50:7849)
- Database: dbms name
- Table: table name
- Query: what data to show
- Format: "json:list format"
- Editable node: "allow the user to change the node address"
✅ For Flask proxy, also specify:
- Proxy address: e.g. http://localhost:5000
- "allow the user to change the proxy address"
✅ Node URL scheme rules (applies to all POST modes):
- The node URL must always include http:// or https://
- A bare IP:PORT without a scheme causes an InvalidSchema error
- Dashboard: const nodeURL = node.startsWith('http') ? node : `https://${node}`;
✅ POST body — Direct POST to AnyLog:
{
"User-Agent": "AnyLog/1.23",
"destination": "network",
"command": "<anylog command>"
}
✅ POST body — Flask proxy (POST /api/query):
{
"url": "https://<node>", ← must include http:// or https://
"User-Agent": "AnyLog/1.23",
"destination": "network",
"command": "<anylog command>"
}
✅ Proxy health check: GET http://localhost:5000/api/health
✅ Recommended additions:
- "include a debug panel" — makes failures easy to diagnose
- "auto-refresh every N seconds" — for live data monitoring