Pages¶
Pages are the screens people use in your Diagonal application. A Page owns a route, access rules, optional Layout, SEO settings, and React source. It reads and changes workspace data through the Page SDK.
Pages are separate from Workflows. Opening a Page does not run a Page Workflow or a render Step. Interactive Page code can call the SDK directly, and it can call a published Workflow when an action belongs in reusable business logic.
Create a Page¶
Open Pages, select Create Page, and complete the four-step wizard.
1. Name & Layout¶
Enter a Name. Diagonal proposes a lowercase, hyphenated Route from the name; you can change it later.
Choose a Layout or Blank. A Layout wraps the Page body and can provide shared chrome such as a header, sidebar, navigation, or footer. Blank is the default. You can change the Layout in the Page Editor.
2. Access¶
New Pages default to All logged-in users.
| Choice | Who can open the Page |
|---|---|
| All logged-in users | Any authenticated workspace identity. |
| Specific permissions | An authenticated identity from the selected Resource with any one of the selected Permissions. |
| Public | Anyone who can reach the URL. |
Page access does not bypass Resource Policies. A user may be allowed to open a Page while the SDK still hides or rejects Records they are not allowed to access.
3. Details¶
Set the Route, optional domain, folder, and optional Navigation placement.
- A Page without a selected domain follows the workspace's primary domain.
- Only active workspace domains can be selected.
- A draft may temporarily use the same route as another draft. Publication requires a free route on that domain.
- Pages and When a request comes in Workflows share the same route space.
Routes can include parameters, for example /customers/{customer}. Configure a parameter binding to choose its Resource and lookup Field. Page code can read both the raw parameter and the resolved Record.
A Page with route parameters cannot be added directly to a Navigation Menu because the Menu has no value to put in the URL. Link to a specific Record from Page code instead.
For a route without parameters, Navigation can:
- leave the Page out of navigation;
- add it to an existing Menu;
- create a new Menu; or
- place it at the top level or beneath a Dropdown in the selected Menu.
The Menu Item points to the Page rather than copying its route. After you publish a new Page route, navigation resolves the new published URL automatically. Menu Item Permissions only hide items; the destination Page still enforces its own access rules.
4. Build¶
Optionally describe What should this page do? and Diagonal's AI agent will author the first draft while you watch. Leave it empty to start with the built-in starter Page. AI building requires access to the AI agent.
Select Create Page. Creation saves a draft and opens the Page Editor; it does not publish the Page.
Edit, preview, and publish¶
The Page Editor has Preview, Code, and Settings views. Draft changes autosave about half a second after you stop editing. Requests are serialized, so an edit made during a save is queued as the next save.
Draft autosave deliberately accepts incomplete code while you work. The preview shows the draft through an isolated preview session. Neither saving nor previewing changes the Page served to users.
Select Publish to make the current draft live. Publish first flushes pending saves, then validates Page source and SDK references, checks the route, and creates an immutable Page version. If validation fails, the current published version stays live and the editor opens the relevant Code or Settings view.
After publication:
- further edits show an unpublished state until you publish again;
- selecting Pause page in Settings stops serving the Page without deleting its published version;
- publishing or selecting Resume page makes that version servable again; and
- sitemap changes are rebuilt after publication, pause, or resume.
Write Page code¶
Page source is the body of a factory function. React and Sdk are injected—do not use import or export.
return function Page() {
const customer = Sdk.helpers.useInput('customer');
return (
<main className="mx-auto max-w-3xl px-6 py-12">
<h1 className="text-3xl font-semibold">{customer?.name ?? 'Customer'}</h1>
</main>
);
}
Use:
Sdk.Components.*for built-in UI;Sdk.Custom.*for workspace shared code Components;Sdk.resource('customers')for Resource/Record operations;Sdk.helpers.*for route params, route bindings, and Page input;Sdk.identityandSdk.authfor the current identity and authentication;Sdk.navigationMenu('<menu-id>')for a workspace Menu;Sdk.workspace.values.*for workspace configuration; andSdk.api,Sdk.router,Sdk.useForm,Sdk.hooks.*, andSdk.utils.*for application behavior.
Prefer Resource slugs over UUIDs so Page source can move between workspaces. The editor provides workspace-aware SDK types and checks references it can resolve statically.
Page input is server-provided data, not a Workflow variable runtime. Read it through Sdk.helpers.getInput(...) for a one-time value or Sdk.helpers.useInput(...) inside the component when the UI should update as input changes.
Refresh data while the Page waits¶
When a Page waits for a change made outside it—a webhook, a queued job, another user—it can refresh itself on a timer instead of showing a Refresh button. Which primitive to use depends on where the data comes from:
Sdk.hooks.usePoll(interval)refreshes route bindings and Page input. It returns{ start, stop }. This is the only option on a public Page with an anonymous visitor, because the Record API needs authentication. Each tick re-renders the Page on the server, so use 3000 ms or more.- A
pollIntervaloption onSdk.hooks.useRecord,Sdk.hooks.useRecords, andSdk.hooks.useApirefetches only that Record, list, or endpoint. Give it a number of milliseconds, or a function that receives the current data and returnsfalseto stop.
Both raise intervals below 1000 ms to 1000 ms. Stop polling as soon as the change arrives.
A usePoll tick rebuilds the Page, so anything the Page keeps in local state is reset and any fetched Record is reloaded. Use usePoll on a simple Page that waits for one change, and pollInterval everywhere else. While the browser tab is hidden, pollInterval stops and usePoll slows to one tick in ten.
Sdk.hooks.useRecord also returns refreshIn for an optional countdown. It is the number of whole seconds until the next automatic request, rounded up. It is 0 while a refresh is in flight, and null when no refresh is scheduled—before the first request completes, without a pollInterval, after the pollInterval function returns false, or while the browser tab is hidden.
Shared Components and Layouts¶
A shared code Component appears under Sdk.Custom.<Name> and receives ordinary React props:
return function Page() {
const customer = Sdk.helpers.useInput('customer');
return <Sdk.Custom.CustomerCard record={customer} showActions />;
}
A Layout is selected in Page settings and wraps the Page through children; it is not rendered through Sdk.Custom.*. Publishing a Component or Layout change follows that editor's publication behavior, while the Page's layout_id change is part of the Page draft and requires Page publication.
SEO and sitemap¶
In Settings, configure the browser/SEO Title, Description, public social image, optional custom head HTML, and Include in sitemap. New Pages are included by default.
Empty SEO fields fall back to Brand Kit defaults. A Page must be public, active, published, and included to appear as a normal sitemap entry. Parameterized routes require sitemap configuration that can produce concrete public Record URLs; a placeholder alone is not a valid sitemap URL.
Only use custom head HTML for markup you trust and actually need. It becomes part of the published document.
Connect Pages to Workflows and integrations¶
Keep UI-local reads and CRUD operations in the Page SDK. Call a published Workflow for business behavior that should be reused, audited as one execution, triggered elsewhere, or kept off the client—for example charging a payment, orchestrating several writes, or sending an email.
Layouts can render Sdk.navigationMenu(...); the Menu is filtered for the current identity before it reaches the Page. Provider-backed SDK components, such as payments or analytics, still require their corresponding workspace integration/configuration. A Page can render without that provider only if its code handles the missing or error state.
Limitations and troubleshooting¶
- The route saves but won't publish: another published Page or Request Workflow owns it on that domain, or it is reserved by the platform.
- A Menu option disappears: Pages with
{parameters}cannot be static Menu Items. - Preview works but Publish fails: draft preview accepts work in progress; publication runs parse, JSX transform, factory, scope, TypeScript, and SDK-reference checks.
- A user sees the Page but not its data: check Resource Policies and the identity Resource, not only Page access.
- A Page is published but returns unavailable: confirm it is Active, on the expected domain, and that the URL uses every required route parameter.
- An SDK name is unknown: use the editor's SDK reference and workspace catalog; do not guess component, Resource, or Field names.