📟 Hypernet
Hyperapp

App

The agent surface of a Hyperapp — a self-describing HTML application that exposes capabilities to agents through links and forms.

The app facet is a Hyperapp's agent surface — the facet the agent uses. This document specifies it.

1. Purpose

The app facet is a self-describing HTML application.

It exposes capabilities through links and forms.

Humans interact with the rendered page. Agents interact with the same page through its structure.

The page itself is the interface.

2. Design Principles

Shared Surface

A Hyperapp is built agent-first: one page exposes the same capabilities to humans and agents, with its important actions, inputs, outputs, and navigation present in the document itself.

It carries no styling — no CSS, no design layer. Yet the same plain HTML still renders as an ordinary, interactive page for a human: links are clickable, forms are fillable and submittable. The human keeps a basic, usable interaction while the agent reads the same structure — neither audience needs a surface of its own.

One surface, two representations: a human gets the rendered HTML; an agent gets the same page as Markdown, served by content negotiation (section 13). The capabilities are identical; only the representation differs.

HTML

A Hyperapp is ordinary HTML. Its capabilities are expressed with standard elements — links and forms — not a proprietary format or a required framework.

It should remain understandable when read as raw HTML, rendered in a browser, or converted to Markdown.

Capability Preservation

A Hyperapp conversion must preserve capabilities.

Links and forms must survive conversion between HTML, Markdown, and other textual representations.

Capabilities are discovered through links.

Humans and agents navigate by following links rather than relying on out-of-band documentation.

The entry point of a Hyperapp is a Directory Page: a root page from which every capability is reachable by following links (see 5.1).

3. Core Concepts

A Hyperapp exposes capabilities through three primary mechanisms:

Links provide navigation and discovery.

Actions

Actions provide execution.

Actions are represented by HTML forms.

A form is the canonical HTML representation of an Action.

An Action is the canonical semantic representation of a form.

Response Pages

Every Action submission MUST return a Response Page.

A Response Page is a Hyperapp page describing the result or current state of an Action submission.

4. Hyperapp Page Metadata

A Hyperapp page MAY include metadata in the HTML <head>.

Recommended metadata:

<meta name="hyperapp:type" content="app" />
<meta name="hyperapp:app" content="Slides" />
<meta name="hyperapp:origin" content="https://example.com" />

hyperapp:origin records the page's base URL so that relative links and Action targets remain resolvable after conversion to Markdown (see URL Resolution in section 6).

Known hyperapp:type values:

  • app
  • action-response
  • embedded-view (a human-only page, not a Hyperapp page; see section 12.1)

Metadata keys

The complete set of hyperapp metadata keys:

keymeaningapplies torequired
hyperapp:appname of the app the page belongs toall pagesrequired on Response Pages; recommended elsewhere
hyperapp:typepage type (app/action-response/embedded-view)all pagesrequired on Response Pages; recommended elsewhere
hyperapp:actionname of the Action a Response Page reportsResponse Pagesrequired on Response Pages
hyperapp:statusoutcome of the Action submissionResponse Pagesrequired on Response Pages
hyperapp:originthe page's base URL for resolving relative referencesall pagesrequired in Markdown when relative references are kept (see section 6)

5. Page Structure

Every Hyperapp page MUST have a <title> in its <head>. A visible heading (<h1>) is optional but recommended.

Beyond the title, a Hyperapp page SHOULD contain:

  • a description
  • a heading
  • links
  • actions, if the page exposes executable capabilities

A title, a description, and at least one link or Action are required for conformance; see section 16. The remaining items are recommended.

The example below is the Create page — a capability page that exposes an Action. The app's root page is a Directory Page (see 5.1).

<!doctype html>
<html>
  <head>
    <title>Create</title>
    <meta name="hyperapp:type" content="app" />
    <meta name="hyperapp:app" content="Slides" />
  </head>
  <body>
    <h1>Create</h1>
    <p>Create a slide deck from markdown.</p>
    <h2>Links</h2>
    <ul>
      <li><a href="/templates">Templates</a></li>
      <li><a href="/themes">Themes</a></li>
    </ul>
    <h2>Actions</h2>
    <form method="post" name="create-a-deck" action="/slides/create">
      <fieldset>
        <legend>Create a deck</legend>
        <p>
          <label for="markdown">markdown</label><br />
          <textarea id="markdown" name="markdown" required></textarea>
        </p>
        <p>
          <label for="name">name</label><br />
          <input id="name" name="name" type="text" required />
        </p>
        <button type="submit">Create deck</button>
      </fieldset>
    </form>
  </body>
</html>

5.1 Directory Page

The root page of a Hyperapp MUST be a Directory Page.

A Directory Page introduces the Hyperapp and links to its pages. The linked pages belong to the same app: they are the other pages of this Hyperapp, and carry the same hyperapp:app value.

A Directory Page consists primarily of links. It exposes capabilities by linking to the pages that hold them, rather than by inlining Actions; the Create page in section 5, for example, is reached from the directory below.

A Directory Page is an app page and carries hyperapp:type set to app.

<!doctype html>
<html>
  <head>
    <title>Slides</title>
    <meta name="hyperapp:type" content="app" />
    <meta name="hyperapp:app" content="Slides" />
    <meta name="hyperapp:origin" content="https://example.com" />
  </head>
  <body>
    <h1>Slides</h1>
    <p>Create, manage, and export slide decks.</p>
    <h2>Pages</h2>
    <ul>
      <li><a href="/create">Create</a></li>
      <li><a href="/templates">Templates</a></li>
      <li><a href="/themes">Themes</a></li>
      <li><a href="/recent">Recent Decks</a></li>
    </ul>
  </body>
</html>

Links represent navigation and discovery.

A link may point to:

  • another Hyperapp page
  • a generated artifact
  • documentation
  • a sub-capability
  • a status page
  • a result page

Example:

<a href="/slides">Slides</a>

Markdown conversion (resolved against the document origin):

[Slides](https://example.com/slides)

Links MUST survive conversion to Markdown, and MUST remain resolvable afterwards.

URL Resolution

A link href or an Action target MAY be relative within an HTML page, because the page has an origin.

Markdown has no origin. A conforming Markdown conversion MUST therefore either:

  • rewrite every link and Action target to an absolute URL, or
  • record the source document's base URL as hyperapp:origin in frontmatter, so that relative references remain resolvable against it.

A relative reference with no recorded origin is non-conforming.

7. Actions

Actions are represented by HTML forms.

An Action defines:

  • title and name
  • method
  • target
  • inputs
  • submit control

Example:

<form method="post" name="create-a-deck" action="/slides/create">
  <fieldset>
    <legend>Create a deck</legend>
    <textarea name="markdown" required></textarea>
    <input name="name" type="text" required />
    <button type="submit">Create deck</button>
  </fieldset>
</form>

Action semantics:

  • Title: Create a deck
  • Name: create-a-deck
  • Method: POST
  • Target: /slides/create
  • Inputs: markdown, name

An Action has a title and a name.

The title is the form's caption — its <legend> — the human-readable phrase shown to people. It heads the Action's ## Action: <title> Markdown block, and it MAY be localized.

The name is the Action's stable reference key — the <form> element's name attribute. The hyperapp:action of a Response Page that reports the Action (section 10), and any input that names it as a source (section 8), refer to this name; the Markdown block carries it as a name: line so an agent can resolve those references. Because the name is not displayed, it need not read as a phrase — keep it stable while the title varies.

<form method="post" name="create-a-deck" action="/slides/create">
  <fieldset>
    <legend>New Presentation</legend>
    <!-- inputs and submit control -->
  </fieldset>
</form>

A person sees the title New Presentation; the hyperapp:action and any source use the name create-a-deck. In Markdown the Action reads:

## Action: New Presentation

- name: `create-a-deck`
- method: POST
- target: `/slides/create`

Every Action MUST define:

  • a title (the <legend> caption)
  • a name (the <form> name attribute)
  • method
  • target
  • at least one named input
  • submit control

For-agent and for-human Actions

An Action's method says how it is submitted, and with that, who supplies its inputs:

  • post (or get) — a for-agent Action: the agent fills the Inputs and submits them. Its Markdown carries the Inputs, because the agent fills them.
  • dialog — a for-human Action: a person fills the Inputs, not the agent. It is the standard HTML <form method="dialog">, submitted through the surrounding UI; here that UI is a Hyperform (section 12.2) — the host renders the Action's declared Inputs (section 8) as a form for the human and submits it on the agent's behalf. The agent opens the Action and waits for the result, a Response Page (section 10) carrying the human's input. Because the human fills it, the agent-facing Markdown omits the Inputs.

A for-human Action exists because a for-agent Action sometimes needs input only a human can give (a subjective choice, an approval, a credential). The app author writes a for-human Action to collect that input and feed it to the for-agent Action. The for-agent Action declares the link: the input that needs it names the for-human Action as its source (section 8), which makes running that for-human Action a required prior step. A flow is therefore a hybrid of for-agent and for-human Actions: the agent opens the for-human Action (the human fills it), then submits the for-agent Action with the result. The Hyperform — how the host renders the form and resolves the wait — is specified with the Hyperblocks (section 12.2).

8. Inputs

Every input MUST have:

  • name
  • type

Inputs SHOULD have:

  • visible label
  • description
  • validation constraints

Example:

<label for="name">name</label>
<input id="name" name="name" type="text" required />

Supported input types include:

  • text
  • textarea
  • number
  • email
  • url
  • checkbox
  • radio
  • select
  • file
  • hidden

Input Values

An input MAY carry a value.

A hidden input almost always carries a value, and that value is part of the Action's capability. Agents MUST submit hidden inputs with their given values.

For select, radio, and checkbox inputs, the available options and their submitted values MUST be discoverable from the page, so that an agent can choose a valid value.

Example:

<label for="theme">theme</label>
<select id="theme" name="theme">
  <option value="default" selected>Default</option>
  <option value="gaia">Gaia</option>
</select>

Agents SHOULD treat input names as stable parameter identifiers.

Input Source

An input MAY declare a source: the name of an Action whose result supplies its value. The agent obtains the value by running that Action and reading the like-named entry from its Results (section 11), then submitting it here.

A required input with a source names a required prior step — the agent runs the source Action before submitting this one. This is how a for-agent Action depends on a for-human Action (section 7): the input that needs human-supplied data declares the for-human Action as its source.

In HTML the source is a data-source attribute on the input, valued with the source Action's name. In Markdown it is a source column in the Inputs table.

Example:

<label for="preferences">preferences</label>
<input id="preferences" name="preferences" type="text" data-source="Preferences" required />

Markdown conversion:

### Inputs

| name        | type | required | source      |
| ----------- | ---- | -------- | ----------- |
| preferences | text | yes      | Preferences |

9. Action Submission

Submitting an Action MUST return an HTML Response Page.

An Action MUST NOT return only raw JSON as the primary response.

The Response Page may represent:

  • success
  • processing
  • failure

The client or agent should inspect the Response Page to determine the next step.

10. Response Pages

A Response Page is an HTML Hyperapp page returned after an Action submission. It describes the result or current state of that submission.

Every Response Page has the same structure:

  • Head metadatahyperapp:type, hyperapp:app, hyperapp:action, and hyperapp:status (required; below).
  • A title — the page's <title>, naming the outcome.
  • A description — a short, human-readable statement of what happened.
  • An outcome body — at least one of Results, Links, or Actions (a follow-up or retry).

A Response Page MUST include the following metadata in <head>:

<meta name="hyperapp:type" content="action-response" />
<meta name="hyperapp:app" content="..." />
<meta name="hyperapp:action" content="..." />
<meta name="hyperapp:status" content="success|processing|failed|cancelled" />

Allowed hyperapp:status values:

  • success
  • processing
  • failed
  • cancelled

10.1 Success

A success Response Page means the Action completed.

It SHOULD expose the final outputs — as Results or Links.

<!doctype html>
<html>
  <head>
    <title>Deck Created</title>
    <meta name="hyperapp:type" content="action-response" />
    <meta name="hyperapp:app" content="Slides" />
    <meta name="hyperapp:action" content="create-a-deck" />
    <meta name="hyperapp:status" content="success" />
  </head>
  <body>
    <h1>Deck Created</h1>
    <p>The slide deck was created successfully.</p>
    <h2>Links</h2>
    <ul>
      <li><a href="/files/deck.html">Preview Deck</a></li>
      <li><a href="/files/deck.md">Source Markdown</a></li>
    </ul>
  </body>
</html>

10.2 Processing

A processing Response Page means the Action was accepted but is not complete.

It MUST include a link to a status page, result page, or other page where the final result can be obtained.

A processing response MAY say when to re-fetch with Refresh — either <meta http-equiv="refresh" content="N; url=<status>"> in the head (a browser auto-refreshes it; an agent reads the same signal) or the equivalent Refresh: N HTTP header. The client waits N seconds, then re-fetches, until a non-processing Response Page is returned.

The work being awaited need not be a machine task. It may be a human in the loop — a Hyperform (section 12.2) the host presents for a person to fill; completing it is what advances the Action to success. The client surfaces the result the same way regardless — it follows the result until it resolves — whether the work is done by a machine or by a human.

<!doctype html>
<html>
  <head>
    <title>Generating Deck</title>
    <meta name="hyperapp:type" content="action-response" />
    <meta name="hyperapp:app" content="Slides" />
    <meta name="hyperapp:action" content="create-a-deck" />
    <meta name="hyperapp:status" content="processing" />
  </head>
  <body>
    <h1>Generating Deck</h1>
    <p>Your deck is being generated.</p>
    <h2>Links</h2>
    <ul>
      <li><a href="/jobs/123">Job Status</a></li>
      <li><a href="/jobs/123/result">Result Page</a></li>
    </ul>
  </body>
</html>

10.3 Failed

A failed Response Page means the Action did not complete.

It MUST describe the failure.

If the cause is the agent's input, it SHOULD carry an Errors block (section 11) naming the offending inputs, together with a retry Action so the agent can correct them and resubmit. If the cause is operational — not the input — it SHOULD describe the problem and MAY offer a retry Action or a link back.

The Errors block is the signal: present, the agent fixes the named inputs and resubmits; absent, it is an operational failure to report or retry.

<!doctype html>
<html>
  <head>
    <title>Deck Creation Failed</title>
    <meta name="hyperapp:type" content="action-response" />
    <meta name="hyperapp:app" content="Slides" />
    <meta name="hyperapp:action" content="create-a-deck" />
    <meta name="hyperapp:status" content="failed" />
  </head>
  <body>
    <h1>Deck Creation Failed</h1>
    <p>The deck could not be created.</p>
    <h2>Errors</h2>
    <ul>
      <li data-input="markdown">Invalid markdown.</li>
    </ul>
    <h2>Actions</h2>
    <form method="post" name="create-a-deck" action="/slides/create">
      <fieldset>
        <legend>Retry creating the deck</legend>
        <p>
          <label for="markdown">markdown</label><br />
          <textarea id="markdown" name="markdown" required># Slide 1</textarea>
        </p>
        <p>
          <label for="name">name</label><br />
          <input id="name" name="name" type="text" value="My Deck" required />
        </p>
        <button type="submit">Retry</button>
      </fieldset>
    </form>
  </body>
</html>

10.4 Cancelled

A cancelled Response Page means a human ended a Hyperform (section 12.2) without completing it.

It SHOULD state that the step was cancelled, and MAY offer a retry Action or a link back.

11. Results and Errors

A Response Page body carries two kinds of structured content: Results (the outputs) and Errors (what the agent must fix). Links (section 6) and Actions (section 7) may appear in the body as well.

Results

When an Action produces textual or structured output that is itself the result — an answer, a translation, a computed value — the Response Page SHOULD include that output inline. Outputs that are files or artifacts are exposed as ordinary Links (section 6) instead.

Inline results SHOULD be grouped under a Results heading. Each result SHOULD be labelled so that an agent can identify it.

<h2>Results</h2>
<dl>
  <dt>translation</dt>
  <dd>Bonjour le monde</dd>
</dl>

Markdown conversion:

## Results

- **translation**: Bonjour le monde

Inline results, and their labels, MUST survive conversion to Markdown.

Errors

A failed Response Page (section 10.3) SHOULD expose validation errors in a machine-readable, field-level form, in addition to any human-readable description. The Errors block is what tells the agent the failure was caused by its input — and which fields to fix.

Each error SHOULD be associated with the input it concerns using a data-input attribute whose value is the input name. A form-level error that concerns no single input MAY omit data-input or use data-input="*".

<h2>Errors</h2>
<ul>
  <li data-input="name">A deck name is required.</li>
  <li data-input="markdown">Invalid markdown.</li>
</ul>

Markdown conversion:

## Errors

| input    | message                  |
| -------- | ------------------------ |
| name     | A deck name is required. |
| markdown | Invalid markdown.        |

The error-to-input association MUST be preserved during conversion to Markdown.

12. Hyperblocks

Most human–agent collaboration happens through conversation. A Hyperblock is how they collaborate on the page itself — the primary form of human-in-the-loop beyond chat. It is a human-facing block the agent does not read but instead surfaces or opens; the host renders it for the person to use directly, and what they view or supply feeds back into the agent's work.

Shared Surface (section 2) is the rule — humans and agents meet the same page. A Hyperblock is the deliberate exception: a slot where a person acts directly rather than the agent.

There are two kinds, the two directions of human-in-the-loop:

  • embed — an Embedded View (section 12.1): rendered content a human views — a document, a chart, a preview. It carries a result out to the person.
  • form — a Hyperform (section 12.2): a form a human fills — a choice, an approval, a credential. It brings input in from the person.

How the host presents a Hyperblock to the person is up to the host; authentication is a deployment concern (section 15).

12.1 embed — Embedded View

An Embedded View is a human-facing page that the host displays in a browser frame for a human user to view rendered content — a document, a chart, a preview. It is an ordinary web page, and the deliberate exception to Shared Surface (section 2): it serves humans only and is not part of the agent surface.

An Embedded View:

  • is reached as a Link (section 6) from a Hyperapp page; the agent treats its URL as something to surface to the user;
  • is exempt from the Hyperapp rules — it need not carry link or Action structure, is not converted to Markdown, and is not a Response Page;
  • SHOULD declare hyperapp:type set to embedded-view, so the host and conversion tooling recognize it as a human-only view and serve it as-is. It MAY also carry hyperapp:app to associate it with its app;
  • MAY authenticate differently from agent-facing pages: a view rendered in a frame that cannot set request headers typically carries a token in its URL (see section 15).

An Embedded View is human-only and outside the agent surface — the agent never reads it, only surfaces its URL to the user for the host to frame.

<!doctype html>
<html>
  <head>
    <title>Deck preview</title>
    <meta name="hyperapp:type" content="embedded-view" />
    <meta name="hyperapp:app" content="Slides" />
  </head>
  <body>
    <!-- a fully rendered slide deck; ordinary HTML/CSS/JS for human viewing -->
  </body>
</html>

12.2 form — Hyperform

A Hyperform is the human-facing form a for-human Action (method="dialog", section 7) produces. The host renders the Action's declared Inputs (section 8) as a form for a person to fill and submits it on the agent's behalf — the app ships no UI of its own. It is how a flow collects the input only a human can give.

The agent opens the Hyperform by fetching the for-human Action's target — a GET — then waits. What it reads is just the action, method: GET, and the target; the Inputs are omitted (the host fills them from the human's input):

## Action(Human-in-the-loop): Preferences

- method: GET
- target: `/preferences`

Until the person submits, the wait resolves as a processing Response Page (section 10.2); on submit, a re-fetch returns a Response Page (section 10) carrying their input, which the agent passes to the following Action. If the person ends the Hyperform without completing it, the result is a cancelled Response Page (section 10).

The host renders the form and resolves the wait through the platform's wire mechanism, a deployment concern (see the deployment profile). In HTML the for-human Action is an ordinary <form method="dialog">.

13. Markdown Representation

A Hyperapp MUST remain understandable when converted to Markdown.

An agent requests the Markdown representation with Accept: text/markdown; absent that header the server returns HTML. The same URL serves both.

Links MUST remain links.

Action Preservation

Forms MUST be converted into Action blocks.

No executable Action may be omitted during conversion.

Each Action renders as its own section, headed by its title — ## Action: <title>, or ## Action(Human-in-the-loop): <title> for a for-human Action (section 12.2) — and carries the Action's name (its reference key) as a name: line. A heading that only introduces Actions (such as <h2>Actions</h2>) is omitted, since each Action already labels itself.

The conversion MUST preserve:

  • action title
  • action name
  • method
  • target
  • input names
  • input types
  • required status
  • input values, when present
  • the options and their submitted values for select, radio, and checkbox inputs
  • hidden inputs and their values
  • input descriptions, when present

Together these keep the Action submittable from its Markdown alone.

A for-human Action (method="dialog", section 7) is the exception: a person fills it through a Hyperform (section 12.2), so its Markdown omits the Inputs and shows method: GET.

Example HTML:

<form method="post" name="create-a-deck" action="https://example.com/slides/create">
  <fieldset>
    <legend>Create a deck</legend>
    <input type="hidden" name="csrf" value="a1b2c3" />
    <textarea name="markdown" required></textarea>
    <input name="name" type="text" required />
    <label for="theme">theme</label>
    <select id="theme" name="theme">
      <option value="default" selected>Default</option>
      <option value="gaia">Gaia</option>
    </select>
    <button type="submit">Create deck</button>
  </fieldset>
</form>

MUST become a Markdown Action block preserving the same semantics, for example:

## Action: Create a deck

- name: `create-a-deck`
- method: POST
- target: `https://example.com/slides/create`

### Inputs

| name     | type     | required | value   | options       |
| -------- | -------- | -------- | ------- | ------------- |
| csrf     | hidden   | yes      | a1b2c3  |               |
| markdown | textarea | yes      |         |               |
| name     | text     | yes      |         |               |
| theme    | select   | no       | default | default, gaia |

The exact formatting of the Action block is implementation-defined.

The value and options columns MAY be omitted when no input in the Action carries a value or options.

The preserved semantics are normative.

Response Page Metadata

Response Page metadata in <head> SHOULD be preserved in Markdown frontmatter when the conversion system supports frontmatter.

Example HTML metadata:

<meta name="hyperapp:type" content="action-response" />
<meta name="hyperapp:app" content="Slides" />
<meta name="hyperapp:action" content="create-a-deck" />
<meta name="hyperapp:status" content="success" />

Markdown frontmatter:

---
hyperapp:type: action-response
hyperapp:app: Slides
hyperapp:action: create-a-deck
hyperapp:status: success
hyperapp:origin: https://example.com
---

When links or Action targets are kept as relative references, the conversion MUST record the source document's base URL as hyperapp:origin (see URL Resolution in section 6).

14. Agent Interpretation

When reading a Hyperapp, an agent should determine:

  • what app this page belongs to
  • what links are available
  • what actions are available
  • what inputs are required
  • where requests should be sent
  • whether an Action response is complete
  • where to obtain final results if processing is still ongoing

Agents enter a Hyperapp at its Directory Page and discover capabilities by following links to the app's other pages.

A page whose hyperapp:type is embedded-view (section 12.1) is a human-only page. Agents SHOULD surface its link to the user rather than read or act on it.

Agents SHOULD NOT assume that form submission directly returns a final result.

Agents SHOULD inspect the returned Response Page.

If hyperapp:status is processing, agents SHOULD follow the provided status or result link, honoring any Refresh.

If hyperapp:status is success, agents SHOULD inspect Results and Links for final outputs.

If hyperapp:status is failed, agents SHOULD inspect the page: if it carries an Errors block, the agent's input was the problem — correct the named fields and resubmit via the retry Action; otherwise it is an operational failure to report, and to retry or work around when appropriate.

If hyperapp:status is cancelled, the human ended the Action; agents SHOULD report that and MAY offer a retry Action or Link.

15. Authentication

A Hyperapp MAY require authentication. This spec does not mandate a credential scheme.

  • Agents present credentials using standard HTTP mechanisms — typically an Authorization header sent on every request (link fetches and Action submissions alike).
  • A request without valid credentials MUST be rejected with HTTP 401 (unauthenticated) or 403 (forbidden). Where practical the response body SHOULD still be a Hyperapp page, so an agent can read what is required and how to proceed.
  • Authentication MUST NOT break discovery: a page's link and Action structure is the contract even when a specific capability is gated.
  • A view rendered in a browser frame that cannot set request headers (for example an <iframe> preview) MAY instead carry a short-lived token in its URL.

Specific token formats, issuers, audiences, and cross-app delegation are deployment concerns and are out of scope here. An ecosystem MAY define them in a separate profile (see, for AGX, the AGX Hyperapp Deployment Profile).

16. Conformance

A document is a valid Hyperapp if it contains:

  • a title (<title>)
  • a description
  • at least one link or action

The root page of a Hyperapp MUST be a Directory Page: an app page consisting primarily of links to the app's other pages.

If an Action is present, it MUST contain:

  • method
  • target
  • at least one named input
  • submit control

A Response Page is conforming only if it contains:

  • hyperapp:type set to action-response
  • hyperapp:app
  • hyperapp:action
  • hyperapp:status
  • at least one of Results, Links, or Actions

A Markdown representation is conforming only if:

  • links are preserved and remain resolvable (absolute, or relative with a recorded hyperapp:origin)
  • forms are represented as Action blocks
  • input values, options, and hidden inputs are preserved; for a for-human Action (section 7) the Markdown preserves the action title and name, method, and target, and the host renders its Inputs as a Hyperform (section 12.2)
  • inline Results are preserved
  • no executable capability is omitted
  • Response Page metadata is preserved when frontmatter is supported

17. Complete Example

HTML App Page

This is the Create capability page. The app's root Directory Page is shown in 5.1.

<!doctype html>
<html>
  <head>
    <title>Create</title>
    <meta name="hyperapp:type" content="app" />
    <meta name="hyperapp:app" content="Slides" />
  </head>
  <body>
    <h1>Create</h1>
    <p>Create a slide deck from markdown.</p>
    <h2>Links</h2>
    <ul>
      <li><a href="/templates">Templates</a></li>
      <li><a href="/themes">Themes</a></li>
    </ul>
    <h2>Actions</h2>
    <form method="post" name="create-a-deck" action="/slides/create">
      <fieldset>
        <legend>Create a deck</legend>
        <p>
          <label for="markdown">markdown</label><br />
          <textarea id="markdown" name="markdown" required></textarea>
        </p>
        <p>
          <label for="name">name</label><br />
          <input id="name" name="name" type="text" required />
        </p>
        <button type="submit">Create deck</button>
      </fieldset>
    </form>
  </body>
</html>

Markdown App Page

---
hyperapp:type: app
hyperapp:app: Slides
hyperapp:origin: https://example.com
---

# Create

Create a slide deck from markdown.

## Links

- [Templates](/templates)
- [Themes](/themes)

## Action: Create a deck

- name: `create-a-deck`
- method: POST
- target: `/slides/create`

### Inputs

| name     | type     | required |
| -------- | -------- | -------- |
| markdown | textarea | yes      |
| name     | text     | yes      |

HTML Response Page

<!doctype html>
<html>
  <head>
    <title>Deck Created</title>
    <meta name="hyperapp:type" content="action-response" />
    <meta name="hyperapp:app" content="Slides" />
    <meta name="hyperapp:action" content="create-a-deck" />
    <meta name="hyperapp:status" content="success" />
  </head>
  <body>
    <h1>Deck Created</h1>
    <p>The slide deck was created successfully.</p>
    <h2>Links</h2>
    <ul>
      <li><a href="/files/deck.html">Preview Deck</a></li>
      <li><a href="/files/deck.md">Source Markdown</a></li>
    </ul>
  </body>
</html>

Markdown Response Page

---
hyperapp:type: action-response
hyperapp:app: Slides
hyperapp:action: create-a-deck
hyperapp:status: success
hyperapp:origin: https://example.com
---

# Deck Created

The slide deck was created successfully.

## Links

- [Preview Deck](/files/deck.html)
- [Source Markdown](/files/deck.md)

On this page