> ## Documentation Index
> Fetch the complete documentation index at: https://learn.nextedy.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Write Page Scripts with Velocity

> Use Velocity page scripts in Nextedy GANTT to pre-process widget parameters on the server before the Gantt chart renders, enabling dynamic baselines, markers, and data-driven configuration.

export const LastReviewed = ({date}) => {
  if (!date) return null;
  const formatted = new Date(`${date}T00:00:00Z`).toLocaleDateString("en-US", {
    year: "numeric",
    month: "long",
    day: "numeric",
    timeZone: "UTC"
  });
  return <p className="mt-10 text-sm text-gray-400 dark:text-zinc-500 not-prose">
      Last reviewed on {formatted}
    </p>;
};

## How Page Scripts Work

Page scripts run on the Polarion server using the Apache Velocity template engine. The rendered output is then embedded into the Gantt widget as JavaScript. This means you can use Velocity expressions to access Polarion data (projects, users, plans, work items) and inject dynamic values into the Gantt configuration.

<Frame>
  <img src="https://mintcdn.com/none-17b4493f/umKaPvHwUHw-ZQFM/gantt/diagrams/guides/scripting/page-script/diagram-1.svg?fit=max&auto=format&n=umKaPvHwUHw-ZQFM&q=85&s=f40f0204ceaad0bd70f5521fbd3bd5b0" alt="diagram" style={{ maxWidth: "560px", width: "100%" }} width="560" height="70" data-path="gantt/diagrams/guides/scripting/page-script/diagram-1.svg" />
</Frame>

A common use is a page script that reads a page parameter (for example a `department` parameter) and injects it into the widget's query so the Gantt shows only the matching work items:

<Frame>
  <img src="https://mintcdn.com/none-17b4493f/DW7SPQWol8VdzZS9/gantt/images/48001231111/1.png?fit=max&auto=format&n=DW7SPQWol8VdzZS9&q=85&s=1bfcb8608e6920b079b98fbe7ee24285" alt="A 'department' Page Parameter referenced in the Gantt widget Query field to filter which work packages are shown" width="1774" height="582" data-path="gantt/images/48001231111/1.png" />
</Frame>

<Frame>
  <img src="https://mintcdn.com/none-17b4493f/DW7SPQWol8VdzZS9/gantt/images/48001231111/2.png?fit=max&auto=format&n=DW7SPQWol8VdzZS9&q=85&s=ed97d687ef1ac545cd442f9e70f1a1e3" alt="Selecting a department value for the Page Parameter that the query field uses to filter the Gantt" width="2850" height="444" data-path="gantt/images/48001231111/2.png" />
</Frame>

A page script can also walk up the parent hierarchy and add the parents of the selected items to the chart, using `$pageContext` to pass the assembled query back to the widget's Query field:

<Frame>
  <img src="https://mintcdn.com/none-17b4493f/DW7SPQWol8VdzZS9/gantt/images/48001231111/3.png?fit=max&auto=format&n=DW7SPQWol8VdzZS9&q=85&s=787689d516ef5b072210afbd70453997" alt="Velocity page script iterating two parent levels and writing the assembled parentQ value into the Query field so parent items appear on the Gantt" width="2938" height="674" data-path="gantt/images/48001231111/3.png" />
</Frame>

## Available Velocity Context Variables

The following objects are available inside page scripts:

| Variable          | Type             | Purpose                     |
| ----------------- | ---------------- | --------------------------- |
| `$project`        | Polarion project | Current project reference   |
| `$user`           | Polarion user    | Current logged-in user      |
| `$trackerService` | Polarion service | Query work items and plans  |
| `$page`           | Wiki page        | Current page reference      |
| `config`          | Gantt config     | Widget configuration object |
| `markerFactory`   | Marker factory   | Create timeline markers     |

## Create a Baseline Comparison Page

This example creates a portal page that lists project baselines and opens the Gantt chart with a comparison overlay.

1. Add a page parameter named `baselineRevision` of type **string** to your Gantt report page.

2. In **Widget Parameters > Advanced > Item Script**, add the baseline loading logic:

   ```javascript theme={null}
   var revision = config.getPageParameters().get("baselineRevision");
   if(revision && revision.length > 0){
       var origWi = wi.getDataSvc().getVersionedInstance(wi.uri, revision);
       task.planned_start_date = util.getDate(origWi, "start");
       task.planned_duration = util.getDuration(origWi, "initialEstimate");
   }
   ```

3. Create a separate Wiki page with this Velocity snippet to list baselines:

   ```velocity theme={null}
   #set($projectId = $page.reference.projectId)
   #set($ganttPagePath = "/project/$projectId/wiki/Planning/Gantt")
   #set($project = $trackerService.getTrackerProject($projectId))
   &lt;ul&gt;
   #foreach($b in $project.baselinesManager.baselines)
       &lt;li&gt;
           &lt;a target="_blank"
              href="/gantt/polarion/#$ganttPagePath?baselineRevision=$b.getBaseRevision()">
               <b>$b.name</b> - $b.getBaseRevision()
           &lt;/a&gt;
           &lt;br/&gt;$b.baseRevisionObject.created
       &lt;/li&gt;
   #end
   &lt;/ul&gt;
   ```

<Tip title="Adjust field names to your mapping">
  The field names in `util.getDate(origWi, "start")` and `util.getDuration(origWi, "initialEstimate")` must match the field names in your widget Data Mapping section. If you use `plannedStart` and `duration`, update the script accordingly.
</Tip>

## Add Dynamic Markers with Velocity

Use the `markerFactory` in the **Markers Script** to create timeline markers from Polarion data. For example, load iteration boundaries from plans:

```javascript theme={null}
markerFactory.addPlanMarkers(
    "template.id:iteration AND project.id:" + config.getContextProjectId(),
    "blue"
)
```

Or load project time points using the Polarion API:

```javascript theme={null}
var timePoints = trackerService.getTrackerProject("$projectId")
    .getTimePoints().iterator();
while(timePoints.hasNext()){
    var tp = timePoints.next();
    var marker = markerFactory.addMarker();
    marker.setText(tp.getName());
    marker.setDate(tp.getTime().getDate());
    marker.setColor("fuchsia");
}
```

<Warning title="Polarion 2304+ getter syntax">
  If you are on Polarion 2304 or later, use getter methods like `tp.getName()` and `tp.getTime().getDate()` instead of direct property access like `tp.name` and `tp.time.date`. See [Migrate Scripts for Polarion 2304+](/gantt/guides/scripting/script-migration-2304) for details.
</Warning>

## Verify Your Changes

After saving the page, reload the Gantt chart. You should now see:

* Baseline comparison bars rendered below current task bars (if a baseline revision is selected)
* Dynamic markers appearing as vertical lines on the Gantt timeline
* Velocity-generated values correctly resolved in the widget output

## See Also

* [Write Gantt Config Scripts](/gantt/guides/scripting/gantt-config-script) for client-side global configuration
* [Write Item Scripts](/gantt/guides/scripting/item-script-basics) for per-task customization
* [Create Markers with Scripts](/gantt/guides/scripting/marker-scripts) for detailed marker scripting
* [Compare Schedule with Baselines](/gantt/guides/visualization/baselines-comparison) for baseline features
* [Configure Page Parameters](/gantt/guides/layout/page-parameters) for page parameter setup

<LastReviewed date="2026-07-07" />
