# Displaying an HTML Report on a Workflow Results Page GNPS2 workflows can expose a generated or static HTML file as an embedded view on the task results page. The general pattern has three parts: 1. Put the HTML source in the workflow repository. 2. Publish the HTML file into the task's `nf_output` directory. 3. Register the published path as an `htmlfile` view in `workflowdisplay.yaml`. The published filename is the contract between the workflow and the display configuration. Keep it stable even if the source template or the process that creates it changes. ## 1. Add the HTML page Store the page with the workflow's other runtime assets, for example: ```text bin/ report.html ``` The page may be a completely static report, a file generated by a workflow process, or a client-side application that loads other task outputs. Prefer a self-contained page where practical. If it uses CDN scripts, fonts, images, or APIs, those resources must be reachable from the user's browser and permitted by the embedding environment. A minimal task-aware page looks like this: ```html Workflow report

Workflow report

Loading...

``` Use `textContent` for untrusted values. If values must become markup, escape or sanitize them before assigning them to `innerHTML`. ## 2. Publish the HTML artifact Add a Nextflow process that copies the page into a predictable output folder: ```nextflow process publishHTMLReport { publishDir "${_publishdir}/visualizations", mode: 'copyNoFollow' output: path 'report.html' script: """ ln -sf ${TOOL_FOLDER}/report.html report.html """ } ``` Call the process from the workflow entry point: ```nextflow workflow Main { // Run the analysis processes. publishHTMLReport() } ``` With the common convention `_publishdir = "${params.publishdir}/nf_output"`, this publishes: ```text nf_output/visualizations/report.html ``` `copyNoFollow` is important in the symlink example because it publishes the HTML content rather than leaving a link to a work-directory or repository path. A process that directly generates or copies a regular HTML file may use the workflow's normal `copy` mode instead. If the report is generated from process outputs, declare those files as process inputs and write `report.html` in the process script. Do not rely on execution order alone: Nextflow dependencies should be expressed through channels. ## 3. Register the results-page view Add a unique view to `workflowdisplay.yaml`: ```yaml - name: Interactive Report displayname: Interactive Report viewname: interactive_report displaytype: htmlfile parameters: filename: nf_output/visualizations/report.html task: "[task]" error_missingfile: "Report not yet produced" ``` The `filename` must exactly match the path published by Nextflow, relative to the task root. `viewname` should be unique within the file. Pass `task: "[task]"` when the HTML reads its task ID from the query string or loads other files from the task. For a static page that does not need task context, the minimal form is: ```yaml - name: Report displayname: Report viewname: report displaytype: htmlfile parameters: filename: nf_output/report.html ``` ## Loading other task outputs An interactive report should fetch published task files through the task file endpoint rather than assuming that a relative URL beside the HTML will resolve: ```text /resultfile?task=&file=nf_output/path/to/output.tsv ``` Always URL-encode both the task ID and file path. Treat missing or incomplete outputs as normal states: a workflow can fail after publishing the report, a view can load while files are still being published, and some workflow modes may intentionally omit a dataset. Show a useful empty or error state instead of leaving the page stuck on a loading message. Other GNPS2 services can be called in the same task-aware way when appropriate. For example, a task-internal spectrum can be identified by a USI such as: ```text mzspec:GNPS2:TASK--nf_output/path/to/file.mgf:scan: ``` Keep service-specific URLs and output paths in named constants near the top of the script so the report is easy to adapt. ## Recommended behavior - Keep all required workflow artifacts beneath `nf_output` and use stable, explicit paths. - Make the layout responsive because the page is displayed inside an iframe. - Expect the iframe to be sandboxed; do not depend on access to the parent page or on `window.location.origin` always containing the server origin. - Open external links with `target="_blank"`; add `rel="noopener noreferrer"`. - Encode URL components and escape user- or workflow-supplied text. - Cache repeated API requests and lazy-load expensive visualizations for large reports. - Provide loading, empty, partial-data, and request-failure states. - Avoid placing secrets in the HTML or JavaScript. Everything delivered to the browser is visible to the user. ## Verification checklist Before merging the view: - Confirm the workflow publishes the HTML at the configured `filename`. - Confirm the process is invoked in every workflow mode that should show the report. - Open the result page and verify that the HTML renders inside the embedded view. - Verify task-aware requests with a real task ID, including paths containing spaces or punctuation. - Test missing and empty data, failed workflows, and modes that omit optional outputs. - Check the browser console for sandbox, mixed-content, CORS, and content security policy errors. - Test the page at narrow and wide viewport sizes. In short, the reusable interface is: ```text HTML source or generator -> Nextflow publishDir under nf_output -> matching workflowdisplay.yaml htmlfile filename -> embedded task-results view ```