Support/First Class Modules/Checklists & Signoffs

First Class Modules

Checklists & Signoffs

Attaches reusable, versioned checklists to authorized records and lets each item require notes, documents, or photos before the completed run enters the existing Workflow signoff path.

Open raw .md
Runtime key
module.checklists-signoffs
Experience
Evidence-backed work acceptance
Security
Server-enforced

Use Checklists & Signoffs when work must be performed step by step and accepted with reviewable evidence. A run can attach to a ticket, project, work order, or other universal record without copying that record or inventing another approval system.

Note

The bundled renderer key is module.checklists-signoffs. First-class means BuildWithHQ supplies a native, typed, secured runtime experience inside normal app provisioning and the signed-in user's existing permissions.

What it does

Attaches reusable, versioned checklists to authorized records and lets each item require notes, documents, or photos before the completed run enters the existing Workflow signoff path.

Key capabilities

  • Create reusable versioned templates with ordered required or optional items.
  • Attach a template snapshot to any authorized universal record.
  • Track up to 1,000 ordered run items with completion actor, time, note, and revision.
  • Require one or more native File documents or photos as proof for selected items.
  • Calculate bounded progress and refuse submission while required work or evidence is missing.
  • Submit exactly one current run to the existing Workflow and Universal Inbox approval path.
  • Support rejection, editing, proof replacement, resubmission, approval, and replayable history.
  • Reject stale revisions and make duplicate completion, submission, and decision requests idempotent.

Common uses

  • Work-order inspection and closeout proof.
  • Project stage-gate and quality checklists.
  • Support-ticket diagnostic or escalation checkoffs.
  • Safety, compliance, onboarding, handoff, and document-review signoffs.

How it connects

Runs attach through universal Record relationships. Evidence remains a native File, decisions remain Workflow approval records, reviewer attention remains in Universal Inbox, and activity/audit records preserve the end-to-end chain.

Where applicable, its records use the universal RecordId conventions so they can participate in secured relationships, activity history, favorites, dynamic fields, notifications, Inbox attention, and global search without copying the source record.

Security and data boundary

Every list, detail, item update, evidence link/download, submission, and decision derives tenant, user, DataRole, Location, and source-record scope from server identity. Evidence links do not grant File access, and Workflow permissions—not checklist UI state—control signoff authority.

  • The authenticated service derives the SaaS app, tenant account, user, DataRole, and location scope; browser identifiers are never authorization proof.
  • The page editor composes React components with validated data bindings. Those bindings call typed runtime APIs, whose application services execute reviewed stored procedures.
  • List, search, detail, relation, activity, favorite, and write operations reapply their required server-side permissions.

Add it to an app

  1. Add module.checklists-signoffs to the source-record pages and menus where users perform or review work.
  2. Create a versioned template with ordered items, required/optional state, proof type, and responsible role.
  3. Grant source-record, checklist action, Workflow approval, File, DataRole, and Location permissions independently.
  4. Attach a run to a representative ticket, project, work order, or custom record and complete it with required notes/documents/photos.
  5. Test cross-tenant and cross-location denial, stale and duplicate requests, unauthorized file access, reject/edit/replace/resubmit/approve, failure recovery, and a 1,000-item boundary run before publishing.

Copy/paste the checklist page

The normal choice is the native block. It already provides template creation, record-attached runs, item updates, document/photo proof, submission, and signoff status. Paste this page document into Raw JSON mode:

{
  "blocks": [
    {
      "_id": "work-checklists-signoffs",
      "_type": "module.checklists-signoffs",
      "props": {},
      "children": []
    }
  ]
}

With empty props, the page loads a bounded first page of checklist runs visible to the signed-in user. On a contextual record page, set targetRecordId through the page editor's validated binding to pre-filter and prefill that record. The value remains a query target; the server independently authorizes it.

Custom unstyled React feed

For custom presentation inside apps/tenant-runtime/src, retain the official authenticated API helper and SDK parser and replace only the markup. This read view does not infer edit or approval authority in React:

import { useEffect, useState } from "react";
import type {
  ChecklistRunDetail,
  ChecklistRunList,
  ChecklistRunStatus,
} from "@buildwithhq/module-sdk";
import { getChecklistRun, listChecklistRuns } from "./api";

type ChecklistFeedProps = {
  readonly targetRecordId?: string;
};

const statuses: readonly (ChecklistRunStatus | "")[] = [
  "", "Draft", "InProgress", "ReadyForSignoff",
  "Approved", "Rejected", "Cancelled",
];

export function CustomChecklistFeed({ targetRecordId = "" }: ChecklistFeedProps) {
  const [status, setStatus] = useState<ChecklistRunStatus | "">("");
  const [feed, setFeed] = useState<ChecklistRunList | null>(null);
  const [selected, setSelected] = useState<ChecklistRunDetail | null>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    const request = new AbortController();
    setSelected(null);
    setError(null);
    listChecklistRuns(targetRecordId, status, request.signal)
      .then(setFeed)
      .catch((caught: unknown) => {
        if (!(caught instanceof DOMException && caught.name === "AbortError")) {
          setError(caught instanceof Error ? caught.message : "Checklists could not be loaded.");
        }
      });
    return () => request.abort();
  }, [status, targetRecordId]);

  const open = async (checklistRunId: string) => {
    setError(null);
    try {
      setSelected(await getChecklistRun(checklistRunId));
    } catch (caught) {
      setError(caught instanceof Error ? caught.message : "The checklist could not be loaded.");
    }
  };

  return (
    <section className="custom-checklists" aria-labelledby="checklists-title">
      <header>
        <div>
          <p>First-class module</p>
          <h1 id="checklists-title">Checklists &amp; Signoffs</h1>
        </div>
        <label>
          Status
          <select value={status} onChange={(event) => setStatus(event.target.value as ChecklistRunStatus | "")}>
            {statuses.map((value) => <option key={value || "all"} value={value}>{value || "All statuses"}</option>)}
          </select>
        </label>
      </header>

      {error && <p role="alert">{error}</p>}
      {!feed && !error && <p role="status">Loading checklists...</p>}
      {feed && <p>Showing {feed.items.length} of {feed.totalRecords} visible checklist runs</p>}
      {feed?.items.length === 0 && <p>No checklists match this secured view.</p>}

      <ol className="custom-checklists__runs">
        {feed?.items.map((run) => (
          <li key={run.checklistRunId} data-status={run.status}>
            <button type="button" onClick={() => void open(run.checklistRunId)}>
              <span><strong>{run.title}</strong><small>{run.targetTitle}</small></span>
              <span>{run.completedItemCount}/{run.itemCount} complete / {run.status}</span>
            </button>
          </li>
        ))}
      </ol>

      {selected && (
        <article className="custom-checklists__detail" aria-labelledby="checklist-detail-title">
          <button type="button" onClick={() => setSelected(null)}>Close details</button>
          <h2 id="checklist-detail-title">{selected.title}</h2>
          <p>{selected.status} / revision {selected.revision}</p>
          <ol>
            {selected.items.map((item) => (
              <li key={item.checklistRunItemId}>
                <strong>{item.title}</strong>
                <span>{item.status}{item.isRequired ? " / required" : " / optional"}</span>
                {item.responseText && <p>{item.responseText}</p>}
                {item.evidence.length > 0 && (
                  <ul>{item.evidence.map((proof) => <li key={proof.checklistItemEvidenceId}>{proof.proofKind}: {proof.fileName}</li>)}</ul>
                )}
              </li>
            ))}
          </ol>
        </article>
      )}
    </section>
  );
}

Copy/paste write lifecycle

These helpers show the correct order for a proof-backed item: create a versioned template, attach a run to an authorized Record, upload bytes through Files, attach that File as proof, update with the newest item revision, then reload and submit with one stable request ID.

import type { ChecklistRunItem } from "@buildwithhq/module-sdk";
import {
  attachChecklistProof,
  createChecklistTemplate,
  getChecklistRun,
  startChecklistRun,
  submitChecklistForSignoff,
  updateChecklistItem,
  uploadFile,
} from "./api";

export const createCloseoutTemplate = () => createChecklistTemplate({
  name: "Work-order closeout",
  description: "Completion requires a site photo.",
  items: [{
    itemKey: "completion-photo",
    title: "Photograph the completed work",
    instructions: "Show the finished work and surrounding area.",
    responseType: "Checkbox",
    isRequired: true,
    evidenceRequirement: "Photo",
    minimumEvidenceCount: 1,
    sortOrder: 0,
  }],
});

export const startCloseout = (targetRecordId: string, checklistTemplateId: string) =>
  startChecklistRun({ targetRecordId, checklistTemplateId, title: "Closeout" });

export async function completeItemWithPhoto(
  item: ChecklistRunItem,
  photo: File,
  caption: string,
  locationId?: string,
) {
  const uploaded = await uploadFile(photo, { description: caption, locationId });
  if (!uploaded.recordId) throw new Error("The Files API did not return a RecordId.");

  const attached = await attachChecklistProof(item.checklistRunItemId, {
    fileRecordId: uploaded.recordId,
    proofKind: "Photo",
    caption,
  });

  return updateChecklistItem(item.checklistRunItemId, {
    expectedRevision: attached.itemRevision ?? item.revision,
    status: "Completed",
    responseText: "Completed with attached photo evidence.",
  });
}

export async function requestSignoff(checklistRunId: string, requestId: string) {
  const current = await getChecklistRun(checklistRunId);
  return submitChecklistForSignoff(checklistRunId, {
    expectedRevision: current.revision,
    requestId,
  });
}

Create the requestId once with crypto.randomUUID() and keep that same value when retrying one logical submission. Generate a new ID only for a genuinely new submit attempt after the run has been edited. The current SDK list helper deliberately retrieves at most the first 100 authorized runs; use the module's bounded server pagination contract when building a larger administrative catalog. Approval and rejection happen through the existing Universal Inbox Workflow approval contract, not by writing checklist status directly.

Optional starter styling

Import this beside the custom component or replace it entirely. Presentation does not change the authenticated data binding or server authorization:

.custom-checklists { width: 100%; max-width: none; }
.custom-checklists > header {
  align-items: end;
  display: flex;
  gap: 1rem;
  justify-content: space-between;
}
.custom-checklists__runs {
  display: grid;
  gap: .75rem;
  list-style: none;
  margin: 1rem 0;
  padding: 0;
}
.custom-checklists__runs > li {
  background: var(--surface, #fff);
  border: 1px solid var(--line, #d8dee8);
  border-radius: .75rem;
}
.custom-checklists__runs button {
  align-items: center;
  background: transparent;
  border: 0;
  color: inherit;
  display: flex;
  gap: 1rem;
  justify-content: space-between;
  padding: 1rem;
  text-align: left;
  width: 100%;
}
.custom-checklists__runs span { display: grid; gap: .25rem; }
.custom-checklists__detail {
  background: var(--surface-muted, #f7f9fc);
  border-radius: .75rem;
  padding: 1rem;
}
@media (max-width: 640px) {
  .custom-checklists > header,
  .custom-checklists__runs button { align-items: stretch; flex-direction: column; }
}

Exact lifecycle and data path

PurposeMethod and routeImportant contract
List templatesGET /api/modules/checklists-signoffs/templatesActive templates visible in the current tenant
Create templatePOST /api/modules/checklists-signoffs/templates1–1,000 unique ordered items
List runsGET /api/modules/checklists-signoffs/runsFilter by target/status; maximum 200 rows per page
Open runGET /api/modules/checklists-signoffs/runs/{checklistRunId}Authorized snapshot, items, revisions, and visible proof
Attach runPOST /api/modules/checklists-signoffs/runsTarget Record must be inside the current create/edit envelope
Update itemPUT /api/modules/checklists-signoffs/items/{checklistRunItemId}expectedRevision rejects stale edits
Upload proof bytesPOST /api/modules/files/uploadFiles validates size, signature, MIME and storage policy
Attach proofPOST /api/modules/checklists-signoffs/items/{checklistRunItemId}/proofFile and checklist must share an authorized scope
Remove proofDELETE /api/modules/checklists-signoffs/proof/{checklistItemEvidenceId}Allowed only while the run is editable
Request signoffPOST /api/modules/checklists-signoffs/runs/{checklistRunId}/submitRevision-fenced and idempotent by requestId
Approve/rejectPOST /api/inbox/items/{inboxItemId}/workflow-approvalCurrent Inbox activity and Workflow permission are rechecked

The API derives SaaS, organization, user, DataRoles and locations from verified server identity. Completing an item does not bypass its proof requirement; attaching proof does not grant permission to download that File; and submitting a run does not grant approval authority. The database returns the bounded authorized checklist projection that the component renders.

See the complete React component catalog for generated styled and unstyled block exports, or the headless application guide when the React application lives outside the BuildWithHQ tenant shell.

Build a professional Checklists & Signoffs dashboard

These six registry-backed presentation blocks let a designer turn the secured Checklists & Signoffs API into a complete admin page without writing a chart, grid, status badge, empty state, or timeline from scratch. The normal operational API begins at /api/modules/checklists-signoffs; a dashboard-wide count or trend should come from a separate purpose-built presentation binding so the browser never downloads a broad record population to calculate one number.

The ZIP contains this feature's fictional design composition at pages/first-class/checklists-signoffs-sample.json, its executable authenticated page at pages/first-class/checklists-signoffs-live.json, and the catalog-driven FirstClassPresentationGallery.tsx. Use the sample only for visual design. The live page calls the real native API and reviewed stored procedures under the signed-in user's scope.

Payload kindRuntime blockUseful Checklists & Signoffs projection
metric-setcore.metric-stripVisible runs, completion, signoff queue, and exceptions
entity-listcore.entity-listRecent authorized runs and attached business records
progress-listcore.progress-listRun distribution or item completion
series-chartcore.series-chartStarted, completed, submitted, and approved over time
data-gridcore.presentation-gridOne bounded page of runs with progress and status
timelinecore.timelineCompletion, evidence, submission, rejection, and approval events

Copy/paste design preview: all six blocks

This complete static page document renders immediately in Puck/Monaco and is useful while styling a template. Its names, counts, dates, and IDs are fictional design fixtures; static preview values are not live tenant facts.

Copy the complete six-block page JSON
{
  "blocks": [
    {
      "_id": "checklists-signoffs-metrics",
      "_type": "core.metric-strip",
      "props": {
        "title": "Checklist operations",
        "asOfUtc": "2026-09-04T18:00:00Z",
        "items": [
          {
            "key": "visible",
            "label": "Visible runs",
            "value": 84,
            "format": "number",
            "tone": "neutral"
          },
          {
            "key": "awaiting",
            "label": "Awaiting signoff",
            "value": 9,
            "format": "number",
            "tone": "warning"
          },
          {
            "key": "complete",
            "label": "Items complete",
            "value": 72,
            "format": "percent",
            "tone": "success"
          },
          {
            "key": "attention",
            "label": "Need attention",
            "value": 4,
            "format": "number",
            "tone": "danger"
          }
        ]
      },
      "children": []
    },
    {
      "_id": "checklists-signoffs-recent",
      "_type": "core.entity-list",
      "props": {
        "title": "Recent checklist runs",
        "hasMore": true,
        "items": [
          {
            "id": "checklists-signoffs-sample-1",
            "recordId": "checklists-signoffs-record-1",
            "primary": "North Wing closeout",
            "secondary": "WO-1048 - 18 of 20 items",
            "status": {
              "key": "ready-for-signoff",
              "label": "Ready for signoff",
              "tone": "warning"
            },
            "trailing": "2 proofs"
          },
          {
            "id": "checklists-signoffs-sample-2",
            "recordId": "checklists-signoffs-record-2",
            "primary": "North Wing closeout - Follow-up",
            "secondary": "WO-1048 - 18 of 20 items - Updated two hours ago by the assigned owner",
            "status": {
              "key": "in-review",
              "label": "In review",
              "tone": "primary"
            },
            "trailing": "Today"
          },
          {
            "id": "checklists-signoffs-sample-3",
            "recordId": "checklists-signoffs-record-3",
            "primary": "North Wing closeout - West region",
            "secondary": "WO-1048 - 18 of 20 items - Related to three visible records at the Reno location",
            "status": {
              "key": "on-track",
              "label": "On track",
              "tone": "success"
            },
            "trailing": "3 related"
          },
          {
            "id": "checklists-signoffs-sample-4",
            "recordId": "checklists-signoffs-record-4",
            "primary": "North Wing closeout - Customer response",
            "secondary": "WO-1048 - 18 of 20 items - Waiting for an external response before work can continue",
            "status": {
              "key": "scheduled",
              "label": "Scheduled",
              "tone": "warning"
            },
            "trailing": "Tomorrow"
          },
          {
            "id": "checklists-signoffs-sample-5",
            "recordId": "checklists-signoffs-record-5",
            "primary": "North Wing closeout - Regional operations review with a deliberately long title",
            "secondary": "WO-1048 - 18 of 20 items - This deliberately longer supporting line verifies wrapping, truncation, responsive spacing, and dense dashboard behavior.",
            "status": {
              "key": "needs-attention",
              "label": "Needs attention",
              "tone": "danger"
            },
            "trailing": "Review",
            "tertiary": "Long-content fixture: verify keyboard focus, wrapping, narrow columns, and mobile overflow before publishing."
          },
          {
            "id": "checklists-signoffs-sample-6",
            "recordId": "checklists-signoffs-record-6",
            "primary": "North Wing closeout - Completed preview",
            "secondary": "WO-1048 - 18 of 20 items - Closed after review with its related evidence retained",
            "status": {
              "key": "complete",
              "label": "Complete",
              "tone": "success"
            },
            "trailing": "Closed"
          }
        ]
      },
      "children": []
    },
    {
      "_id": "checklists-signoffs-bystatus",
      "_type": "core.progress-list",
      "props": {
        "title": "Runs by status",
        "items": [
          {
            "key": "draft",
            "label": "Draft",
            "value": 18,
            "maximum": 84,
            "displayValue": "18",
            "tone": "neutral",
            "status": {
              "key": "draft",
              "label": "Draft",
              "tone": "neutral"
            }
          },
          {
            "key": "active",
            "label": "In progress",
            "value": 41,
            "maximum": 84,
            "displayValue": "41",
            "tone": "primary",
            "status": {
              "key": "active",
              "label": "In progress",
              "tone": "primary"
            }
          },
          {
            "key": "approved",
            "label": "Approved",
            "value": 25,
            "maximum": 84,
            "displayValue": "25",
            "tone": "success",
            "status": {
              "key": "approved",
              "label": "Approved",
              "tone": "success"
            }
          }
        ]
      },
      "children": []
    },
    {
      "_id": "checklists-signoffs-trend",
      "_type": "core.series-chart",
      "props": {
        "title": "Checklist throughput",
        "variant": "bar",
        "defaultPeriodKey": "d7",
        "periods": [
          {
            "key": "d7",
            "label": "7 days",
            "labels": [
              "Fri",
              "Sat",
              "Sun",
              "Mon",
              "Tue",
              "Wed",
              "Thu"
            ],
            "series": [
              {
                "key": "primary",
                "label": "Runs started",
                "tone": "primary",
                "values": [
                  8,
                  5,
                  4,
                  12,
                  15,
                  11,
                  17
                ]
              },
              {
                "key": "secondary",
                "label": "Runs approved",
                "tone": "success",
                "values": [
                  6,
                  4,
                  3,
                  9,
                  12,
                  10,
                  14
                ]
              }
            ]
          }
        ]
      },
      "children": []
    },
    {
      "_id": "checklists-signoffs-table",
      "_type": "core.presentation-grid",
      "props": {
        "title": "Visible checklist runs",
        "columns": [
          {
            "key": "checklist",
            "label": "Checklist",
            "type": "text",
            "align": "left"
          },
          {
            "key": "target",
            "label": "Attached record",
            "type": "text",
            "align": "left"
          },
          {
            "key": "progress",
            "label": "Progress",
            "type": "number",
            "align": "right"
          },
          {
            "key": "status",
            "label": "Status",
            "type": "status",
            "align": "left"
          },
          {
            "key": "updated",
            "label": "Updated",
            "type": "date",
            "align": "left"
          }
        ],
        "rows": [
          {
            "id": "checklists-signoffs-row-1",
            "recordId": "checklists-signoffs-record-1",
            "cells": {
              "checklist": "North Wing closeout",
              "target": "WO-1048",
              "progress": 90,
              "status": {
                "key": "ready",
                "label": "Ready for signoff",
                "tone": "warning"
              },
              "updated": "2026-09-04T17:45:00Z"
            }
          },
          {
            "id": "checklists-signoffs-row-2",
            "recordId": "checklists-signoffs-record-2",
            "cells": {
              "checklist": "North Wing closeout - Follow-up",
              "target": "WO-1048",
              "progress": 91,
              "status": {
                "key": "in-review",
                "label": "In review",
                "tone": "primary"
              },
              "updated": "2026-09-04T15:42:00Z"
            }
          },
          {
            "id": "checklists-signoffs-row-3",
            "recordId": "checklists-signoffs-record-3",
            "cells": {
              "checklist": "North Wing closeout - West region",
              "target": "WO-1048",
              "progress": 92,
              "status": {
                "key": "on-track",
                "label": "On track",
                "tone": "success"
              },
              "updated": "2026-09-04T12:18:00Z"
            }
          },
          {
            "id": "checklists-signoffs-row-4",
            "recordId": "checklists-signoffs-record-4",
            "cells": {
              "checklist": "North Wing closeout - Customer response",
              "target": "WO-1048",
              "progress": 93,
              "status": {
                "key": "scheduled",
                "label": "Scheduled",
                "tone": "warning"
              },
              "updated": "2026-09-03T21:07:00Z"
            }
          },
          {
            "id": "checklists-signoffs-row-5",
            "recordId": "checklists-signoffs-record-5",
            "cells": {
              "checklist": "North Wing closeout - Regional operations review with a deliberately long title",
              "target": "WO-1048 - This deliberately longer supporting line verifies wrapping, truncation, responsive spacing, and dense dashboard behavior.",
              "progress": 94,
              "status": {
                "key": "needs-attention",
                "label": "Needs attention",
                "tone": "danger"
              },
              "updated": "2026-09-03T16:31:00Z"
            }
          },
          {
            "id": "checklists-signoffs-row-6",
            "recordId": "checklists-signoffs-record-6",
            "cells": {
              "checklist": "North Wing closeout - Completed preview",
              "target": "WO-1048",
              "progress": 95,
              "status": {
                "key": "complete",
                "label": "Complete",
                "tone": "success"
              },
              "updated": "2026-09-02T19:14:00Z"
            }
          }
        ],
        "page": {
          "pageNumber": 1,
          "pageSize": 6,
          "totalRecords": 84,
          "totalIsExact": true,
          "hasMore": true
        }
      },
      "children": []
    },
    {
      "_id": "checklists-signoffs-timeline",
      "_type": "core.timeline",
      "props": {
        "title": "Checklist activity",
        "hasMore": true,
        "items": [
          {
            "id": "checklists-signoffs-event-1",
            "recordId": "checklists-signoffs-record-1",
            "occurredUtc": "2026-09-04T17:58:00Z",
            "title": "Evidence attached",
            "description": "A closeout photo was attached to item 18.",
            "actor": "Jordan Lee",
            "tone": "success"
          },
          {
            "id": "checklists-signoffs-event-2",
            "recordId": "checklists-signoffs-record-2",
            "occurredUtc": "2026-09-04T15:42:00Z",
            "title": "Evidence attached - Follow-up",
            "description": "A closeout photo was attached to item 18. Updated two hours ago by the assigned owner.",
            "actor": "Avery Patel",
            "tone": "primary"
          },
          {
            "id": "checklists-signoffs-event-3",
            "recordId": "checklists-signoffs-record-3",
            "occurredUtc": "2026-09-04T12:18:00Z",
            "title": "Evidence attached - West region",
            "description": "A closeout photo was attached to item 18. Related to three visible records at the Reno location.",
            "actor": "Sam Rivera",
            "tone": "success"
          },
          {
            "id": "checklists-signoffs-event-4",
            "recordId": "checklists-signoffs-record-4",
            "occurredUtc": "2026-09-03T21:07:00Z",
            "title": "Evidence attached - Customer response",
            "description": "A closeout photo was attached to item 18. Waiting for an external response before work can continue.",
            "actor": "Maya Chen",
            "tone": "warning"
          },
          {
            "id": "checklists-signoffs-event-5",
            "recordId": "checklists-signoffs-record-5",
            "occurredUtc": "2026-09-03T16:31:00Z",
            "title": "Evidence attached - Regional operations review with a deliberately long title",
            "description": "A closeout photo was attached to item 18. This deliberately longer supporting line verifies wrapping, truncation, responsive spacing, and dense dashboard behavior.",
            "actor": "Automation",
            "tone": "danger"
          },
          {
            "id": "checklists-signoffs-event-6",
            "recordId": "checklists-signoffs-record-6",
            "occurredUtc": "2026-09-02T19:14:00Z",
            "title": "Evidence attached - Completed preview",
            "description": "A closeout photo was attached to item 18. Closed after review with its related evidence retained.",
            "actor": "Jordan Lee",
            "tone": "success"
          }
        ]
      },
      "children": []
    }
  ]
}

Copy/paste React composition

Copy InteractivePresentationComponents.tsx and its optional CSS from the Professional Foundation Developer Kit, then add this module-specific composition. It is semantic and unstyled by default; pass styled after importing interactive-presentation-components.css for the supplied polished foundation. Either version accepts only a bounded already-authorized document and fails closed through the shared strict parsers.

import {
  EntityList,
  MetricStrip,
  PresentationGrid,
  ProgressList,
  SeriesChart,
  Timeline,
} from "./InteractivePresentationComponents";

export interface ChecklistsSignoffsPresentationData {
  readonly metrics: unknown;
  readonly recent: unknown;
  readonly byStatus: unknown;
  readonly trend: unknown;
  readonly table: unknown;
  readonly timeline: unknown;
}

export interface ChecklistsSignoffsPresentationProps {
  /** Pass only the already-authorized presentation document returned by the API. */
  readonly data?: ChecklistsSignoffsPresentationData | null;
  readonly loading?: boolean;
  readonly error?: boolean;
  readonly styled?: boolean;
  /** Record identity is navigation context; the detail API must authorize it again. */
  readonly onOpenRecord?: (recordId: string) => void;
}

export function ChecklistsSignoffsPresentation({
  data,
  loading = false,
  error = false,
  styled = false,
  onOpenRecord,
}: ChecklistsSignoffsPresentationProps) {
  if (error) return <p role="alert">The Checklists & Signoffs presentation could not be loaded.</p>;
  if (loading || !data) return <p role="status">Loading Checklists & Signoffs presentation...</p>;

  return (
    <main className={styled ? "bwhq-api-example" : undefined}>
      <header>
        <p>Checklists & Signoffs</p>
        <h1>Checklist operations</h1>
        <p>Completion, evidence, signoff readiness, visible runs, and recent decisions.</p>
      </header>

      <MetricStrip data={data.metrics} styled={styled} />
      <div className={styled ? "bwhq-api-example__split" : undefined}>
        <ProgressList data={data.byStatus} styled={styled} />
        <EntityList data={data.recent} styled={styled} onOpenRecord={onOpenRecord} />
      </div>
      <SeriesChart data={data.trend} styled={styled} />
      <PresentationGrid data={data.table} styled={styled} onOpenRecord={onOpenRecord} />
      <Timeline data={data.timeline} styled={styled} onOpenRecord={onOpenRecord} />
    </main>
  );
}

Copy the live, authenticated module page

This document has no placeholder key and needs no invented endpoint. Save it to a page and add that page to a User Type menu. The registered native component calls /api/modules/checklists-signoffs, uses the current tenant session, and preserves the module's real list, detail, create/update, pagination, empty, loading, and error behavior. Dynamic Records discovers the organization's real tenant-owned modules when no module key is configured.

Copy the executable live page
{
  "blocks": [
    {
      "_id": "checklists-signoffs-live",
      "_type": "module.checklists-signoffs",
      "props": {},
      "children": []
    }
  ]
}

The server derives SaaS app, organization, user, DataRoles, locations, module-specific membership/privacy, and any AI-read gate from verified identity. A returned identifier can select a detail target, but the detail or write endpoint authorizes it again. Page layout, status, tone, totals, action names, and identifiers never grant authority.

Tip

Use concise items with explicit proof rules and keep the normal checklist below the hard 1,000-item boundary. Split genuinely different phases into related runs instead of making one checklist behave like an unbounded database table.

Important

A renderer being bundled in the tenant application does not make its data visible in every app. The server returns only components and records authorized for the current app and signed-in user; unavailable or unauthorized blocks fail closed.

Capability review: 2026-09-14. For exact current technical availability, use the generated API Map and first-class module inventory.