diff --git a/ui/desktop/app/controllers/scopes/scope/projects/settings/index.js b/ui/desktop/app/controllers/scopes/scope/projects/settings/index.js
new file mode 100644
index 000000000..b34531637
--- /dev/null
+++ b/ui/desktop/app/controllers/scopes/scope/projects/settings/index.js
@@ -0,0 +1,8 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import Controller from '@ember/controller';
+
+export default class ScopesScopeProjectsSettingsIndexController extends Controller {}
diff --git a/ui/desktop/app/router.js b/ui/desktop/app/router.js
index 2e841f68e..12cb417bf 100644
--- a/ui/desktop/app/router.js
+++ b/ui/desktop/app/router.js
@@ -26,6 +26,9 @@ Router.map(function () {
this.route('sessions', function () {
this.route('session', { path: ':session_id' }, function () {});
});
+ this.route('settings', function () {
+ this.route('setting', function () {});
+ });
});
});
});
diff --git a/ui/desktop/app/routes/scopes/scope/projects/settings.js b/ui/desktop/app/routes/scopes/scope/projects/settings.js
new file mode 100644
index 000000000..d8c221a80
--- /dev/null
+++ b/ui/desktop/app/routes/scopes/scope/projects/settings.js
@@ -0,0 +1,8 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import Route from '@ember/routing/route';
+
+export default class ScopesScopeProjectsSettingsRoute extends Route {}
diff --git a/ui/desktop/app/routes/scopes/scope/projects/settings/index.js b/ui/desktop/app/routes/scopes/scope/projects/settings/index.js
new file mode 100644
index 000000000..531ec047a
--- /dev/null
+++ b/ui/desktop/app/routes/scopes/scope/projects/settings/index.js
@@ -0,0 +1,8 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import Route from '@ember/routing/route';
+
+export default class ScopesScopeProjectsSettingsIndexRoute extends Route {}
diff --git a/ui/desktop/app/templates/scopes/scope/projects.hbs b/ui/desktop/app/templates/scopes/scope/projects.hbs
index 6b190ac88..93ea576cc 100644
--- a/ui/desktop/app/templates/scopes/scope/projects.hbs
+++ b/ui/desktop/app/templates/scopes/scope/projects.hbs
@@ -15,6 +15,10 @@
{{t 'resources.session.title_plural'}}
+
+
+ {{t 'titles.settings'}}
+
diff --git a/ui/desktop/app/templates/scopes/scope/projects/settings.hbs b/ui/desktop/app/templates/scopes/scope/projects/settings.hbs
new file mode 100644
index 000000000..73c06654b
--- /dev/null
+++ b/ui/desktop/app/templates/scopes/scope/projects/settings.hbs
@@ -0,0 +1,14 @@
+{{!
+ Copyright (c) HashiCorp, Inc.
+ SPDX-License-Identifier: BUSL-1.1
+}}
+
+
+
+
+ {{t 'titles.settings'}}
+ {{! TODO: Add a link to the settings documentation }}
+ {{! }}
+
+
+
\ No newline at end of file
diff --git a/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs b/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs
new file mode 100644
index 000000000..d14e21775
--- /dev/null
+++ b/ui/desktop/app/templates/scopes/scope/projects/settings/index.hbs
@@ -0,0 +1,6 @@
+{{!
+ Copyright (c) HashiCorp, Inc.
+ SPDX-License-Identifier: BUSL-1.1
+}}
+
+{{outlet}}
\ No newline at end of file
diff --git a/ui/desktop/tests/acceptance/projects/settings/index-test.js b/ui/desktop/tests/acceptance/projects/settings/index-test.js
new file mode 100644
index 000000000..01f5b4950
--- /dev/null
+++ b/ui/desktop/tests/acceptance/projects/settings/index-test.js
@@ -0,0 +1,84 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import { module, test } from 'qunit';
+import { currentURL, click, visit } from '@ember/test-helpers';
+import { setupApplicationTest } from 'ember-qunit';
+import setupMirage from 'ember-cli-mirage/test-support/setup-mirage';
+import { authenticateSession } from 'ember-simple-auth/test-support';
+import WindowMockIPC from '../../../helpers/window-mock-ipc';
+
+module('Acceptance | projects | settings | index', function (hooks) {
+ setupApplicationTest(hooks);
+ setupMirage(hooks);
+
+ const instances = {
+ scopes: {
+ global: null,
+ org: null,
+ project: null,
+ },
+ authMethods: {
+ global: null,
+ },
+ target: null,
+ target2: null,
+ session: null,
+ };
+
+ const urls = {
+ scopes: {
+ global: null,
+ org: null,
+ },
+ authenticate: {
+ global: null,
+ methods: {
+ global: null,
+ },
+ },
+ projects: null,
+ targets: null,
+ settings: null,
+ };
+
+ const setDefaultClusterUrl = (test) => {
+ const windowOrigin = window.location.origin;
+ const clusterUrl = test.owner.lookup('service:clusterUrl');
+ clusterUrl.rendererClusterUrl = windowOrigin;
+ };
+
+ hooks.beforeEach(function () {
+ authenticateSession();
+ // Generate scopes
+ instances.scopes.global = this.server.create('scope', {
+ id: 'global',
+ name: 'Global',
+ });
+ const globalScope = { id: 'global', type: 'global' };
+ instances.scopes.org = this.server.create('scope', {
+ type: 'org',
+ scope: globalScope,
+ });
+ const orgScope = { id: instances.scopes.org.id, type: 'org' };
+ instances.scopes.project = this.server.create('scope', {
+ type: 'project',
+ scope: orgScope,
+ });
+ urls.scopes.org = `/scopes/${instances.scopes.org.id}`;
+ urls.scopes.global = `/scopes/${instances.scopes.global.id}`;
+ urls.projects = `${urls.scopes.org}/projects`;
+ urls.settings = `${urls.projects}/settings`;
+
+ this.owner.register('service:browser/window', WindowMockIPC);
+ setDefaultClusterUrl(this);
+ });
+
+ test('can navigate to the settings page', async function (assert) {
+ await visit(urls.projects);
+ await click(`[href="${urls.settings}"]`);
+ assert.strictEqual(currentURL(), urls.settings);
+ });
+});
diff --git a/ui/desktop/tests/unit/controllers/scopes/scope/projects/settings/index-test.js b/ui/desktop/tests/unit/controllers/scopes/scope/projects/settings/index-test.js
new file mode 100644
index 000000000..c642cd49f
--- /dev/null
+++ b/ui/desktop/tests/unit/controllers/scopes/scope/projects/settings/index-test.js
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module(
+ 'Unit | Controller | scopes/scope/projects/settings/index',
+ function (hooks) {
+ setupTest(hooks);
+
+ // TODO: Replace this with your real tests.
+ test('it exists', function (assert) {
+ let controller = this.owner.lookup(
+ 'controller:scopes/scope/projects/settings/index',
+ );
+ assert.ok(controller);
+ });
+ },
+);
diff --git a/ui/desktop/tests/unit/routes/scopes/scope/projects/settings-test.js b/ui/desktop/tests/unit/routes/scopes/scope/projects/settings-test.js
new file mode 100644
index 000000000..29f4a85dd
--- /dev/null
+++ b/ui/desktop/tests/unit/routes/scopes/scope/projects/settings-test.js
@@ -0,0 +1,16 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Route | scopes/scope/projects/settings', function (hooks) {
+ setupTest(hooks);
+
+ test('it exists', function (assert) {
+ let route = this.owner.lookup('route:scopes/scope/projects/settings');
+ assert.ok(route);
+ });
+});
diff --git a/ui/desktop/tests/unit/routes/scopes/scope/projects/settings/index-test.js b/ui/desktop/tests/unit/routes/scopes/scope/projects/settings/index-test.js
new file mode 100644
index 000000000..e27c7aca1
--- /dev/null
+++ b/ui/desktop/tests/unit/routes/scopes/scope/projects/settings/index-test.js
@@ -0,0 +1,16 @@
+/**
+ * Copyright (c) HashiCorp, Inc.
+ * SPDX-License-Identifier: BUSL-1.1
+ */
+
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Route | scopes/scope/projects/settings/index', function (hooks) {
+ setupTest(hooks);
+
+ test('it exists', function (assert) {
+ let route = this.owner.lookup('route:scopes/scope/projects/settings/index');
+ assert.ok(route);
+ });
+});