diff --git a/src/features/legal/errors.js b/src/features/legal/errors.js
new file mode 100644
index 0000000..52405c4
--- /dev/null
+++ b/src/features/legal/errors.js
@@ -0,0 +1,22 @@
+/*
+Copyright 2026 Seekra
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+export class FetchError extends Error {
+ constructor (message) {
+ super(message);
+ this.name = 'FetchError';
+ };
+};
diff --git a/src/features/legal/services/fetchLegalContent.js b/src/features/legal/services/fetchLegalContent.js
new file mode 100644
index 0000000..663ce9d
--- /dev/null
+++ b/src/features/legal/services/fetchLegalContent.js
@@ -0,0 +1,44 @@
+/*
+Copyright 2026 Seekra
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import { FetchError } from '../errors';
+import { getAssetsUrl } from '@/config/env';
+
+const fetchHtml = async function fetchHtml (url, options) {
+ let response;
+ try {
+ response = await fetch(url, options);
+ } catch (err) {
+ if (err instanceof TypeError) throw new FetchError(err);
+ else throw err;
+ }
+ if (response.ok) return await response.text();
+ else throw new FetchError();
+};
+
+export const getLegalNotice = async function getLegalNotice () {
+ const legalNoticeUrl = new URL('legal/legal_notice.html', getAssetsUrl()).href;
+ const html = await fetchHtml(legalNoticeUrl);
+
+ const parser = new DOMParser();
+ const doc = parser.parseFromString(html, 'text/html');
+
+ const legalNoticeContainer = doc.querySelector('main') ?? doc.body;
+ legalNoticeContainer.querySelectorAll('a').forEach(
+ (link) => link.classList.add('link')
+ );
+ return legalNoticeContainer.innerHTML;
+};
diff --git a/src/features/legal/views/LegalNoticeView.vue b/src/features/legal/views/LegalNoticeView.vue
index 631eaed..196a9f7 100644
--- a/src/features/legal/views/LegalNoticeView.vue
+++ b/src/features/legal/views/LegalNoticeView.vue
@@ -14,5 +14,34 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
+
+
+
+
+