Developer Docs - Mobile Docs - Overview

Helix lets you build dynamic, interactive screens in the mobile app without writing a single line of C#. A Lava Application endpoint returns a chunk of XAML, the app swaps that XAML into the live page, and the person never leaves the screen they were on.

If you have used HTMX on the web, this will feel immediately familiar. Helix is Rock's HTMX-based approach, and the mobile vocabulary is a deliberate port of it. If you have used the mobile Content block's Callbacks, you already know most of the idea: Helix is that same swap loop, generalized so any element can start a request and any named element on the page can receive the result.

Your first Helix screen

Three pieces: an element to receive the content, an element to go get it, and an endpoint to serve it.

On the page


    

The endpoint

A GET endpoint with the slug my-groups, in an application with the slug group-toolbox. Its Code Template is ordinary Lava that happens to emit XAML instead of HTML (25 here being whichever group type you care about):

{% assign memberships = CurrentPerson | Groups:'25' %}


    {% for membership in memberships %}
        

Four things to internalize first

All Lava runs on the server. Write as much Lava as you like in your Code Template; the shell receives its rendered output. There is no second Lava pass on the device, so a fragment is a snapshot of the moment it was served. The Content block's ProcessLava setting does not apply to Helix fragments.

One request, one target. A response has a single root element and lands in one place. There are no out-of-band swaps and no response content selection.

Setting a verb wires the interaction for you. You do not need Command="{Binding ...}" plumbing. The moment you put Hx.Get on a Button, its Clicked is wired. Put it on anything else and it gets a tap gesture.

Targeting is by id, not by selector. HTMX aims at the DOM with CSS selectors. Helix aims at an element you have given an Hx.Id. Ids work across the whole page, which is what makes it possible for one block to update an element inside a different block.

Vocabulary

These terms come up constantly in the rest of these docs.

Routes

Mobile uses the same ^ shorthand web does.

Any of them may carry a query string, and query string values stay in the URL for every verb.

What the shell sends

Every Helix request carries these, so CurrentPerson resolves and your Execute security verbs are enforced exactly as they are for a browser.

To serve both a browser and the app from one endpoint, branch on the ClientType merge field rather than reading the header yourself. It is Mobile for the app and Web for everything else:

{% if ClientType == 'Mobile' %}
    
        
{% else %}
    
Hello from the browser
{% endif %}

ClientType is a rendering hint, never an authorization input. It is derived from a header that any caller can send, so branch presentation on it and never gate data access on it. See Security.

Where to next