There's three ways I can think of doing this:
parameterize a template so the customer can override with their own composition:
CustomerTemplate.page, (used via /apex/CustomerTemplate?template=CustomerComposition)
<apex:page renderas="pdf">
<apex:composition template="{!BLANKVALUE($CurrentPage.parameters.template, $Page.ManagedTemplate)}">
<apex:define name="data">customer's own content</apex:define>
</apex:composition>
</apex:page>
ManagedTemplate.page, (an exemplary/fallback template shows the customer what's needed)
<apex:page>
<!-- put your own data here -->
<apex:insert name="data" /><!-- put the customer's content here -->
<!-- put your own data here -->
</apex:page>
use VF Dynamic Bindings to make a dependency-free example your customer can deploy/modify
UnmanagedComposition.page (can be installed separately and edited by the customer)
<apex:page>
<apex:composition template="{!$Page['ns__ManagedTemplate']}">
<apex:define name="content">Herp derp</apex:define>
</apex:composition>
</apex:page>
ManagedTemplate.page (your own data with allowance for customization above/below)
<apex:page>
<apex:insert name="header" /><!-- inject the header defined by the customer -->
<!-- put your own part of the content here -->
<apex:insert name="footer /><!-- inject the footer defined by the customer -->
</apex:page>
create a global
controller for use by a VF Component created by your customer (detailed control):
ManagedController.cls
global with sharing class ManagedController {
global List<Case> CasesProp {get; set;}
global String getProperty() {return '...';}
}
CustomerComponent.component
<apex:component controller="ns__ManagedController">
<apex:attribute name="cases" type="Case[]" assignTo="CasesProp" description="..." />
<apex:repeat value="{!CasesProp}" var="case">
eg {!Property} ...
</apex:repeat>
<apex:component>
The three solutions do address slightly different requirements. The first one allows you to package everything up with an out-of-the-box default look and feel.
Number two is very easy for the customer to create a dumb/flat header and footer to sandwich around whatever data or content you are trying to surface.
Third solution exposes controller logic to the customer so they have full control over what they surface and how, but requires them to reinvent a lot of your VF to do that.