Programmable templates

LP reports are HTML, Tailwind and Handlebars – anything you can build on a web page, you can put in a PDF. With a full helper reference.

Reporting requirements are bespoke. Every fund has its own corporate identity, its own idea of what belongs on a company card, its own LP-specific appendices, and an LPA that dictates half the layout. Template builders with a fixed set of blocks run out of room quickly.

Fundra's reports are programmable templates: HTML, Tailwind classes and Handlebars expressions, rendered in a browser and printed to PDF. Anything you can build on a web page – layouts, charts, tables, custom typography, background artwork, your own brand system – you can put in a report.

While Fundra comes with a state-of-the-art template library built on industry best practices and leading fund reporting standards, every template is fully customizable. After all, LP reporting is more than a compliance exercise–it's your primary communication channel for building trust, demonstrating performance, and strengthening relationships with your investors.

<header class="flex items-center justify-between">
  <div class="flex flex-col items-start gap-y-1">
    <h3 class="text-sm font-medium uppercase text-neutral-500">
      Quarterly Report – {{fund.name}}
    </h3>
    <h1 class="text-3xl font-bold">{{company.name}}</h1>
    <h6 class="text-md tracking-wide text-neutral-400">{{company.legal_name}}</h6>
  </div>
  <img src="{{company.logo_url}}" class="size-20 rounded-xl border shadow-sm" />
</header>

Drafting the narrative

Layout is only half of a report. The other half is the writing, and Fundra drafts it from what the portfolio has already told you: the quarter's investor updates, board notes and KPI movements become a first draft of a company section or a portfolio summary, rather than a blank page.

Turn on Use my tone of voice and the model takes your previous reports into account, adapting to how your firm writes over time – so the draft sounds like your last LP letter instead of like a chatbot. It's a starting point to edit, not a send-ready document.

Tone of voice is currently in beta.

Templates aligned with Invest Europe reporting guidelines are available as a starting point if you'd rather not build a layout from scratch.

How a report is put together

A report is a set of sections, each with its own template, header, footer and page setup – orientation, margins and page size:

SectionTypical content
cover_pageTitle page with fund branding
executive_summaryThe quarter's narrative
capital_accountsLP capital account statements – usually landscape
portfolio_summaryThe portfolio table – usually landscape
company_cardOne page per portfolio company, repeated across the fund
back_pageBack cover, disclaimers, contact details

Templates are edited in Settings → Reporting, with a live preview against real data and version history, so you can iterate on a layout without touching a live report.

Writing templates

Everything in Handlebars works – {{value}}, {{#if}}, {{#each}}, {{#with}}, partials, comments. On top of that, Fundra registers the helpers below.

Two conventions worth knowing:

  • Helpers take hash arguments: {{currency fmv decimals=1 currency="EUR"}}. Some also accept a positional shorthand – {{round value 2}} is the same as {{round value decimals=2}}.
  • An unknown helper renders a red badge in the preview rather than failing silently, so typos are visible while you're editing.

Text and formatting

HelperResult
{{upper value}}Uppercase
{{trim value}}Trims surrounding whitespace
{{concat a b c}}Joins the arguments into one string
{{slugify value}}Acme Incacme-inc
{{split value by="&"}}Inserts a line break before each occurrence of by
{{markdown value}}Renders markdown – useful for AI summaries and free-text fields
{{date value format="MMM yyyy"}}Formats a date; omit format for the default
{{period months}}272 years, 3 months – for holding periods

Numbers

HelperResult
{{int value}}Whole number with thousands separators
{{round value 2}}Fixed decimals
{{number value decimals=1 prefix="" suffix=""}}Formatted number with optional prefix and suffix
{{short value}}Abbreviated: 12345671.2m
{{percentage value decimals=1}}Multiplies by 100 and appends % – pass 0.152, get 15.2%
{{currency value currency="EUR" decimals=0}}Currency code plus an abbreviated amount
{{growth "investment.fmv" decimals=1}}Change against the previous period, styled up or down
{{add a b}} {{mul a b}} {{div a b}}Arithmetic

{{currency}} and {{number}} understand Fundra's currency objects: passing a field that carries { value, currency } uses its own currency rather than the one you specify. {{growth}} takes a path as a string and compares the current record against the previous period's, so it works inside a repeated company card without extra plumbing.

Charts and visuals

{{chart}}

An area or bar chart over a series of rows – typically a company's timeseries.

{{chart data.timeseries
        metrics="revenue,ebitda"
        metricLabels="Revenue,EBITDA"
        chartType="bar"
        stacked=false
        height=260}}
OptionDefault
metrics (or keys, dataKeys)Inferred from the numeric columns present
metricLabelsThe metric names
chartType (or variant)area; use bar for bars
xKeyperiod_label if present, else date
stackedtrue for bar charts, false for area
colorsBuilt-in palette
width / height640 / 280
legendShown when there's more than one series
showValuestrue
valueDecimals0
yoyfalse – overlays the prior-year series
axesOne shared axis

Lists are comma-separated. A metric can carry a fallback with or(...), so metrics="or(billedArr,revenue)" uses ARR where a company reports it and revenue where it doesn't – handy when one template covers a whole portfolio.

Other visual helpers

HelperRenders
{{sparkline metric="investment_valuation"}}An inline sparkline from the record's timeseries
{{piechart data=segments min=0.05 other=true}}A donut chart; slices below min roll into "Other"
{{captable}}The company's cap table as a donut, by ownership
{{datagrid rows=... columns=...}}A full data grid – grouping, aggregation, formatting
{{portfolio}}The standard portfolio overview table for the fund
{{icon value}}A colour chip derived from the value, plus its label
{{flag "Germany"}}Country flag and name
{{avatar user}}Avatar image; accepts a user object or a URL
{{link value prefix="" name="" class=""}}An anchor, adding https:// when missing
{{#background}}…{{/background}}Wraps content as a full-bleed page background

Logic and arrays

HelperBehaviour
{{eq a b}} {{neq a b}}Equality, for use inside {{#if}}
{{#lt a b}}…{{else}}…{{/lt}}Block form of less-than
{{or a b empty="–"}}First truthy value, with a fallback
{{nullif value}}Turns falsy values into nothing, so {{#if}} treats 0 as absent
{{get obj "a.b.c"}}Reads a nested path
{{#each (filter companies "investment_status" "active")}}Filters by field; operator="eq" (default), "neq" or "in"
{{#limit companies 5}}…{{/limit}}Iterates the last n items
{{#join tags separator=", "}}…{{/join}}Joins an array, with an optional limit
{{maxkey rows "fmv"}}Largest value of a key across rows – useful for scaling bars
{{count_by companies "country"}}Counts grouped by a field
{{percent_by_array companies "segment" by="fmv"}}Shares by group, by count or weighted by a field – feeds {{piechart}}

Partials

PartialInserts
{{> pagenumber}}The current page number, filled in at print time
{{> executive_summary}}The executive summary written for this report

You can define your own partials in a template and reuse them across sections – a company header, a KPI row, a footer block.

Putting it together

<section class="grid grid-cols-3 gap-4">
  {{#each (filter data.fundCompanies "investment_status" "active")}}
    <div class="rounded-lg border p-4">
      <div class="flex items-center gap-2">
        {{avatar company}}
        <span class="font-medium">{{company.name}}</span>
        {{flag company.country}}
      </div>
      <dl class="mt-2 text-sm">
        <dt>FMV</dt><dd>{{currency investment.fmv}}</dd>
        <dt>MOIC</dt><dd>{{round investment.moic 1}}x</dd>
        <dt>Ownership</dt><dd>{{percentage investment.shareholding_fd}}</dd>
      </dl>
      {{chart timeseries metrics="revenue" height=90 showValues=false}}
    </div>
  {{/each}}
</section>

Because the output is HTML, your brand system carries straight over – the same fonts, colours and spacing scale as your website, applied with Tailwind classes. Custom CSS can be added per template for anything Tailwind doesn't cover, including print-specific rules like page breaks.

On this page