feat(db): mesh data model — meshes, members, invites, audit log

- pgSchema "mesh" with 4 tables isolating the peer mesh domain
- Enums: visibility, transport, tier, role
- audit_log is metadata-only (E2E encryption enforced at broker/client)
- Cascade on mesh delete, soft-delete via archivedAt/revokedAt

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-04-04 21:19:32 +01:00
commit d3163a5bff
1384 changed files with 314925 additions and 0 deletions

View File

@@ -0,0 +1,98 @@
---
title: Legal pages
description: Learn how to create and update legal pages
url: /docs/web/marketing/legal
---
# Legal pages
Legal pages are defined in the `apps/web/src/app/[locale]/(marketing)/legal` directory.
TurboStarter comes with the following legal pages:
* **Terms and Conditions**: to define the terms and conditions of your application
* **Privacy Policy**: to define the privacy policy of your application
* **Cookie Policy**: to define the cookie policy of your application
For obvious reasons, **these pages are empty and you need to fill in the content.**
## Content from CMS
Content for legal pages are stored as [MDX](https://mdxjs.com/) files in [content collection](/docs/web/cms/content-collections) in `packages/cms/src/content/collections/legal` directory.
Then it's parsed and rendered as a Next.js page under corresponding slug:
```tsx title="apps/web/src/app/[locale]/(marketing)/legal/[slug]/page.tsx"
import {
CollectionType,
getContentItemBySlug,
getContentItems,
} from "@turbostarter/cms";
export default async function Page({ params }: PageParams) {
const item = getContentItemBySlug({
collection: CollectionType.LEGAL,
slug: (await params).slug,
locale: (await params).locale,
});
if (!item) {
return notFound();
}
return <Mdx mdx={item.mdx} />;
}
export function generateStaticParams() {
return getContentItems({ collection: CollectionType.LEGAL }).items.map(
({ slug, locale }) => ({
slug,
locale,
}),
);
}
```
As it's fully typesafe it also allows us to generate metadata for each page based on the frontmatter that you define in the MDX file:
```tsx title="apps/web/src/app/[locale]/(marketing)/legal/[slug]/page.tsx"
export async function generateMetadata({ params }: PageParams) {
const item = getContentItemBySlug({
collection: CollectionType.LEGAL,
slug: (await params).slug,
locale: (await params).locale,
});
if (!item) {
return notFound();
}
return getMetadata({
title: item.title,
description: item.description,
})({ params });
}
```
Read more about it in the [CMS section](/docs/web/cms/overview).
## ChatGPT prompts
Each `.mdx` file with legal content include a set of useful prompts that you can use to generate the content.
<Callout type="warn" title="Please, be aware of this!">
Please, be aware that **ChatGPT is not a lawyer** and the content generated by it should be reviewed by one before publishing. Take your time and treat the generated content as a starting point not a final document.
</Callout>
```mdx title="privacy-policy.mdx"
---
title: Privacy Policy
description: Our privacy policy outlines how we collect, use, and protect your personal information.
---
{/* 💡 You can use one of the following ChatGPT prompts to generate this 💡 */}
...
```
Feel free to add your own content or even additional pages to the `legal` collection.