Click a contact in Post 3's grid or Post 4's table, and you'd expect a detail screen showing that one person in full. This is the simplest kind of block on the platform, precisely because there's no repetition to manage — one query, one row, values available wherever the block needs them.

1 The XML

No dynamiclist, no row template — a detail block is just a container with its own SQL:

emxml_blkContactDetail.xml
<block>

    <!-- Block-level SQL first: its columns are tokens for everything below -->
    <sql>
        <query name="contact_detail"><![CDATA[
            SELECT c.contact_name, c.job_title, c.department, c.email, c.phone,
                   UPPER(LEFT(c.contact_name,1)) AS initials,
                   DATE_FORMAT(c.created_date,'%%b %%Y') AS customer_since,
                   IF(c.status='Active','Active','Inactive') AS status_label,
                   COUNT(o.order_id) AS open_order_count
            FROM   contacts c
            LEFT JOIN orders o ON o.contact_id = c.contact_id AND o.status = 'open'
            WHERE  c.contact_id = '%contact_id%'
            AND    c.dept_id    = '%deptid%'
            GROUP BY c.contact_id
            LIMIT  1
        ]]></query>
    </sql>

    <div class="detail-card">

        <div class="detail-header">
            <div class="detail-avatar">%initials%</div>
            <div>
                <div class="detail-name">%contact_name%</div>
                <div class="detail-role">%job_title% &#183; %department%</div>
            </div>
            <div class="detail-status">%status_label%</div>
        </div>

        <div class="detail-body">
            <div>
                <div class="detail-field-label">Email</div>
                <div class="detail-field-value">%email%</div>
            </div>
            <div>
                <div class="detail-field-label">Phone</div>
                <div class="detail-field-value">%phone%</div>
            </div>
            <div>
                <div class="detail-field-label">Open Orders</div>
                <div class="detail-field-value">%open_order_count%</div>
            </div>
            <div>
                <div class="detail-field-label">Customer Since</div>
                <div class="detail-field-value">%customer_since%</div>
            </div>
        </div>

    </div>

</block>

What's different about single-row data

<block> root
Every block file's root element is <block>. It's transparent — it emits no tag of its own — and it's what makes a block-level <sql> legal at all: <sql> sits as a direct child of <block>, never nested inside one of the layout <div>s.
<sql> comes first
This is the one ordering rule worth memorising. A block-level query has to be the first child of <block>, before the markup that reads its tokens. Put it at the bottom and every %token% above it renders as literal, unresolved text — no error, just the raw %contact_name% printed on the page. (Inside a dynamiclist it's the other way round: there the query follows the row template.)
no row template
There's nothing to repeat, so there's no type="row" — just ordinary HTML tags with the query's columns referenced as tokens directly.
%contact_id%
Where the "which contact" value comes from — passed in as a parameter when this block is opened (a click on a card or table row, carrying that row's id along with it).
tokens travel further
Because this is a single-row query, its columns become ordinary tokens usable anywhere in the block — unlike list and table data, which stays scoped to its own row template and goes no further.
LIMIT 1
Worth keeping even though contact_id should already be unique — it's a safety net, not a formality, since a query returning more than one row here would only ever use the first regardless.
2 Rendered live
app.example.com/manager/contacts/1042
S
Sarah Whitfield
Operations Manager · Operations
Active
Email
s.whitfield@example.com
Phone
+44 1895 700 142
Open Orders
3
Customer Since
Mar 2023
Same JOIN pattern as the table post, same tenant scoping, same one-query rule — the only real change is LIMIT 1 and the fact that nothing here is wrapped in a row template.

The pattern so far

Three posts in, and the shape is already clear: every read operation on the platform is the same idea — a query, a template, tokens standing in for columns — adjusted for how many rows come back and how they need to be laid out. Many free-form rows: dynamiclist. Many structured rows: dynamiclisttable. Exactly one row, values used freely: block-level SQL, no wrapper at all. Reading data was never the hard part of building a web application — it's writing it back that usually is, which is where the next two posts go.