This commit is contained in:
Raven Scott
2026-05-29 13:15:49 -04:00
parent 5013d69ec2
commit d66d6398d3
11 changed files with 884 additions and 3 deletions
+83
View File
@@ -0,0 +1,83 @@
import type { Metadata } from 'next';
import LegalDocumentLayout from '@/components/legal/LegalDocumentLayout';
export const metadata: Metadata = {
title: 'Acceptable Use Policy - P2NS Legal',
description: 'Acceptable use of P2NS software and participation in P2NS peer networks.',
alternates: { canonical: 'https://p2ns.space/legal/acceptable-use' },
openGraph: {
title: 'Acceptable Use Policy - P2NS Legal',
url: 'https://p2ns.space/legal/acceptable-use',
siteName: 'P2NS',
type: 'website',
},
};
export default function AcceptableUsePage() {
return (
<LegalDocumentLayout
title="Acceptable Use Policy"
description="Rules for responsible use of P2NS and networks you operate."
seeAlso={[
{ href: '/legal/eula', label: 'End User License Agreement' },
{ href: '/legal/disclaimer', label: 'Disclaimer' },
]}
>
<h2>Purpose</h2>
<p>
This Acceptable Use Policy (&quot;AUP&quot;) describes prohibited and discouraged uses of P2NS
software and of networks built with it. Network operators are expected to enforce similar rules
for peers they invite.
</p>
<h2>Prohibited uses</h2>
<p>You must not use P2NS to:</p>
<ul>
<li>Violate applicable criminal, civil, or regulatory law</li>
<li>Distribute malware, phishing pages, or exploit kits</li>
<li>Harass, threaten, or discriminate against individuals or groups</li>
<li>Infringe intellectual property, privacy, or publicity rights</li>
<li>Impersonate persons, organizations, or services without authorization</li>
<li>Send unsolicited bulk messages or conduct denial-of-service attacks</li>
<li>Circumvent lawful court orders or mandated access controls where you lack authority</li>
<li>Mine cryptocurrency or abuse shared resources without operator consent</li>
</ul>
<h2>Network operator duties</h2>
<p>If you issue invites or operate a genesis or master node, you should:</p>
<ul>
<li>Know who you admit as writers on your network</li>
<li>Respond to credible abuse reports affecting your network</li>
<li>Revoke access for peers that violate this AUP or your local policies</li>
<li>Document your own terms for participants when operating public or shared networks</li>
</ul>
<h2>Content responsibility</h2>
<p>
Claims, votes, and domain records you publish are your responsibility. The Project does not
pre-screen domain claims or tunnel endpoints.
</p>
<h2>Security research</h2>
<p>
Good-faith security research is welcome when conducted ethically: obtain permission where required,
avoid harm to third parties, and report issues through responsible disclosure channels described in
the <a href="/community">Community</a> page.
</p>
<h2>Enforcement</h2>
<p>
The Project may refuse support or collaboration with parties that egregiously violate this AUP.
Operators may disconnect peers, rotate invites, or rebuild networks using documented recovery
procedures.
</p>
<h2>Reporting</h2>
<p>
Report abuse related to Project infrastructure (the Site or repository) through public issue
trackers or community contacts. For abuse on third-party networks, contact the network operator
first.
</p>
</LegalDocumentLayout>
);
}
+82
View File
@@ -0,0 +1,82 @@
import type { Metadata } from 'next';
import LegalDocumentLayout from '@/components/legal/LegalDocumentLayout';
export const metadata: Metadata = {
title: 'Disclaimer - P2NS Legal',
description: 'Disclaimer regarding P2NS network operation, DNS resolution, and security.',
alternates: { canonical: 'https://p2ns.space/legal/disclaimer' },
openGraph: {
title: 'Disclaimer - P2NS Legal',
url: 'https://p2ns.space/legal/disclaimer',
siteName: 'P2NS',
type: 'website',
},
};
export default function DisclaimerPage() {
return (
<LegalDocumentLayout
title="Disclaimer"
description="Important limitations regarding P2NS and peer-to-peer networks."
seeAlso={[
{ href: '/legal/eula', label: 'End User License Agreement' },
{ href: '/legal/acceptable-use', label: 'Acceptable Use Policy' },
]}
>
<h2>General</h2>
<p>
P2NS is experimental network infrastructure software. The P2NS open-source project provides software
and documentation without operating a commercial DNS service or guaranteeing outcomes for any
deployment.
</p>
<h2>No professional advice</h2>
<p>
Documentation on p2ns.space is for technical education. It is not legal, security, or
telecommunications advice. Consult qualified professionals before relying on P2NS in regulated or
high-risk environments.
</p>
<h2>DNS and naming</h2>
<p>
P2NS resolves names through peer consensus, not ICANN or traditional registrars. The Project does
not guarantee uniqueness, permanence, or global reachability of any name. Conflicts, forks, and
stale records can occur. Users must perform their own due diligence before trusting a resolved
endpoint.
</p>
<h2>Peer-to-peer risks</h2>
<p>
Participating in a P2NS network exposes you to other peers. Invites, writes, and consensus depend on
operator policy. Malicious or misconfigured peers may publish harmful or misleading records. You are
responsible for who you admit and what you trust.
</p>
<h2>Security and TLS</h2>
<p>
P2NS can generate a local certificate authority and per-domain TLS certificates. Trusting that CA
is your choice. Misconfiguration, expired certificates, or split networks can cause browser warnings
or interception risks if operators are negligent. The Project is not liable for incidents arising
from your PKI or proxy configuration.
</p>
<h2>Third-party content and services</h2>
<p>
Domains tunneled through Holesail or other tools may point to content the Project does not control.
Plugins and external sites linked from documentation are provided by their respective authors.
</p>
<h2>Availability</h2>
<p>
Peer networks may partition, lose quorum, or fail to sync. Masters may go offline. Storage may
corrupt. Backups and recovery procedures are the operator&apos;s responsibility.
</p>
<h2>Regulatory compliance</h2>
<p>
Operating DNS, proxies, or tunnels may require licenses, logging, or content policies in your
country. The Project does not ensure your deployment meets those obligations.
</p>
</LegalDocumentLayout>
);
}
+118
View File
@@ -0,0 +1,118 @@
import type { Metadata } from 'next';
import LegalDocumentLayout from '@/components/legal/LegalDocumentLayout';
import { P2NS_REPO_URL } from '@/lib/legal/documents';
export const metadata: Metadata = {
title: 'End User License Agreement - P2NS Legal',
description: 'EULA for downloading, installing, and running P2NS software.',
alternates: { canonical: 'https://p2ns.space/legal/eula' },
openGraph: {
title: 'End User License Agreement - P2NS Legal',
url: 'https://p2ns.space/legal/eula',
siteName: 'P2NS',
type: 'website',
},
};
export default function EulaPage() {
return (
<LegalDocumentLayout
title="End User License Agreement"
description="Terms for using P2NS software."
seeAlso={[
{ href: '/legal/open-source-license', label: 'Open Source License (ISC)' },
{ href: '/legal/disclaimer', label: 'Disclaimer' },
{ href: '/legal/acceptable-use', label: 'Acceptable Use Policy' },
]}
>
<h2>Agreement</h2>
<p>
This End User License Agreement (&quot;EULA&quot;) is between you (&quot;User&quot;) and the P2NS
open-source project (&quot;Project&quot;) for the P2NS software, including source code, binaries,
documentation, and updates obtained from the Project repository or authorized mirrors
(&quot;Software&quot;).
</p>
<p>
By downloading, installing, or using the Software, you agree to this EULA. If you do not agree, do
not use the Software.
</p>
<h2>License grant</h2>
<p>
The Software is primarily licensed under the ISC License. This EULA supplements that license with
additional terms regarding use, risk allocation, and acceptable conduct. If this EULA conflicts with
the ISC License on permissions granted by the license, the ISC License controls for those
permissions. See the <a href="/legal/open-source-license">Open Source License</a> page and the{' '}
<a href={P2NS_REPO_URL} target="_blank" rel="noopener noreferrer">
upstream repository
</a>
.
</p>
<h2>Permitted use</h2>
<p>You may use the Software to:</p>
<ul>
<li>Operate peer-to-peer DNS and related services on networks you own or are authorized to administer</li>
<li>Modify and redistribute the Software according to the ISC License</li>
<li>Integrate the Software with compatible plugins and tools described in Project documentation</li>
</ul>
<h2>Restrictions</h2>
<p>You agree not to:</p>
<ul>
<li>Use the Software in violation of applicable law or the <a href="/legal/acceptable-use">Acceptable Use Policy</a></li>
<li>Remove or obscure license notices required by the ISC License</li>
<li>Represent that the Project endorses your deployment without permission</li>
<li>Use the Software to attack, disrupt, or impersonate systems or users without authorization</li>
</ul>
<h2>Operator responsibility</h2>
<p>
If you run the Software as a network operator (master, genesis, or joiner), you are responsible for
peers you admit, domains you publish, certificates you issue, and compliance with law in your
jurisdiction. The Project does not operate your network.
</p>
<h2>Updates</h2>
<p>
The Project may release updates that change behavior, storage formats, or protocols. You are
responsible for testing upgrades and maintaining backups before applying them.
</p>
<h2>Termination</h2>
<p>
This EULA terminates automatically if you breach it. Upon termination, you must stop using the
Software, though rights and obligations under the ISC License for code you already received may
continue as stated in that license.
</p>
<h2>Disclaimer of warranties</h2>
<p>
THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
TITLE, AND NON-INFRINGEMENT. THE PROJECT DOES NOT WARRANT THAT THE SOFTWARE WILL BE ERROR-FREE,
SECURE, OR UNINTERRUPTED.
</p>
<h2>Limitation of liability</h2>
<p>
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE
LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES, OR ANY LOSS OF
DATA, PROFITS, OR GOODWILL, ARISING FROM USE OF THE SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
</p>
<h2>Export and compliance</h2>
<p>
You are responsible for complying with export control, sanctions, and telecommunications rules that
apply to cryptography, peer-to-peer networking, and DNS in your region.
</p>
<h2>Changes</h2>
<p>
The Project may update this EULA. Continued use after the posted &quot;Last updated&quot; date
constitutes acceptance of changes.
</p>
</LegalDocumentLayout>
);
}
+86
View File
@@ -0,0 +1,86 @@
import type { Metadata } from 'next';
import LegalDocumentLayout from '@/components/legal/LegalDocumentLayout';
import { P2NS_REPO_URL } from '@/lib/legal/documents';
export const metadata: Metadata = {
title: 'Open Source License - P2NS Legal',
description: 'ISC open source license summary for the P2NS software.',
alternates: { canonical: 'https://p2ns.space/legal/open-source-license' },
openGraph: {
title: 'Open Source License - P2NS Legal',
url: 'https://p2ns.space/legal/open-source-license',
siteName: 'P2NS',
type: 'website',
},
};
export default function OpenSourceLicensePage() {
return (
<LegalDocumentLayout
title="Open Source License"
description="ISC License for P2NS software."
seeAlso={[
{ href: '/legal/eula', label: 'End User License Agreement' },
{ href: '/legal/terms', label: 'Terms of Service' },
]}
>
<h2>Overview</h2>
<p>
P2NS software is distributed under the{' '}
<a href="https://opensource.org/licenses/ISC" target="_blank" rel="noopener noreferrer">
ISC License
</a>
, a permissive open-source license similar in spirit to the MIT and BSD licenses. The canonical
license text ships with the source repository.
</p>
<p>
<strong>Repository:</strong>{' '}
<a href={P2NS_REPO_URL} target="_blank" rel="noopener noreferrer">
{P2NS_REPO_URL}
</a>
</p>
<h2>Permissions</h2>
<p>Subject to the conditions below, the ISC License generally allows you to:</p>
<ul>
<li>Use the software for any purpose, including commercial use</li>
<li>Modify the source code</li>
<li>Distribute original or modified versions</li>
<li>Sublicense or incorporate the code into other works</li>
</ul>
<h2>Conditions</h2>
<p>When distributing the software or substantial portions, you must:</p>
<ul>
<li>Include the original copyright notice</li>
<li>Include the ISC License text</li>
</ul>
<h2>Disclaimer in the license</h2>
<p>
THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND. THE AUTHORS AND
COPYRIGHT HOLDERS DISCLAIM LIABILITY FOR CLAIMS OR DAMAGES ARISING FROM USE OF THE SOFTWARE, AS
STATED IN THE FULL LICENSE.
</p>
<h2>Relationship to the EULA</h2>
<p>
The <a href="/legal/eula">End User License Agreement</a> on this site adds project-specific
guidance on network operation and acceptable use. It does not replace the ISC License for source
code you receive under that license.
</p>
<h2>Third-party dependencies</h2>
<p>
P2NS depends on other open-source packages, each under its own license. See the repository{' '}
<code>package.json</code> and dependency notices for details.
</p>
<h2>Contributions</h2>
<p>
By contributing to the repository, you agree that your contributions may be distributed under the
same license as the project, unless otherwise stated in the contribution process.
</p>
</LegalDocumentLayout>
);
}
+76
View File
@@ -0,0 +1,76 @@
import type { Metadata } from 'next';
import Link from 'next/link';
import { legalDocuments, LEGAL_LAST_UPDATED, LEGAL_NOTICE } from '@/lib/legal/documents';
export const metadata: Metadata = {
title: 'Legal - P2NS',
description:
'Legal information for the P2NS open-source project and p2ns.space website: Terms of Service, Privacy Policy, EULA, and related policies.',
keywords: ['P2NS legal', 'terms of service', 'privacy policy', 'EULA', 'open source license'],
authors: [{ name: 'Raven Scott' }],
openGraph: {
title: 'Legal - P2NS',
description: 'Legal documents for the P2NS project and p2ns.space website.',
url: 'https://p2ns.space/legal',
siteName: 'P2NS',
type: 'website',
},
twitter: {
card: 'summary_large_image',
title: 'Legal - P2NS',
description: 'Legal documents for the P2NS project and p2ns.space website.',
},
alternates: {
canonical: 'https://p2ns.space/legal',
},
};
export default function LegalHubPage() {
return (
<div className="min-h-screen bg-[#111829]">
<section className="py-20 bg-gradient-to-b from-blue-50 to-white dark:from-gray-900 dark:to-gray-800">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
Legal
</h1>
<p className="text-xl text-gray-600 dark:text-gray-300 mb-4">
Policies and agreements for the P2NS open-source project and this website.
</p>
<p className="text-sm text-gray-500 dark:text-gray-400">
Last updated: {LEGAL_LAST_UPDATED}
</p>
</div>
</section>
<section className="py-20 bg-white dark:bg-gray-900">
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="mb-10 rounded-lg border border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-900/30 px-4 py-3 text-sm text-amber-900 dark:text-amber-100 max-w-4xl">
{LEGAL_NOTICE}
</div>
<div className="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
{legalDocuments.map((doc) => {
const Icon = doc.icon;
return (
<Link
key={doc.href}
href={doc.href}
className="group bg-white dark:bg-gray-800 p-6 rounded-lg border border-gray-200 dark:border-gray-700 hover:border-blue-500 dark:hover:border-blue-500 transition-all hover:shadow-lg"
>
<div className="flex items-center space-x-3 mb-4">
<div className="p-2 bg-blue-100 dark:bg-blue-900 rounded-lg group-hover:bg-blue-200 dark:group-hover:bg-blue-800 transition-colors">
<Icon className="h-6 w-6 text-blue-600 dark:text-blue-400" />
</div>
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">
{doc.title}
</h2>
</div>
<p className="text-gray-600 dark:text-gray-400">{doc.description}</p>
</Link>
);
})}
</div>
</div>
</section>
</div>
);
}
+94
View File
@@ -0,0 +1,94 @@
import type { Metadata } from 'next';
import LegalDocumentLayout from '@/components/legal/LegalDocumentLayout';
export const metadata: Metadata = {
title: 'Privacy Policy - P2NS Legal',
description: 'Privacy Policy for p2ns.space and how P2NS self-hosted software handles data locally.',
alternates: { canonical: 'https://p2ns.space/legal/privacy' },
openGraph: {
title: 'Privacy Policy - P2NS Legal',
url: 'https://p2ns.space/legal/privacy',
siteName: 'P2NS',
type: 'website',
},
};
export default function PrivacyPage() {
return (
<LegalDocumentLayout
title="Privacy Policy"
description="How this website and the P2NS software relate to your information."
seeAlso={[
{ href: '/legal/terms', label: 'Terms of Service' },
{ href: '/legal/eula', label: 'End User License Agreement' },
]}
>
<h2>Scope</h2>
<p>
This Privacy Policy describes practices for the p2ns.space website (the &quot;Site&quot;). It does
not fully describe what happens when you run P2NS on your own machinesthat depends on your
configuration, peers, and networks.
</p>
<h2>Information we collect on the Site</h2>
<p>
The Site is primarily static documentation. We do not operate user accounts or a hosted P2NS
service on p2ns.space. We do not use third-party analytics or advertising trackers on the Site at
this time.
</p>
<p>When you visit the Site, standard web hosting may automatically process:</p>
<ul>
<li>IP address and approximate region</li>
<li>Browser type, requested URL, and referrer</li>
<li>Date and time of requests</li>
<li>TLS and HTTP error logs for security and reliability</li>
</ul>
<p>
This data is used to deliver pages, protect against abuse, and troubleshoot outages. Retention
depends on the hosting provider&apos;s log policies.
</p>
<h2>Self-hosted P2NS software</h2>
<p>
P2NS runs locally on systems you control. It stores configuration, certificates, peer data, and
domain records on your devices. It communicates with other peers over peer-to-peer protocols. The
Project does not receive that data unless you choose to share it (for example by opening a public
issue or discussion).
</p>
<h2>Cookies and local storage</h2>
<p>
The Site does not set non-essential cookies for tracking. Your browser may store cache data for
performance. Theme or UI preferences, if stored, remain in your browser only.
</p>
<h2>Third-party services</h2>
<p>
Links from the Site may take you to external Git hosts, documentation, or community tools with their
own privacy practices. Review those policies before submitting personal information there.
</p>
<h2>Children</h2>
<p>The Site is not directed at children under 13, and we do not knowingly collect their information.</p>
<h2>Your choices</h2>
<ul>
<li>You may stop visiting the Site at any time.</li>
<li>You may use privacy tools or VPNs according to your local laws.</li>
<li>For software privacy, configure P2NS and your network according to your operational requirements.</li>
</ul>
<h2>Changes</h2>
<p>
We may update this Policy. Material changes will be reflected in the &quot;Last updated&quot; date on
this page.
</p>
<h2>Contact</h2>
<p>
Privacy questions may be raised through the Project&apos;s public repository or the{' '}
<a href="/community">Community</a> page.
</p>
</LegalDocumentLayout>
);
}
+104
View File
@@ -0,0 +1,104 @@
import type { Metadata } from 'next';
import LegalDocumentLayout from '@/components/legal/LegalDocumentLayout';
export const metadata: Metadata = {
title: 'Terms of Service - P2NS Legal',
description: 'Terms of Service for using the p2ns.space website and P2NS project materials.',
alternates: { canonical: 'https://p2ns.space/legal/terms' },
openGraph: {
title: 'Terms of Service - P2NS Legal',
url: 'https://p2ns.space/legal/terms',
siteName: 'P2NS',
type: 'website',
},
};
export default function TermsPage() {
return (
<LegalDocumentLayout
title="Terms of Service"
description="Rules for using the p2ns.space website."
seeAlso={[
{ href: '/legal/privacy', label: 'Privacy Policy' },
{ href: '/legal/eula', label: 'End User License Agreement' },
]}
>
<h2>Agreement</h2>
<p>
By accessing or using the p2ns.space website (the &quot;Site&quot;), you agree to these Terms of
Service. If you do not agree, do not use the Site. The Site is operated by the P2NS open-source
project (the &quot;Project&quot;) for informational and community purposes.
</p>
<h2>About the Project</h2>
<p>
P2NS is peer-to-peer DNS software distributed as open source. The Site provides documentation,
guides, and links to the software repository. Running P2NS on your own systems is governed by the{' '}
<a href="/legal/eula">End User License Agreement</a> and the{' '}
<a href="/legal/open-source-license">Open Source License</a>, not solely by these Terms.
</p>
<h2>Use of the Site</h2>
<p>You may use the Site for lawful, personal, and non-commercial reference unless we state otherwise. You agree not to:</p>
<ul>
<li>Attempt to disrupt, overload, or compromise the Site or its infrastructure</li>
<li>Scrape or automate access in a way that harms availability or violates robots directives</li>
<li>Misrepresent your affiliation with the Project or imply endorsement without permission</li>
<li>Use the Site to distribute malware or unlawful content</li>
</ul>
<h2>Content and accuracy</h2>
<p>
Documentation and examples are provided &quot;as is&quot; for education. Network software evolves;
steps may become outdated. You are responsible for verifying instructions before operating
production systems.
</p>
<h2>Third-party links</h2>
<p>
The Site may link to external projects and services (for example Holesail, Pears, or third-party Git
hosts). The Project does not control those sites and is not responsible for their content, policies,
or availability.
</p>
<h2>Intellectual property</h2>
<p>
Site branding, layout, and original prose are provided by the Project. P2NS software is licensed
separately under the ISC License. Trademarks of third parties belong to their respective owners.
</p>
<h2>Changes</h2>
<p>
We may update these Terms or the Site at any time. Continued use after changes constitutes acceptance
of the revised Terms. The &quot;Last updated&quot; date at the top of this page indicates when these
Terms were last revised.
</p>
<h2>Disclaimer of warranties</h2>
<p>
THE SITE IS PROVIDED &quot;AS IS&quot; WITHOUT WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
</p>
<h2>Limitation of liability</h2>
<p>
TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, THE PROJECT AND CONTRIBUTORS SHALL NOT BE LIABLE
FOR ANY INDIRECT, INCIDENTAL, SPECIAL, CONSEQUENTIAL, OR PUNITIVE DAMAGES ARISING FROM YOUR USE OF
THE SITE.
</p>
<h2>Governing law</h2>
<p>
These Terms are governed by applicable law in the jurisdiction where the Site operator resides,
without regard to conflict-of-law rules. Disputes should first be raised through the Project&apos;s
community channels listed on the <a href="/community">Community</a> page.
</p>
<h2>Contact</h2>
<p>
Questions about these Terms may be directed via the Project repository or community page linked from
this Site.
</p>
</LegalDocumentLayout>
);
}
+42
View File
@@ -94,6 +94,48 @@ export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
changeFrequency: 'weekly',
priority: 0.8,
},
{
url: `${baseUrl}/legal`,
lastModified: new Date(),
changeFrequency: 'yearly',
priority: 0.3,
},
{
url: `${baseUrl}/legal/terms`,
lastModified: new Date(),
changeFrequency: 'yearly',
priority: 0.3,
},
{
url: `${baseUrl}/legal/privacy`,
lastModified: new Date(),
changeFrequency: 'yearly',
priority: 0.3,
},
{
url: `${baseUrl}/legal/eula`,
lastModified: new Date(),
changeFrequency: 'yearly',
priority: 0.3,
},
{
url: `${baseUrl}/legal/disclaimer`,
lastModified: new Date(),
changeFrequency: 'yearly',
priority: 0.3,
},
{
url: `${baseUrl}/legal/acceptable-use`,
lastModified: new Date(),
changeFrequency: 'yearly',
priority: 0.3,
},
{
url: `${baseUrl}/legal/open-source-license`,
lastModified: new Date(),
changeFrequency: 'yearly',
priority: 0.3,
},
];
}
+42 -3
View File
@@ -1,12 +1,17 @@
import Link from 'next/link';
import { Github, ExternalLink } from 'lucide-react';
import { legalDocuments } from '@/lib/legal/documents';
export default function Footer() {
const primaryLegal = legalDocuments.filter((d) =>
['terms', 'privacy', 'eula'].includes(d.id)
);
return (
<footer className="border-t border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-900">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
<div className="col-span-1 md:col-span-2">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-5 gap-8">
<div className="col-span-1 md:col-span-2 lg:col-span-2">
<h3 className="text-lg font-bold mb-4 bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
P2NS
</h3>
@@ -71,15 +76,49 @@ export default function Footer() {
</li>
</ul>
</div>
<div>
<h4 className="text-sm font-semibold mb-4 text-gray-900 dark:text-gray-100">Legal</h4>
<ul className="space-y-2">
<li>
<Link href="/legal" className="text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
Legal overview
</Link>
</li>
{legalDocuments.map((doc) => (
<li key={doc.href}>
<Link
href={doc.href}
className="text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
>
{doc.title}
</Link>
</li>
))}
</ul>
</div>
</div>
<div className="mt-8 pt-8 border-t border-gray-200 dark:border-gray-800">
<p className="text-sm text-center text-gray-600 dark:text-gray-400">
© {new Date().getFullYear()} P2NS.
<span className="hidden sm:inline"> · </span>
<span className="block sm:inline mt-2 sm:mt-0">
{primaryLegal.map((doc, i) => (
<span key={doc.href}>
{i > 0 && <span className="mx-1.5">·</span>}
<Link
href={doc.href}
className="hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
>
{doc.shortTitle}
</Link>
</span>
))}
</span>
</p>
</div>
</div>
</footer>
);
}
+69
View File
@@ -0,0 +1,69 @@
import Link from 'next/link';
import { LEGAL_LAST_UPDATED, LEGAL_NOTICE } from '@/lib/legal/documents';
interface LegalDocumentLayoutProps {
title: string;
description?: string;
children: React.ReactNode;
seeAlso?: { href: string; label: string }[];
}
export default function LegalDocumentLayout({
title,
description,
children,
seeAlso,
}: LegalDocumentLayoutProps) {
return (
<div className="min-h-screen">
<section className="py-20 bg-gradient-to-b from-blue-50 to-white dark:from-gray-900 dark:to-gray-800">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
<p className="text-sm text-gray-500 dark:text-gray-400 mb-4">
<Link href="/legal" className="hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
Legal
</Link>
<span className="mx-2">/</span>
<span className="text-gray-700 dark:text-gray-300">{title}</span>
</p>
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-4">
{title}
</h1>
{description && (
<p className="text-xl text-gray-600 dark:text-gray-300">{description}</p>
)}
<p className="text-sm text-gray-500 dark:text-gray-400 mt-4">
Last updated: {LEGAL_LAST_UPDATED}
</p>
</div>
</section>
<section className="py-16 bg-white dark:bg-gray-900">
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="mb-8 rounded-lg border border-amber-200 dark:border-amber-800 bg-amber-50 dark:bg-amber-900/30 px-4 py-3 text-sm text-amber-900 dark:text-amber-100">
{LEGAL_NOTICE}
</div>
<div className="prose prose-lg dark:prose-invert max-w-none text-gray-600 dark:text-gray-300">
{children}
</div>
{seeAlso && seeAlso.length > 0 && (
<div className="mt-12 pt-8 border-t border-gray-200 dark:border-gray-700">
<h2 className="text-lg font-semibold text-gray-900 dark:text-white mb-3">See also</h2>
<ul className="space-y-2">
{seeAlso.map((link) => (
<li key={link.href}>
<Link
href={link.href}
className="text-blue-600 dark:text-blue-400 hover:underline"
>
{link.label}
</Link>
</li>
))}
</ul>
</div>
)}
</div>
</section>
</div>
);
}
+88
View File
@@ -0,0 +1,88 @@
import type { LucideIcon } from 'lucide-react';
import {
Scale,
Shield,
FileKey,
AlertTriangle,
Ban,
Code2,
} from 'lucide-react';
export const LEGAL_LAST_UPDATED = 'May 29, 2026';
export const LEGAL_NOTICE =
'These documents describe the P2NS open-source project and the p2ns.space website. They are not legal advice. Operators and users are responsible for compliance in their jurisdiction.';
export type LegalDocumentId =
| 'terms'
| 'privacy'
| 'eula'
| 'disclaimer'
| 'acceptable-use'
| 'open-source-license';
export interface LegalDocumentMeta {
id: LegalDocumentId;
title: string;
shortTitle: string;
description: string;
href: string;
icon: LucideIcon;
}
export const legalDocuments: LegalDocumentMeta[] = [
{
id: 'terms',
title: 'Terms of Service',
shortTitle: 'Terms',
description: 'Rules for using the p2ns.space website and project materials.',
href: '/legal/terms',
icon: Scale,
},
{
id: 'privacy',
title: 'Privacy Policy',
shortTitle: 'Privacy',
description: 'How the website handles information and what the self-hosted software does locally.',
href: '/legal/privacy',
icon: Shield,
},
{
id: 'eula',
title: 'End User License Agreement',
shortTitle: 'EULA',
description: 'Terms for downloading, installing, and running P2NS software.',
href: '/legal/eula',
icon: FileKey,
},
{
id: 'disclaimer',
title: 'Disclaimer',
shortTitle: 'Disclaimer',
description: 'Limitations of liability for network operation, DNS, and security.',
href: '/legal/disclaimer',
icon: AlertTriangle,
},
{
id: 'acceptable-use',
title: 'Acceptable Use Policy',
shortTitle: 'Acceptable Use',
description: 'Prohibited uses of the software and participation in P2P networks.',
href: '/legal/acceptable-use',
icon: Ban,
},
{
id: 'open-source-license',
title: 'Open Source License',
shortTitle: 'Open Source License',
description: 'ISC license summary and link to the upstream P2NS repository.',
href: '/legal/open-source-license',
icon: Code2,
},
];
export const P2NS_REPO_URL = 'https://git.ssh.surf/snxraven/p2ns';
export function getLegalDocument(id: LegalDocumentId): LegalDocumentMeta | undefined {
return legalDocuments.find((d) => d.id === id);
}