Appearance
Pages
Table of Contents
Pages are custom screens built from a single HTML file containing JavaScript and CSS. Use them for station screens, dashboards, or focused workflows over Factorial's API. The code runs in the viewer's browser. Factorial stores the HTML in its configured object storage and serves it at /pages/<slug> on the same origin as the application.
Creating a page
- Open Pages → All pages in the main menu.
- Expand New page, enter a name and URL slug, then select Save.
- Expand Manage on the new page, choose an HTML file, and select Upload and publish.
A file may be at most 20 MB and must begin with an HTML doctype or element, such as <!doctype html>. Include scripts and styles in the file; additional uploaded assets and server-side code are not supported. Slugs use lowercase letters, numbers, and single hyphens, up to 80 characters. manage, create, and starter are reserved.
Published pages appear in the Pages menu. The menu shows the first 20 by name; All pages provides a paginated list of every page. A page awaiting its first upload has no published screen.
The Pages permission controls creating, renaming, replacing, and deleting pages. Administrators receive it automatically; grant it to other trusted authors through roles. Any signed-in user can open a published page. Its API calls use that viewer's current permissions, and changes are attributed to that viewer through the API.
Updating and deleting
Under Manage, save a new name or slug, or upload replacement HTML. A replacement becomes available after the upload succeeds. Failed uploads leave the previous version available. Viewers reload the page to see the replacement. Changing the slug changes the URL; old links stop working.
Download current HTML retrieves the published file. Delete page removes the menu entry and stops serving its URL. Uploaded files follow Factorial's existing file retention behavior; deleting a page does not purge its uploaded objects.
Calling the API
Use root-relative URLs beginning with /api/v1/. The browser automatically includes the signed-in session cookie for same-origin requests. The cookie is HttpOnly: JavaScript does not need to read it or copy it into an Authorization header. Do not embed API keys in pages.
js
const response = await fetch('/api/v1/tasks/query', {
method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ pagination: { next: 25 } })
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || `Request failed (${response.status})`);
}
const page = await response.json();
// page.items contains this batch. Continue with page.next_cursor when
// page.has_next_page is true, keeping the same query and sort order.Writes use the same session. For example, starting a task:
js
await fetch('/api/v1/tasks/status', {
method: 'PATCH',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ task_ids: [taskId], status: 'IN_PROGRESS' })
});Check every response before displaying a change as saved. A 401 means the viewer needs to sign in again; a 403 means their role does not allow the operation. Other errors include a JSON error message. Network failures may leave the outcome unknown: refresh the affected records before retrying a write.
Pages use ordinary API requests. They do not receive Factorial's built-in live page updates or session keepalive. Include a refresh button or deliberately spaced polling, and display when the data was last refreshed. Stop polling while the tab is hidden and avoid overlapping requests. Handle session expiry even while a custom page remains open.
Who's viewing
GET /api/v1/me returns the signed-in viewer's id, name, and email. Use it to greet the viewer or show their own work. For example, list the viewer's open tasks:
js
const meResponse = await fetch('/api/v1/me', { credentials: 'same-origin' });
if (!meResponse.ok) throw new Error(`Couldn't load the viewer (${meResponse.status})`);
const me = await meResponse.json();
const response = await fetch('/api/v1/tasks/query', {
method: 'POST',
credentials: 'same-origin',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
filters: [
{ r: ['ASSIGNEE'], f: 'id', o: 'EQ', v: me.id },
{ f: 'status', o: 'IN', v: ['TODO', 'IN_PROGRESS'] }
]
})
});Starter and API reference
Download starter HTML on All pages provides a complete task board with pagination, refresh, error handling, and a Start action. Download it, edit it with your preferred coding tool, and upload it to a page. API calls work when the file is served by Factorial; opening it from your local filesystem does not provide a Factorial session.
API → API Docs, also linked from All pages, opens the generated reference at /api. Download API schema retrieves the OpenAPI document at /api/openapi.json. Give that document and the starter HTML to your coding agent so it can use the endpoints and request shapes available in your installed version. The reference supports requests using your browser session.
See API for queries, pagination, file uploads, and write behavior. Prefer the documented /api/v1/ endpoints when building pages.