Form layouts
Form layouts define how fields appear on a record's edit and view screens. They live in .tsx files, but they do not produce React components. Instead, a custom JSX factory compiles them into XML strings that the platform's form engine renders at runtime.
The JSX-to-XML factory
Every app's tsconfig.json includes two critical settings:
{
"jsx": "react",
"jsxFactory": "entity"
}
The entity function - implemented in api/typings/jsx-runtime.ts - is a custom JSX runtime. When TypeScript compiles a .tsx layout file, it calls entity instead of React.createElement. The return value is a plain XML string, not a virtual DOM node.
Every layout file needs two things at the top: a /** @jsx entity */ pragma and the entity import from #typings:
/** @jsx entity */
import { entity } from '#typings';
// What you write in default.tsx:
export default (
<layout>
<field name="title" />
<section caption="Details">
<field name="description" />
<field name="c_priority" />
</section>
</layout>
);
// What the compiler produces (via the entity function):
// '<field name="title" /><section caption="Details"><field name="description" /><field name="c-priority" /></section>'
The resulting XML string is stored as the layout in the compiled app schema. At runtime, the platform reads this XML and renders the form - React is never involved.
File structure
Layouts live in views/layouts/ inside the package structure:
default.tsx- the main form layout, used for the standard record view.index.ts- exports anAppLayoutmap that associates layout names with their.tsxfiles.
You can define multiple layout files when an app needs alternative views. Each one gets an entry in the AppLayout map exported from index.ts.
Layout elements
Fields
The <field> element renders a single field on the form. Its name prop must match a field name declared in fields/index.ts:
/** @jsx entity */
import { entity } from '#typings';
export default (
<layout>
<field name="title" />
<field name="c_priority" />
<field name="c_due_date" />
</layout>
);
See Fields for the full list of field types and options.
Sections
The <section> element groups related fields under a collapsible heading:
<section caption="Billing details">
<field name="c_invoice_number" />
<field name="c_total_cost" />
<field name="c_currency" />
</section>
Sections keep complex forms organized. Users can expand or collapse them to focus on the fields they need.
Conditional rendering
Because layout files are valid TypeScript, you can use JavaScript expressions to include or exclude elements:
{showBilling && (
<section caption="Billing">
<field name="c_invoice_number" />
</section>
)}
This lets you build dynamic layouts that adapt to app configuration or context.
Props and naming conventions
Two automatic transformations happen during compilation:
- CamelCase to kebab-case - a prop written as
camelCasein TSX becomescamel-casein the output XML. For example,c_prioritystays as-is because underscores are not affected, but a hypotheticaldataSourceprop would becomedata-source. - HTML escaping - all prop values are escaped so that characters like
<,>, and&do not break the XML output.
The name prop on <field> always references a field name from Fields. Keep field names consistent between fields/index.ts and your layout files.
Common mistake - treating layouts as React
The single most frequent error is writing React code inside a .tsx layout file. Because the file extension is .tsx and the syntax looks like JSX, developers assume they can use:
- React hooks (
useState,useEffect) - Component state and lifecycle methods
- React context or portals
None of these work. The entity factory returns a string, not a React element tree. If you need runtime UI behavior - such as showing or hiding fields based on the current record state - use View logic hooks instead. See Common mistakes for more examples.
Quick reference
| Element | Purpose | Key prop |
|---|---|---|
<field> | Render a single field | name - field name from fields/index.ts |
<section> | Collapsible group of fields | caption - section heading text |
What to read next
- Fields - field types and options that
<field>elements reference. - View logic - runtime visibility, requiredness, and read-only rules.
- Package structure - where layout files sit in the app directory.