Skip to main content

Legal documents

Publish Privacy Policy, Terms of Service, Legal Notice, and Data Processing Agreement from markdown in shellui.config.ts. ShellUI renders the content in the shell—no separate legal site or navigation item is required.

Legal pages are public: they work without sign-in and sit on dedicated routes outside the main app layout (no sidebar). Signed-in users can also open the same content from Settings.

What ShellUI does in the UI

When at least one document has non-empty markdown, ShellUI:

  • Registers public routes under /legal for the index and each configured document.
  • Shows footer links on the login page (root window only, not when login runs inside an iframe).
  • Adds Settings → System → Legal documents with a tab per document and inline markdown preview.

If every key is missing or empty, legal routes stay registered but show “not configured” copy, login footer links are hidden, and the Settings entry is omitted.

Configuration

Add legalDocuments to shellui.config.ts or shellui.config.json. Each property is a markdown string loaded at config read time (not a URL).

TypeScript with files on disk

Keep long text in legal/*.md and load it when the config is evaluated:

import type { ShellUIConfig } from '@shellui/core';
import { readFileSync } from 'node:fs';

const config: ShellUIConfig = {
title: 'My App',
legalDocuments: {
privacyPolicy: readFileSync(new URL('./legal/privacy-policy.md', import.meta.url), 'utf8'),
termsOfService: readFileSync(new URL('./legal/terms-of-service.md', import.meta.url), 'utf8'),
legalNotice: readFileSync(new URL('./legal/legal-notice.md', import.meta.url), 'utf8'),
dataProcessingAgreement: readFileSync(
new URL('./legal/data-processing-agreement.md', import.meta.url),
'utf8',
),
},
};

export default config;

JSON config

Inline markdown or load strings in a small build step; the config shape is the same:

{
"title": "My App",
"legalDocuments": {
"privacyPolicy": "# Privacy Policy\n\n…",
"termsOfService": "# Terms of Service\n\n…"
}
}

Supported keys

Config keyDefault title in UIPublic path
privacyPolicyPrivacy Policy/legal/privacy-policy
termsOfServiceTerms of Service/legal/terms-of-service
legalNoticeLegal Notice/legal/legal-notice
dataProcessingAgreementData Processing Agreement/legal/data-processing-agreement

Types are defined as LegalDocumentsConfig on ShellUIConfig in @shellui/core.

Partial configuration

Omit keys you do not need, or pass an empty string. getLegalDocuments() only includes entries whose value is a non-empty string after trim(). Those documents are excluded from login links, the /legal index list, and Settings tabs.

Direct URLs

Share or link to these paths on the shell origin (for example http://localhost:4000 in development):

PathView
/legalIndex listing every configured document
/legal/privacy-policyPrivacy Policy
/legal/terms-of-serviceTerms of Service
/legal/legal-noticeLegal Notice
/legal/data-processing-agreementData Processing Agreement

Document pages include a Back to login link. The index page lists documents and also links back to /login.

These routes are not part of your navigation array. They do not appear in the sidebar and are not iframe targets for microfrontends.

Login page

On /login, configured documents appear as small text links in a footer below the sign-in form. Links use in-app routing (react-router) to the /legal/... paths.

The footer is rendered only in the top-level login view (window.parent === window). If login is embedded in an iframe, legal links are not shown on that surface.

Settings

Open the built-in settings route (default /__settings), then System → Legal documents (/__settings/legal-documents).

The panel shows one button per document; the selected document’s markdown is rendered below. This route appears only when getLegalDocuments(config) returns at least one document.

Settings labels follow the active locale (settings.routes.legalDocuments in English and French).

Markdown rendering

Content is rendered with react-markdown and ShellUI typography (headings, paragraphs, lists, blockquotes, inline code). Links in markdown open in a new tab with rel="noreferrer".

On standalone legal and settings views, a breadcrumb links Legal documents → document title. Breadcrumbs are hidden when the content is shown inside an iframe.

Use markdown headings (#, ##, ###) to structure long policy text. The renderer supplies document-level styling; you do not need to ship CSS for legal pages.

your-app/
├── shellui.config.ts
└── legal/
├── privacy-policy.md
├── terms-of-service.md
├── legal-notice.md
└── data-processing-agreement.md

After editing markdown, restart or rely on config watch (shellui start) so the dev server reloads shellui.config.ts.