refactored to allow supplying a custom template rendering function