Communication

This page describes Sercrod network and file communication directives: *fetch, *post, *api, *upload, *download, *response, and *into.

For WebSocket behavior, see WebSocket.

Common Concepts

Response Destinations

*response is the common placement directive for parsed HTTP/upload responses, loaded values, adapter results, and WebSocket messages. Every successful communication response is also mirrored to $response.

<button type="button" *api="/api/contact.php" method="POST" body="form" *response="'result'">
    Send
</button>

*into remains available as a compatibility alias for simple whole-result placement. New HTTP, load, adapter, and WebSocket examples should use *response.

*download is side-effecting and reports through events instead of writing to host data.

JSON Parsing

For HTTP responses, Sercrod checks the response Content-Type. JSON responses are parsed as JSON. Non-JSON responses are kept as text or Blob-like values depending on the directive.

Trigger Timing

Network directives can behave differently depending on the element they are attached to.

On non-clickable elements, *fetch and GET-style *api are commonly used for initial loading.

<serc-rod data='{"items":[]}' *fetch="/api/items.json" *response="'items'">
    <ul>
        <li *for="item of items">%item.title%</li>
    </ul>
</serc-rod>

On clickable elements, the request runs when the user activates the element.

<serc-rod data='{"items":[]}'>
    <button type="button" *fetch="/api/items.json" *response="'items'">
        Load items
    </button>
</serc-rod>

Clickable triggers include:

For *fetch, input[type=image] is also treated as clickable.

role="button" and tabindex="0" do not make a non-clickable element click-triggered for *fetch or *api. For styled controls, put the directive on a real trigger element and use surrounding markup only as decoration:

<p class="load-control">
    <button type="button" *fetch="/api/items.json" *response="'items'">
        Load items
    </button>
</p>

*fetch

*fetch is the simple JSON loading directive. Use *response to choose where the parsed JSON is written.

<serc-rod data='{"items":[]}' *fetch="/api/examples/items.json" *response="'items'">
    <h2>Items from the server</h2>
    <ul>
        <li *for="item of items">%item%</li>
    </ul>
</serc-rod>

When the host is connected, Sercrod fetches the JSON, assigns it to data.items through *response, and re-renders.

Use *fetch for simple GET-style JSON loading.

*post

*post sends host data, or staged data when present, as JSON to the given URL.

<serc-rod data='{"name":"", "email":"", "message":""}'>
    <label>
        Name:
        <input type="text" *input="name" *lazy>
    </label>

    <label>
        Email:
        <input type="email" *input="email" *lazy>
    </label>

    <label>
        Message:
        <textarea *input="message" *lazy></textarea>
    </label>

    <button type="button" *post="/api/contact-demo">
        Send as JSON
    </button>
</serc-rod>

The request uses Content-Type: application/json and sends a Sercrod request envelope with sercrod, data, and params fields. The JSON response is parsed when possible, mirrored to $response, and written to normal data only when *response or its *into alias asks for it.

Use *lazy on form fields when the user is expected to type and then click the submit button. See Input Timing.

*api

*api is the more general HTTP directive.

It supports:

<serc-rod data='{"form":{"email":"","message":""},"result":null}'>
    <input type="email" *input="form.email" *lazy>
    <textarea *input="form.message" *lazy></textarea>

    <button
        type="button"
        *api="/api/contact.php"
        method="POST"
        body="form"
        *response="'result'"
    >Send</button>

    <p *if="result" *print="result.message"></p>
</serc-rod>

Use *api when the request behaves like an API operation and needs options beyond simple JSON loading.

Frontend And Server Response Contract

Sercrod attributes define where a server response will be stored. The server response shape must match the template paths that read it.

<serc-rod data='{"form":{"email":"","message":""},"result":null}'>
    <input type="email" *input="form.email">
    <textarea *input="form.message"></textarea>

    <button
        type="button"
        *api="/api/contact.php"
        method="POST"
        body="form"
        *response="'result'"
    >Send</button>

    <p *if="result" *print="result.message"></p>
</serc-rod>

Because the template reads result.message, the server should return an object with a message key.

{
    "ok": true,
    "message": "Submission received.",
    "errors": [],
    "received": {
        "email": "user@example.com",
        "message": "Hello"
    }
}

The response root is part of the contract. If the server returns a bare array, or renames message, the template no longer matches the response.

With *fetch="/api/items.json" *response="'items'", the response is stored in items. If the template uses *for="item of items", items must be the array expected by the template.

Integration Example: Push Registration

The standard push path does not need a separate *api button. Declare the application registration endpoint on *push:

<p *push="/api/push"></p>
<button *if="$push && $push.needs_action" *push.register>
  Enable notifications
</button>

The application endpoint receives { action, registration }. The normalized registration includes platform, provider, and token. Repeated register requests must be safe, and unregister uses the same endpoint with action: "unregister".

Sercrod does not provide the application server, token database, provider account, FCM/APNs server credentials, service-account private keys, APNs private keys, or production notification policy. Real provider credentials belong only in the application operator's private server environment.

File Upload

*upload turns an element into an upload trigger. The value resolves to an upload target or upload options object.

The runtime dispatches:

Successful results are mirrored to $response and written to normal data only when *response or its *into alias asks for it.

File Download

*download turns an element into a download trigger. The value resolves to a download target or download options object.

The runtime dispatches:

Successful *download operations do not write to $response, *response, or *into targets. Listen for sercrod-downloaded to react to the operation.

Runtime Events

HTTP and file directives dispatch runtime CustomEvent hooks that can be observed by integrations.

HTTP/API:

File transfer:

Data observation:

sercrod-ready is dispatched once from each host after its first completed update() cycle. Its detail includes host, ready: true, and initial: true. The same host's JavaScript-only ready property is also true at that point.

sercrod-change is a runtime notification and inspection hook for users and external code. It is not Sercrod's render scheduler and must not be treated as Proxy-based rendering reactivity. Its detail includes the host, parent object, changed key, old value, and new value when such a change is reported.