diff --git a/defineRenderer.js b/defineRenderer.js
new file mode 100644
index 000000000..89b99ef1a
--- /dev/null
+++ b/defineRenderer.js
@@ -0,0 +1,48 @@
+var marko = require('./');
+var createRenderFunc = require('raptor-renderer').createRenderFunc;
+
+function defineRenderer(def) {
+ var template = def.template;
+ var getTemplateData = def.getTemplateData;
+ var renderer = def.renderer;
+
+ var loadedTemplate;
+
+
+ if (!renderer) {
+ // Create a renderer function that takes care of translating
+ // the input properties to a view state. Also, this renderer
+ // takes care of re-using existing widgets.
+ renderer = function renderer(input, out) {
+ var newProps = input;
+
+ if (!newProps) {
+ // Make sure we always have a non-null input object
+ newProps = {};
+ }
+
+ if (!loadedTemplate) {
+ // Lazily load the template on first render to avoid potential problems
+ // with circular dependencies
+ loadedTemplate = template.render ? template : marko.load(template);
+ }
+
+ // Use getTemplateData(state, props, out) to get the template
+ // data. If that method is not provided then just use the
+ // the state (if provided) or the input data.
+ var templateData = getTemplateData ?
+ getTemplateData(newProps, out) :
+ newProps;
+
+ // Render the template associated with the component using the final template
+ // data that we constructed
+ loadedTemplate.render(templateData, out);
+ };
+ }
+
+ renderer.render = createRenderFunc(renderer);
+
+ return renderer;
+}
+
+module.exports = defineRenderer;
\ No newline at end of file
diff --git a/docs/javascript-api.md b/docs/javascript-api.md
index 15190dbe0..6fdcd5a11 100644
--- a/docs/javascript-api.md
+++ b/docs/javascript-api.md
@@ -251,4 +251,46 @@ Default options:
*/
assumeUpToDate: NODE_ENV == null ? false : (NODE_ENV !== 'development' && NODE_ENV !== 'dev')
};
-```
\ No newline at end of file
+```
+
+# require('marko/defineRenderer')
+
+Utility module for building a UI component with both a `renderer(input, out)` (for use as a Marko custom tag renderer) a `render(input)` method (for rendering the UI component and inserting the HTML in the DOM):
+
+
+_src/components/app-hello/index.js_
+
+```javascript
+var defineRenderer = require('marko/defineRenderer');
+
+module.exports = defineRenderer({
+ template: require('./template.marko'),
+ getTemplateData: function(input) {
+ var firstName = input.firstName;
+ var lastName = input.lastName;
+
+ return {
+ fullName: firstName + ' ' + lastName
+ };
+ }
+})
+```
+
+The UI component can be used as a custom tag:
+
+```xml
+