diff --git a/ui/core/app/components/doc-link/index.hbs b/ui/core/app/components/doc-link/index.hbs
new file mode 100644
index 000000000..e654aac4a
--- /dev/null
+++ b/ui/core/app/components/doc-link/index.hbs
@@ -0,0 +1,8 @@
+
+
+
diff --git a/ui/core/app/helpers/doc-url.js b/ui/core/app/helpers/doc-url.js
new file mode 100644
index 000000000..ae10962ce
--- /dev/null
+++ b/ui/core/app/helpers/doc-url.js
@@ -0,0 +1,18 @@
+import { helper } from '@ember/component/helper';
+import { get } from '@ember/object';
+import { assert } from '@ember/debug';
+import config from '../config/environment';
+
+export default helper(function docUrl(params/*, hash*/) {
+ const baseURL = config.documentation.baseURL;
+ const docKey = params[0];
+ const configuredPath = get(config.documentation, docKey);
+ if (docKey) {
+ assert(`
+ Documentation for "${docKey}" could not be found. Please ensure that
+ this key exists under "documentation" in your app config.
+ `, configuredPath);
+ }
+ const path = configuredPath || '';
+ return `${baseURL}${path}`;
+});
diff --git a/ui/core/tests/integration/components/doc-link-test.js b/ui/core/tests/integration/components/doc-link-test.js
new file mode 100644
index 000000000..36947afcc
--- /dev/null
+++ b/ui/core/tests/integration/components/doc-link-test.js
@@ -0,0 +1,14 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'ember-qunit';
+import { render, find } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+
+module('Integration | Component | doc-link', function(hooks) {
+ setupRenderingTest(hooks);
+
+ test('it renders', async function(assert) {
+ assert.expect(1);
+ await render(hbs``);
+ assert.ok(find('.doc-link .rose-icon.large'));
+ });
+});
diff --git a/ui/core/tests/integration/helpers/doc-url-test.js b/ui/core/tests/integration/helpers/doc-url-test.js
new file mode 100644
index 000000000..d91c9eeed
--- /dev/null
+++ b/ui/core/tests/integration/helpers/doc-url-test.js
@@ -0,0 +1,29 @@
+import { module, test } from 'qunit';
+import { setupRenderingTest } from 'ember-qunit';
+import { render } from '@ember/test-helpers';
+import { hbs } from 'ember-cli-htmlbars';
+import config from 'ember-get-config';
+
+module('Integration | Helper | doc-url', function(hooks) {
+ setupRenderingTest(hooks);
+
+ test('it renders a URL generated from the documentation config', async function(assert) {
+ assert.expect(3);
+ const baseURL = config.documentation.baseURL;
+ const path = config.documentation.topics.account;
+ await render(hbs`{{doc-url 'topics.account'}}`);
+ assert.ok(baseURL);
+ assert.ok(path);
+ assert.equal(this.element.textContent.trim(), `${baseURL}${path}`);
+ });
+
+ test('it throws an error if the specified documentation path cannot be found', async function(assert) {
+ assert.expect(2);
+ const helper = this.owner.lookup('helper:doc-url');
+ assert.ok(helper.compute(['topics.account']), 'Specified document exists.')
+ assert.throws(() => {
+ helper.compute(['no.such.doc']);
+ }, 'Specified documentation was not found, so the helper threw an error.');
+ });
+
+});