first commit
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"extends": "next/core-web-vitals"
|
||||||
|
}
|
||||||
|
|
||||||
+36
@@ -0,0 +1,36 @@
|
|||||||
|
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||||
|
|
||||||
|
# dependencies
|
||||||
|
/node_modules
|
||||||
|
/.pnp
|
||||||
|
.pnp.js
|
||||||
|
|
||||||
|
# testing
|
||||||
|
/coverage
|
||||||
|
|
||||||
|
# next.js
|
||||||
|
/.next/
|
||||||
|
/out/
|
||||||
|
|
||||||
|
# production
|
||||||
|
/build
|
||||||
|
|
||||||
|
# misc
|
||||||
|
.DS_Store
|
||||||
|
*.pem
|
||||||
|
|
||||||
|
# debug
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# local env files
|
||||||
|
.env*.local
|
||||||
|
.env
|
||||||
|
|
||||||
|
# vercel
|
||||||
|
.vercel
|
||||||
|
|
||||||
|
# typescript
|
||||||
|
*.tsbuildinfo
|
||||||
|
next-env.d.ts
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
FROM node:20-alpine AS base
|
||||||
|
|
||||||
|
# Install dependencies only when needed
|
||||||
|
FROM base AS deps
|
||||||
|
RUN apk add --no-cache libc6-compat
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package.json package-lock.json* ./
|
||||||
|
RUN npm ci
|
||||||
|
|
||||||
|
# Rebuild the source code only when needed
|
||||||
|
FROM base AS builder
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=deps /app/node_modules ./node_modules
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Production image, copy all the files and run next
|
||||||
|
FROM base AS runner
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
ENV NODE_ENV production
|
||||||
|
|
||||||
|
RUN addgroup --system --gid 1001 nodejs
|
||||||
|
RUN adduser --system --uid 1001 nextjs
|
||||||
|
|
||||||
|
COPY --from=builder /app/public ./public
|
||||||
|
COPY --from=builder /app/.next/standalone ./
|
||||||
|
COPY --from=builder /app/.next/static ./.next/static
|
||||||
|
|
||||||
|
USER nextjs
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
ENV PORT 3000
|
||||||
|
ENV HOSTNAME "0.0.0.0"
|
||||||
|
|
||||||
|
CMD ["node", "server.js"]
|
||||||
|
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
# P2NS Website
|
||||||
|
|
||||||
|
Modern, professional public-facing website for P2NS (Peer-to-Peer Decentralized DNS System).
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Modern Design**: Built with Next.js 14+, TypeScript, and Tailwind CSS
|
||||||
|
- **Responsive**: Mobile-first design that works on all devices
|
||||||
|
- **Dark Mode**: Automatic dark mode support
|
||||||
|
- **Interactive Diagrams**: Animated visualizations of P2P concepts
|
||||||
|
- **Comprehensive Documentation**: Complete guides and API references
|
||||||
|
- **SEO Optimized**: Proper metadata, structured data, and semantic HTML
|
||||||
|
- **Accessible**: WCAG AA compliant with proper ARIA labels
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Node.js 18 or higher
|
||||||
|
- npm or yarn
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install dependencies
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# Run development server
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# Build for production
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# Start production server
|
||||||
|
npm start
|
||||||
|
```
|
||||||
|
|
||||||
|
The website will be available at [http://localhost:3000](http://localhost:3000).
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
p2ns-website/
|
||||||
|
├── app/ # Next.js App Router pages
|
||||||
|
│ ├── about/ # About P2NS page
|
||||||
|
│ ├── learn/ # P2P education pages
|
||||||
|
│ ├── features/ # Features page
|
||||||
|
│ ├── docs/ # Documentation pages
|
||||||
|
│ └── community/ # Community page
|
||||||
|
├── components/ # React components
|
||||||
|
│ ├── layout/ # Layout components (Navigation, Footer)
|
||||||
|
│ ├── sections/ # Page sections (Hero, Features, etc.)
|
||||||
|
│ ├── diagrams/ # Interactive diagrams
|
||||||
|
│ └── ui/ # Reusable UI components
|
||||||
|
├── public/ # Static assets
|
||||||
|
└── styles/ # Global styles
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
|
||||||
|
### Self-Hosted
|
||||||
|
|
||||||
|
The website is designed to be self-hostable. You can deploy it using:
|
||||||
|
|
||||||
|
- **Docker**: See `Dockerfile` and `docker-compose.yml`
|
||||||
|
- **Node.js**: Run `npm run build && npm start`
|
||||||
|
- **Static Export**: Configure Next.js for static export if needed
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
No environment variables are required for basic operation. All configuration is handled through Next.js.
|
||||||
|
|
||||||
|
## Technologies Used
|
||||||
|
|
||||||
|
- **Next.js 14+**: React framework with App Router
|
||||||
|
- **TypeScript**: Type-safe development
|
||||||
|
- **Tailwind CSS**: Utility-first CSS framework
|
||||||
|
- **Framer Motion**: Animation library
|
||||||
|
- **Lucide React**: Icon library
|
||||||
|
- **Shiki**: Syntax highlighting
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Contributions are welcome! Please follow the same contribution guidelines as the main P2NS repository.
|
||||||
@@ -0,0 +1,232 @@
|
|||||||
|
import type { Metadata } from "next";
|
||||||
|
import ArchitectureDiagram from "@/components/diagrams/ArchitectureDiagram";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "About P2NS - Peer-to-Peer Decentralized DNS System",
|
||||||
|
description:
|
||||||
|
"Learn about P2NS, a robust, firewall-resistant peer-to-peer DNS resolution system.",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function AboutPage() {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen">
|
||||||
|
{/* Hero Section */}
|
||||||
|
<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">
|
||||||
|
<div>
|
||||||
|
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||||
|
What is P2NS?
|
||||||
|
</h1>
|
||||||
|
<p className="text-xl text-gray-600 dark:text-gray-300 leading-relaxed">
|
||||||
|
P2NS (Peer-to-Peer Name System) is a robust, firewall-resistant
|
||||||
|
peer-to-peer DNS resolution system designed to operate
|
||||||
|
independently of centralized DNS infrastructure. Utilizing UDP
|
||||||
|
hole-punching via the Holesail library, P2NS enables seamless
|
||||||
|
connectivity across challenging network environments.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Problem Statement */}
|
||||||
|
<section className="py-20 bg-white dark:bg-gray-900">
|
||||||
|
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||||
|
The Problem with Centralized DNS
|
||||||
|
</h2>
|
||||||
|
<div className="prose prose-lg dark:prose-invert max-w-none">
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
Traditional DNS systems rely on centralized infrastructure
|
||||||
|
controlled by ICANN and major DNS providers. This creates several
|
||||||
|
critical issues:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li>
|
||||||
|
<strong>Single Points of Failure:</strong> Centralized servers
|
||||||
|
can be targeted by DDoS attacks or taken offline, disrupting
|
||||||
|
service for millions of users.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Censorship:</strong> Governments and ISPs can block or
|
||||||
|
redirect DNS queries, limiting access to information.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Privacy Concerns:</strong> DNS queries reveal browsing
|
||||||
|
habits and can be logged, sold, or surveilled.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Network Restrictions:</strong> Firewalls, NAT, and CGNAT
|
||||||
|
make it difficult to establish direct peer-to-peer connections.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Dependency:</strong> Users are dependent on third-party
|
||||||
|
services that may change policies or go offline.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Solution */}
|
||||||
|
<section className="py-20 bg-gray-50 dark:bg-gray-800">
|
||||||
|
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">
|
||||||
|
How P2NS Solves These Problems
|
||||||
|
</h2>
|
||||||
|
<div className="prose prose-lg dark:prose-invert max-w-none">
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
P2NS addresses these fundamental issues through a decentralized,
|
||||||
|
peer-to-peer architecture:
|
||||||
|
</p>
|
||||||
|
<div className="grid md:grid-cols-2 gap-6">
|
||||||
|
<div className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||||
|
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">
|
||||||
|
Decentralized Resolution
|
||||||
|
</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300">
|
||||||
|
Domains claims are automatically synced with all peers via corestore, and all P2P queries are local to your device. No central authority controls the system.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||||
|
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">
|
||||||
|
Firewall Traversal
|
||||||
|
</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300">
|
||||||
|
UDP hole-punching technology enables connections across
|
||||||
|
firewalls, NAT, CGNAT, and restricted networks like 4G/5G or
|
||||||
|
satellite internet.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||||
|
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">
|
||||||
|
Privacy & Security
|
||||||
|
</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300">
|
||||||
|
The stack uses ibsodium for end-to-end encryption and also employs noise encryption for further security. Web connections are safeguarded via TLS and custom CA.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||||
|
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">
|
||||||
|
Resilience
|
||||||
|
</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300">
|
||||||
|
The network continues to function even if individual peers go
|
||||||
|
offline. Consensus mechanisms ensure data integrity and
|
||||||
|
prevent tampering.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Architecture */}
|
||||||
|
<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">
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 text-center">
|
||||||
|
System Architecture
|
||||||
|
</h2>
|
||||||
|
<p className="text-center text-gray-600 dark:text-gray-300 mb-12 max-w-2xl mx-auto">
|
||||||
|
P2NS is built on a modular architecture using proven P2P
|
||||||
|
technologies
|
||||||
|
</p>
|
||||||
|
<ArchitectureDiagram />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Comparison Table */}
|
||||||
|
<section className="py-20 bg-gray-50 dark:bg-gray-800">
|
||||||
|
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 text-center">
|
||||||
|
P2NS vs Traditional DNS
|
||||||
|
</h2>
|
||||||
|
<div className="overflow-x-auto">
|
||||||
|
<table className="w-full border-collapse bg-white dark:bg-gray-900 rounded-lg overflow-hidden">
|
||||||
|
<thead>
|
||||||
|
<tr className="bg-gray-100 dark:bg-gray-800">
|
||||||
|
<th className="px-6 py-4 text-left text-sm font-semibold text-gray-900 dark:text-white">
|
||||||
|
Feature
|
||||||
|
</th>
|
||||||
|
<th className="px-6 py-4 text-left text-sm font-semibold text-gray-900 dark:text-white">
|
||||||
|
Traditional DNS
|
||||||
|
</th>
|
||||||
|
<th className="px-6 py-4 text-left text-sm font-semibold text-gray-900 dark:text-white">
|
||||||
|
P2NS
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="divide-y divide-gray-200 dark:divide-gray-700">
|
||||||
|
<tr>
|
||||||
|
<td className="px-6 py-4 text-sm font-medium text-gray-900 dark:text-white">
|
||||||
|
Infrastructure
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||||
|
Centralized servers
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||||
|
Decentralized P2P network
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-6 py-4 text-sm font-medium text-gray-900 dark:text-white">
|
||||||
|
Firewall Traversal
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||||
|
Limited
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||||
|
UDP hole-punching
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-6 py-4 text-sm font-medium text-gray-900 dark:text-white">
|
||||||
|
Censorship Resistance
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||||
|
Vulnerable
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||||
|
Highly resistant
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-6 py-4 text-sm font-medium text-gray-900 dark:text-white">
|
||||||
|
Privacy
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||||
|
Queries can be logged
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||||
|
Distributed queries
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-6 py-4 text-sm font-medium text-gray-900 dark:text-white">
|
||||||
|
Resilience
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||||
|
Single points of failure
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||||
|
No single point of failure
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-6 py-4 text-sm font-medium text-gray-900 dark:text-white">
|
||||||
|
Control
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||||
|
Third-party controlled
|
||||||
|
</td>
|
||||||
|
<td className="px-6 py-4 text-sm text-gray-600 dark:text-gray-300">
|
||||||
|
User-controlled
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
import type { Metadata } from 'next';
|
||||||
|
import { Github, ExternalLink, Code, Heart, MessageCircle } from 'lucide-react';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Community - P2NS',
|
||||||
|
description: 'Contribute to P2NS, get support, and learn about the roadmap.',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function CommunityPage() {
|
||||||
|
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">
|
||||||
|
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||||
|
Community
|
||||||
|
</h1>
|
||||||
|
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||||
|
Join the P2NS community and help build the future of decentralized DNS
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className="py-20 bg-white dark:bg-gray-900">
|
||||||
|
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="space-y-12">
|
||||||
|
<div>
|
||||||
|
<div className="flex items-center space-x-3 mb-4">
|
||||||
|
<Github className="h-8 w-8 text-gray-900 dark:text-white" />
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white">Repository</h2>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
P2NS is open source and available on Git. Check out the code, report issues, and contribute.
|
||||||
|
</p>
|
||||||
|
<a
|
||||||
|
href="https://git.ssh.surf/snxraven/p2ns"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="inline-flex items-center space-x-2 px-6 py-3 bg-gray-900 dark:bg-gray-100 text-white dark:text-gray-900 rounded-lg hover:bg-gray-800 dark:hover:bg-gray-200 transition-colors"
|
||||||
|
>
|
||||||
|
<Github className="h-5 w-5" />
|
||||||
|
<span>View Repository</span>
|
||||||
|
<ExternalLink className="h-4 w-4" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div className="flex items-center space-x-3 mb-4">
|
||||||
|
<MessageCircle className="h-8 w-8 text-gray-900 dark:text-white" />
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white">Holesail Discord</h2>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
Join the Holesail Discord server to connect with the community, get help, share ideas, and stay updated on the latest developments.
|
||||||
|
</p>
|
||||||
|
<a
|
||||||
|
href="https://discord.gg/3gFegYtNbN"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="inline-flex items-center space-x-2 px-6 py-3 bg-indigo-600 dark:bg-indigo-500 text-white rounded-lg hover:bg-indigo-700 dark:hover:bg-indigo-600 transition-colors"
|
||||||
|
>
|
||||||
|
<MessageCircle className="h-5 w-5" />
|
||||||
|
<span>Join Discord Server</span>
|
||||||
|
<ExternalLink className="h-4 w-4" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div className="flex items-center space-x-3 mb-4">
|
||||||
|
<Code className="h-8 w-8 text-gray-900 dark:text-white" />
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white">Contributing</h2>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
Contributions are welcome! Here's how you can help:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
<li>Report bugs and issues</li>
|
||||||
|
<li>Suggest new features</li>
|
||||||
|
<li>Submit pull requests</li>
|
||||||
|
<li>Improve documentation</li>
|
||||||
|
<li>Test on different platforms</li>
|
||||||
|
</ul>
|
||||||
|
<div className="bg-gray-50 dark:bg-gray-800 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||||
|
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-3">Contribution Guidelines</h3>
|
||||||
|
<ol className="list-decimal pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li>Fork the repository</li>
|
||||||
|
<li>Create a branch for your changes</li>
|
||||||
|
<li>Make your changes and test thoroughly</li>
|
||||||
|
<li>Submit a pull request with a clear description</li>
|
||||||
|
<li>Focus on stability and cross-platform compatibility</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div className="flex items-center space-x-3 mb-4">
|
||||||
|
<Heart className="h-8 w-8 text-gray-900 dark:text-white" />
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white">Support</h2>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
Need help? Here are some resources:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li>Check the <a href="/docs/troubleshooting" className="text-blue-600 dark:text-blue-400 hover:underline">Troubleshooting</a> guide</li>
|
||||||
|
<li>Review the <a href="/docs" className="text-blue-600 dark:text-blue-400 hover:underline">Documentation</a></li>
|
||||||
|
<li>Open an issue on the repository</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-4">Roadmap</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
Future enhancements planned for P2NS:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li><strong>Encrypted Corestore storage:</strong> Enhanced security for stored data</li>
|
||||||
|
<li><strong>Enhanced consensus:</strong> Blockchain-style consensus mechanisms</li>
|
||||||
|
<li><strong>Mobile app integration:</strong> Native mobile applications</li>
|
||||||
|
<li><strong>Decentralized invite system:</strong> Remove master dependency</li>
|
||||||
|
<li><strong>Performance optimizations:</strong> Faster resolution and lower latency</li>
|
||||||
|
<li><strong>Additional platforms:</strong> Expanded platform support</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,347 @@
|
|||||||
|
import type { Metadata } from 'next';
|
||||||
|
import CodeBlock from '@/components/ui/CodeBlock';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Admin Panel - P2NS Documentation',
|
||||||
|
description: 'Complete guide to the P2NS web-based admin interface, features, and usage instructions',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function AdminPanelPage() {
|
||||||
|
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">
|
||||||
|
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||||
|
Admin Panel
|
||||||
|
</h1>
|
||||||
|
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||||
|
Complete guide to the web-based admin interface
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className="py-20 bg-white dark:bg-gray-900">
|
||||||
|
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">Introduction</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
The P2NS Admin Panel is a comprehensive web-based management interface that provides real-time control
|
||||||
|
over all aspects of your P2NS node. It offers an intuitive interface for managing domains, Holesail servers
|
||||||
|
and clients, DNS records, certificates, and system settings.
|
||||||
|
</p>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
The admin panel is accessible at <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">https://p2ns.admin</code> and uses WebSocket connections
|
||||||
|
for real-time updates, ensuring you always have the latest information about your system.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Getting Started</h2>
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">Accessing the Admin Panel</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
Once your P2NS node is running, access the admin panel by navigating to:
|
||||||
|
</p>
|
||||||
|
<CodeBlock code="https://p2ns.admin" />
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Certificate Trust</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
The admin panel uses HTTPS with automatically generated certificates. On first access, you'll need to trust
|
||||||
|
the root CA certificate. The system will attempt to install it automatically, but you may need to:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
<li>Accept the security warning in your browser</li>
|
||||||
|
<li>Manually install the root CA certificate if automatic installation fails</li>
|
||||||
|
<li>Trust the certificate in your system's certificate store</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Features Overview</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
The admin panel is organized into several tabs, each providing specific functionality:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Domains</strong> - Manage P2P domain registrations</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Host</strong> - Manage Holesail servers and clients</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Local DNS</strong> - Custom DNS records and conflict resolution</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Entries</strong> - View Autopass ledger entries</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Peers</strong> - Monitor connected peers</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Certificates</strong> - Manage TLS certificates</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Interfaces</strong> - View virtual network interfaces</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Logs</strong> - Real-time system logs</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Stats</strong> - System statistics and metrics</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Settings</strong> - Configure environment variables</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Detailed Feature Descriptions</h2>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">Domains</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
The Domains tab provides comprehensive management of P2P domain registrations:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">View all domains:</strong> See all registered domains in the network with their associated hashes</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Search functionality:</strong> Quickly find domains using the search bar</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Local indicator:</strong> Domains claimed locally are marked with a 🏠 icon</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Add domains:</strong> Register new domains by providing a domain name and Holesail hash</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Remove domains:</strong> Delete locally claimed domains (only local domains can be removed)</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Pagination:</strong> Navigate through large domain lists efficiently</li>
|
||||||
|
</ul>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
All changes are synchronized in real-time via WebSocket, so you'll see updates immediately as they occur.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Host</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
The Host tab manages Holesail servers and clients for network tunneling:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Holesail Servers</h4>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Create servers:</strong> Set up new Holesail servers with custom ports, hosts, and keys</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Configure options:</strong> Set name, port, host (default 0.0.0.0), key, secure/UDP flags, and log level</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Domain assignment:</strong> Optionally assign servers to specific domains</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Restart servers:</strong> Restart running servers without deleting them</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">View logs:</strong> Access real-time logs for each server in a terminal interface</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Delete servers:</strong> Remove servers and clean up resources</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Status monitoring:</strong> See server status (running/stopped) at a glance</li>
|
||||||
|
</ul>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
Server configurations are persisted in <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">holesail_servers.json</code> and survive restarts.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Holesail Clients</h4>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Create clients:</strong> Set up Holesail clients to connect to remote servers</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Domain selection:</strong> Choose which domain the client should connect for</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Key and port:</strong> Configure connection key and local port</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Restart clients:</strong> Restart clients without deleting configuration</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">View logs:</strong> Monitor client connection logs in real-time</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Delete clients:</strong> Remove client configurations</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Status tracking:</strong> Monitor client connection status</li>
|
||||||
|
</ul>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
Client configurations are persisted in <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">holesail_clients.json</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Local DNS</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
The Local DNS tab allows you to manage custom DNS records and resolve conflicts between P2P and public DNS:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Custom DNS Records</h4>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
Create and manage custom DNS records for any domain. Supported record types include:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">A</strong> - IPv4 address records</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">AAAA</strong> - IPv6 address records</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">CNAME</strong> - Canonical name records</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">MX</strong> - Mail exchange records</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">TXT</strong> - Text records</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">SRV</strong> - Service records</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">SOA</strong> - Start of authority records</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">CAA</strong> - Certificate authority authorization</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">NS</strong> - Name server records</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">PTR</strong> - Pointer records</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">OTHER</strong> - Other record types</li>
|
||||||
|
</ul>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
Each record can be edited or deleted, and all changes are persisted to <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">local_dns.json</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">DNS Conflict Selector</h4>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
When a domain exists in both the P2P network and public DNS, the DNS Conflict Selector allows you to choose
|
||||||
|
which version to use. You can set preferences for each conflicting domain, and your choices are saved in
|
||||||
|
<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">selector_cache.json</code> for persistence across restarts.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Entries</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
The Entries tab displays all Autopass ledger entries, which represent domain claims and votes in the P2P network:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">View all entries:</strong> Browse all claims and votes in the distributed ledger</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Search functionality:</strong> Search entries by key or value</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Pagination:</strong> Navigate through large entry lists</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Real-time updates:</strong> See new entries as they're added to the network</li>
|
||||||
|
</ul>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
This view helps you understand the consensus state of the network and see how domain claims are being voted on.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Peers</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
The Peers tab shows all currently connected peers in the P2P network:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Peer list:</strong> View all connected peers with their public keys</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Peer count:</strong> See the total number of connected peers</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Search:</strong> Find specific peers by public key</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Pagination:</strong> Navigate through peer lists</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Real-time updates:</strong> See peers connect and disconnect in real-time</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Certificates</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
The Certificates tab manages TLS certificates for secure HTTPS connections:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Generate certificates:</strong> Create new certificates for any domain</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">View certificate details:</strong> Inspect certificate information including SANs and expiration</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Regenerate certificates:</strong> Create new certificates for existing domains</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Delete certificates:</strong> Remove certificates for domains</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Search functionality:</strong> Find certificates by domain name</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">CA Management</h4>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Regenerate Root CA:</strong> Create a new root certificate authority</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Install Root CA:</strong> Install the root CA certificate in your system's trust store</li>
|
||||||
|
</ul>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
The root CA is used to sign all domain certificates, ensuring secure connections to P2P domains.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Interfaces</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
The Interfaces tab displays virtual network interface mappings:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Domain-to-IP mappings:</strong> See which domains are assigned to which local IP addresses</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Search functionality:</strong> Find interfaces by domain or IP</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Cleanup:</strong> Remove unused virtual interfaces to free up IP addresses</li>
|
||||||
|
</ul>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
Virtual interfaces are automatically created when domains are added and are used for local routing.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Logs</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
The Logs tab provides a real-time terminal view of system logs:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Real-time streaming:</strong> See logs as they're generated</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Log levels:</strong> View DEBUG, INFO, WARN, and ERROR messages</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Terminal interface:</strong> Full-featured terminal with scrollback and search</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Auto-scroll:</strong> Automatically scroll to show latest logs</li>
|
||||||
|
</ul>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
This is invaluable for debugging issues and monitoring system behavior in real-time.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Stats</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
The Stats tab provides comprehensive statistics and metrics about your P2NS node:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">System Overview</h4>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">System uptime:</strong> How long the node has been running</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Node type:</strong> Master or joiner node status</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Connected peers:</strong> Current number of connected peers</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Total domains:</strong> Number of registered domains</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">DNS Statistics</h4>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
<li>Total DNS queries and success rate</li>
|
||||||
|
<li>Average response time</li>
|
||||||
|
<li>P2P resolution rate</li>
|
||||||
|
<li>Query type distribution</li>
|
||||||
|
<li>Top queried domains</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Network & Peers</h4>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
<li>Peer connection events over time</li>
|
||||||
|
<li>Total connections and average duration</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Holesail Statistics</h4>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
<li>Active connections</li>
|
||||||
|
<li>Servers and clients started</li>
|
||||||
|
<li>Average connection duration</li>
|
||||||
|
<li>Protocol usage (TCP/UDP)</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">API & Requests</h4>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
<li>Total API requests and success rate</li>
|
||||||
|
<li>Average response time</li>
|
||||||
|
<li>Failed requests</li>
|
||||||
|
<li>Endpoint usage patterns</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Resource Usage</h4>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
<li>Active sockets, servers, and connections</li>
|
||||||
|
<li>Memory usage (heap, RSS, external)</li>
|
||||||
|
<li>CPU usage and load average</li>
|
||||||
|
<li>Event loop performance</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Domain Management</h4>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
<li>Domains added and removed</li>
|
||||||
|
<li>Net change over time</li>
|
||||||
|
</ul>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
All statistics include interactive charts and can be exported for analysis. You can adjust the refresh interval
|
||||||
|
and time range to focus on specific periods.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Settings</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
The Settings tab allows you to view and edit environment variables:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">View all settings:</strong> See all current environment variable values</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Edit values:</strong> Modify settings like <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">LOG_LEVEL</code>, <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">SUBNET_BASE</code>, etc.</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Search functionality:</strong> Quickly find specific settings</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Save changes:</strong> Persist modifications to <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">.env</code> file</li>
|
||||||
|
</ul>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
Changes take effect after saving, though some settings may require a restart to apply fully.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Real-time Updates</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
The admin panel uses WebSocket connections to provide real-time updates across all tabs:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Automatic refresh:</strong> Data updates automatically when changes occur</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Live logs:</strong> System logs stream in real-time</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Peer updates:</strong> See peers connect and disconnect immediately</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Domain changes:</strong> New domain registrations appear instantly</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Status indicators:</strong> Connection status shown in the top-right corner</li>
|
||||||
|
</ul>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
The WebSocket connection automatically reconnects if interrupted, ensuring you always have the latest information.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Tips and Best Practices</h2>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Monitor logs regularly:</strong> Check the Logs tab to catch issues early</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Use Stats for optimization:</strong> Review statistics to identify performance bottlenecks</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Clean up interfaces:</strong> Periodically clean unused virtual interfaces to free resources</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Manage certificates:</strong> Regenerate certificates if you encounter SSL errors</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Backup configurations:</strong> The JSON files (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">domains.json</code>, <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">local_dns.json</code>, etc.) can be backed up for disaster recovery</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Use search effectively:</strong> Most tabs have search functionality to quickly find specific items</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Check peer connections:</strong> Monitor the Peers tab to ensure network connectivity</li>
|
||||||
|
<li><strong className="text-gray-900 dark:text-white">Review DNS conflicts:</strong> Use the DNS Conflict Selector to manage domains that exist in both P2P and public DNS</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">API Integration</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
While the admin panel provides a user-friendly interface, all functionality is also available via the REST API
|
||||||
|
for programmatic access. See the <a href="/docs/api" className="text-blue-600 dark:text-blue-400 hover:underline">API Reference</a> documentation
|
||||||
|
for complete endpoint documentation.
|
||||||
|
</p>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
The admin panel itself uses these API endpoints, so you can build custom tools or integrate P2NS management
|
||||||
|
into your own applications.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
import type { Metadata } from 'next';
|
||||||
|
import CodeBlock from '@/components/ui/CodeBlock';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'API Reference - P2NS Documentation',
|
||||||
|
description: 'Complete REST API and WebSocket documentation for P2NS.',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function APIPage() {
|
||||||
|
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">
|
||||||
|
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||||
|
API Reference
|
||||||
|
</h1>
|
||||||
|
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||||
|
Complete REST API and WebSocket documentation
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className="py-20 bg-white dark:bg-gray-900">
|
||||||
|
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-8">
|
||||||
|
The P2NS Admin API provides comprehensive endpoints for managing the decentralized DNS system.
|
||||||
|
All endpoints are accessible at <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">https://p2ns.admin</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="bg-blue-50 dark:bg-blue-900 border-l-4 border-blue-500 p-4 rounded mb-8">
|
||||||
|
<p className="text-blue-800 dark:text-blue-200">
|
||||||
|
<strong>Note:</strong> For complete API documentation including all endpoints, request/response formats,
|
||||||
|
and WebSocket events, please refer to the{' '}
|
||||||
|
<a
|
||||||
|
href="https://git.ssh.surf/snxraven/p2ns/src/branch/main/docs/RESTAPI.md"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="underline"
|
||||||
|
>
|
||||||
|
REST API documentation
|
||||||
|
</a>{' '}
|
||||||
|
in the main repository.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">Base URL</h2>
|
||||||
|
<CodeBlock code="https://p2ns.admin" />
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">WebSocket Endpoint</h2>
|
||||||
|
<CodeBlock code="wss://p2ns.admin/ws" />
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mt-4">
|
||||||
|
The WebSocket connection provides real-time updates including logs, database changes, peer updates,
|
||||||
|
and system events.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Key Endpoints</h2>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/resolved-domains</code> - List all resolved domains</li>
|
||||||
|
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">POST /api/add-domain</code> - Add a new domain</li>
|
||||||
|
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">POST /api/remove-domain</code> - Remove a domain</li>
|
||||||
|
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/peers</code> - List connected peers</li>
|
||||||
|
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/status</code> - Get system status</li>
|
||||||
|
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/local-dns</code> - Get local DNS records</li>
|
||||||
|
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/holesail-servers</code> - List Holesail servers</li>
|
||||||
|
<li><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">GET /api/holesail-clients</code> - List Holesail clients</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Authentication</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300">
|
||||||
|
The API does not require authentication since it's designed for local use. In production environments,
|
||||||
|
you should restrict access to trusted networks or implement authentication.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Response Format</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
Most endpoints return JSON responses. Success responses typically return <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">200</code>
|
||||||
|
with the requested data or <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">"OK"</code> for successful operations.
|
||||||
|
Errors return appropriate HTTP status codes with error messages.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">More Information</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300">
|
||||||
|
For detailed API documentation including all endpoints, parameters, response formats, and WebSocket message types,
|
||||||
|
see the <a href="https://git.ssh.surf/snxraven/p2ns/src/branch/main/docs/RESTAPI.md" target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">full API documentation</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
import type { Metadata } from 'next';
|
||||||
|
import ArchitectureDiagram from '@/components/diagrams/ArchitectureDiagram';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Architecture - P2NS Documentation',
|
||||||
|
description: 'Deep dive into P2NS system architecture and components.',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function ArchitecturePage() {
|
||||||
|
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">
|
||||||
|
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||||
|
System Architecture
|
||||||
|
</h1>
|
||||||
|
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||||
|
Deep dive into P2NS components and design
|
||||||
|
</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">
|
||||||
|
<ArchitectureDiagram />
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Core Components</h2>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">Corestore & Autopass</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
Corestore provides decentralized, append-only storage for domain claims and votes. Autopass manages
|
||||||
|
secure writer additions through an invitation system, ensuring only authorized peers can write to the ledger.
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li>Stores claims as <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">claim:domain:claimant</code></li>
|
||||||
|
<li>Stores votes as <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">vote:domain:claimant:voter</code></li>
|
||||||
|
<li>Master nodes initialize the core and issue invites</li>
|
||||||
|
<li>Joiners request invites to become writers</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Hyperswarm</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
Hyperswarm handles peer discovery using a fixed topic derived from <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">sha256('p2ns-dns')</code>.
|
||||||
|
All peers interested in P2NS join this topic and can discover each other through the DHT.
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li>Automatic peer discovery</li>
|
||||||
|
<li>Handles peer churn (peers joining/leaving)</li>
|
||||||
|
<li>No central directory server required</li>
|
||||||
|
<li>Resilient to network partitions</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">DNS Handler</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
The DNS handler runs a UDP server on port 53 (configurable) that resolves domains through multiple mechanisms:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li><strong>P2P Resolution:</strong> Queries the Corestore for domain claims</li>
|
||||||
|
<li><strong>Local DNS:</strong> Checks local_dns.json for custom records</li>
|
||||||
|
<li><strong>Public DNS Fallback:</strong> Forwards to public DNS servers for non-P2P domains</li>
|
||||||
|
<li><strong>Conflict Resolution:</strong> Uses selector_cache.json preferences when domains exist in both P2P and public DNS</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Proxy Server</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
The proxy server handles HTTP/HTTPS traffic routing:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li><strong>HTTPS (port 443):</strong> Routes to local IPs via Holesail or public IPs based on DNS preferences</li>
|
||||||
|
<li><strong>HTTP (port 80):</strong> Redirects to HTTPS per domain</li>
|
||||||
|
<li><strong>TLS Termination:</strong> Per-domain TLS servers with SNI support</li>
|
||||||
|
<li><strong>WebSocket Support:</strong> Handles WebSocket upgrades for real-time applications</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Holesail Integration</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
Holesail provides UDP hole-punching for P2P tunneling:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li><strong>Servers:</strong> Persistent servers that can be assigned to domains</li>
|
||||||
|
<li><strong>Clients:</strong> Created lazily when domains are accessed, timeout after inactivity</li>
|
||||||
|
<li><strong>Configuration:</strong> Stored in holesail_servers.json and holesail_clients.json</li>
|
||||||
|
<li><strong>Management:</strong> Full control through admin interface with log viewing</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Data Flow</h2>
|
||||||
|
<ol className="list-decimal pl-6 space-y-3 text-gray-600 dark:text-gray-300">
|
||||||
|
<li>User queries a domain via DNS (e.g., <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">dig @127.0.0.1 example.tld</code>)</li>
|
||||||
|
<li>DNS handler checks local_dns.json, then Corestore for P2P claims, then public DNS</li>
|
||||||
|
<li>If P2P domain, assigns local IP and creates Holesail client if needed</li>
|
||||||
|
<li>User accesses domain via HTTPS proxy</li>
|
||||||
|
<li>Proxy routes to local IP, which tunnels through Holesail to the peer</li>
|
||||||
|
<li>Response is returned through the tunnel and back to the user</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Consensus Mechanism</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
P2NS uses a simple voting system for domain claims:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li>When a domain is claimed, peers vote on the claim</li>
|
||||||
|
<li>Local claims are automatically voted for by the claiming peer</li>
|
||||||
|
<li>Consensus is reached when a claim has the most votes</li>
|
||||||
|
<li>Ties are broken lexically (alphabetically)</li>
|
||||||
|
<li>This prevents domain hijacking and ensures network integrity</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Master vs Joiner Modes</h2>
|
||||||
|
<div className="grid md:grid-cols-2 gap-6">
|
||||||
|
<div className="bg-gray-50 dark:bg-gray-800 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||||
|
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Master Node</h3>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li>Initializes the Corestore</li>
|
||||||
|
<li>Loads domains from domains.json</li>
|
||||||
|
<li>Issues invites to joiners</li>
|
||||||
|
<li>Can add domains directly</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="bg-gray-50 dark:bg-gray-800 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||||
|
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Joiner Node</h3>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li>Connects to existing network</li>
|
||||||
|
<li>Requests invites from master</li>
|
||||||
|
<li>Syncs domain data from peers</li>
|
||||||
|
<li>Can vote on domain claims</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
import type { Metadata } from 'next';
|
||||||
|
import CodeBlock from '@/components/ui/CodeBlock';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Configuration - P2NS Documentation',
|
||||||
|
description: 'Environment variables and configuration options for P2NS.',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function ConfigurationPage() {
|
||||||
|
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">
|
||||||
|
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||||
|
Configuration
|
||||||
|
</h1>
|
||||||
|
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||||
|
Customize P2NS to fit your needs
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className="py-20 bg-white dark:bg-gray-900">
|
||||||
|
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">Environment Variables</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-6">
|
||||||
|
Configure P2NS via a <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">.env</code> file (copy from <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">default.env</code>):
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="space-y-8">
|
||||||
|
<div>
|
||||||
|
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">Storage & Files</h3>
|
||||||
|
<table className="w-full border-collapse bg-white dark:bg-gray-900">
|
||||||
|
<thead>
|
||||||
|
<tr className="bg-gray-100 dark:bg-gray-800">
|
||||||
|
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Variable</th>
|
||||||
|
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Default</th>
|
||||||
|
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">STORAGE_DIR</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">./my-storage</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Corestore data directory</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">DOMAINS_FILE</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">domains.json</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Domains JSON file</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">LOCAL_DNS_FILE</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">local_dns.json</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Local DNS records file</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">Network Configuration</h3>
|
||||||
|
<table className="w-full border-collapse bg-white dark:bg-gray-900">
|
||||||
|
<thead>
|
||||||
|
<tr className="bg-gray-100 dark:bg-gray-800">
|
||||||
|
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Variable</th>
|
||||||
|
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Default</th>
|
||||||
|
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">DNS_PORT</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">53</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">DNS server port</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">HTTPS_PORT</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">443</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">HTTPS proxy port</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">HTTP_PORT</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">80</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">HTTP redirect port</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">PUBLIC_DNS_SERVER</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">1.1.1.1</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Public DNS fallback</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">Virtual Interfaces</h3>
|
||||||
|
<table className="w-full border-collapse bg-white dark:bg-gray-900">
|
||||||
|
<thead>
|
||||||
|
<tr className="bg-gray-100 dark:bg-gray-800">
|
||||||
|
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Variable</th>
|
||||||
|
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Default</th>
|
||||||
|
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">SUBNET_BASE</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">192.168.3</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Virtual interface IP base</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">INITIAL_IP_INDEX</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">2</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Starting IP index</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">SUBNET_NAME</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">lo0</code> (macOS), <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">lo</code> (Linux)</td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Interface for virtual IPs</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">Other Settings</h3>
|
||||||
|
<table className="w-full border-collapse bg-white dark:bg-gray-900">
|
||||||
|
<thead>
|
||||||
|
<tr className="bg-gray-100 dark:bg-gray-800">
|
||||||
|
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Variable</th>
|
||||||
|
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Default</th>
|
||||||
|
<th className="px-4 py-2 text-left border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-white font-semibold">Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">LOG_LEVEL</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">0</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Logging level (0-3: DEBUG, INFO, WARN, ERROR)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">HOLESAIL_TIMEOUT</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">300000</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Holesail client timeout (ms)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">DISABLE_DNS_SERVER</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">false</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Disable DNS server</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">DISABLE_PROXY_SERVER</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-900 dark:text-gray-200"><code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">false</code></td>
|
||||||
|
<td className="px-4 py-2 border border-gray-300 dark:border-gray-700 text-gray-600 dark:text-gray-300">Disable proxy servers</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Example Configuration</h2>
|
||||||
|
<CodeBlock code={`LOG_LEVEL=1
|
||||||
|
STORAGE_DIR=./my-storage
|
||||||
|
INTERNAL_DOMAINS=peer.directory,peer.dir,p2ns.admin
|
||||||
|
SUBNET_BASE=192.168.3
|
||||||
|
SELECTOR_CACHE_FILE=selector_cache.json
|
||||||
|
PUBLIC_DNS_SERVER=1.1.1.1`} />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
import type { Metadata } from 'next';
|
||||||
|
import CodeBlock from '@/components/ui/CodeBlock';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Getting Started - P2NS Documentation',
|
||||||
|
description: 'Installation and quick start guide for P2NS.',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function GettingStartedPage() {
|
||||||
|
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">
|
||||||
|
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||||
|
Getting Started
|
||||||
|
</h1>
|
||||||
|
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||||
|
Get P2NS up and running in minutes
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className="py-20 bg-white dark:bg-gray-900">
|
||||||
|
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">Prerequisites</h2>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li><strong>Node.js:</strong> Version 18 or higher (tested up to 20.x)</li>
|
||||||
|
<li><strong>Holesail CLI:</strong> For generating connection hashes (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">npm install -g holesail</code>)</li>
|
||||||
|
<li><strong>Platform:</strong> macOS or Linux (sudo required for ports <1024 and interfaces). Windows support planned.</li>
|
||||||
|
<li><strong>Dependencies:</strong> All dependencies are installed via npm</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Installation</h2>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">1. Clone the Repository</h3>
|
||||||
|
<CodeBlock code={`git clone https://git.ssh.surf/snxraven/p2ns.git
|
||||||
|
cd p2ns`} />
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">2. Install Dependencies</h3>
|
||||||
|
<CodeBlock code="npm install" />
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">3. Configure Environment (Optional)</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
Copy the default environment file and customize as needed:
|
||||||
|
</p>
|
||||||
|
<CodeBlock code={`cp default.env .env
|
||||||
|
# Edit .env with your preferred settings`} />
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Running the System</h2>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">Master Node</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
The master node initializes the network and loads domains from <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">domains.json</code>:
|
||||||
|
</p>
|
||||||
|
<CodeBlock code="sudo node p2ns.js --master" />
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Joiner Node</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
Joiner nodes connect to the network via invites:
|
||||||
|
</p>
|
||||||
|
<CodeBlock code="sudo node p2ns.js" />
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">Clean Storage</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
To start fresh, remove the storage directory:
|
||||||
|
</p>
|
||||||
|
<CodeBlock code="sudo node p2ns.js --clean [--master]" />
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Adding Your First Domain</h2>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">1. Generate a Holesail Hash</h3>
|
||||||
|
<CodeBlock code="holesail --live 80 --public" />
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4 mt-4">
|
||||||
|
This will output a connection hash like: <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">hs://s00084bf87dfa89a3048fb081c0e6207eb5a</code>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4 mt-8">2. Add the Domain</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
You can add domains in several ways:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Via Admin Interface</h4>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
Access <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">https://p2ns.admin</code> and use the Domains tab to add domains interactively.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h4 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Via domains.json</h4>
|
||||||
|
<CodeBlock code={`[
|
||||||
|
{
|
||||||
|
"domain": "example.tld",
|
||||||
|
"hash": "hs://s00084bf87dfa89a3048fb081c0e6207eb5a"
|
||||||
|
}
|
||||||
|
]`} language="json" />
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Accessing the Interfaces</h2>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li><strong>Admin Interface:</strong> <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">https://p2ns.admin</code></li>
|
||||||
|
<li><strong>Peer Directory:</strong> <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">https://peer.directory</code></li>
|
||||||
|
</ul>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mt-4">
|
||||||
|
<strong>Note:</strong> You'll need to trust the root CA certificate in your browser. The system will attempt to install it automatically.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Next Steps</h2>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li>Read the <a href="/docs/configuration" className="text-blue-600 dark:text-blue-400 hover:underline">Configuration</a> guide</li>
|
||||||
|
<li>Check out the <a href="/docs/api" className="text-blue-600 dark:text-blue-400 hover:underline">API Reference</a></li>
|
||||||
|
<li>Learn about <a href="/learn/p2p" className="text-blue-600 dark:text-blue-400 hover:underline">How P2P Works</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
import type { Metadata } from 'next';
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { Book, Settings, Code, Wrench, Network, FileText, LayoutDashboard } from 'lucide-react';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Documentation - P2NS',
|
||||||
|
description: 'Complete documentation for P2NS including installation, configuration, API reference, and troubleshooting.',
|
||||||
|
};
|
||||||
|
|
||||||
|
const docSections = [
|
||||||
|
{
|
||||||
|
title: 'Getting Started',
|
||||||
|
description: 'Installation guide, prerequisites, and quick start instructions',
|
||||||
|
icon: Book,
|
||||||
|
href: '/docs/getting-started',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Configuration',
|
||||||
|
description: 'Environment variables, setup files, and configuration options',
|
||||||
|
icon: Settings,
|
||||||
|
href: '/docs/configuration',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Admin Panel',
|
||||||
|
description: 'Complete guide to the web-based admin interface and its features',
|
||||||
|
icon: LayoutDashboard,
|
||||||
|
href: '/docs/admin-panel',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'API Reference',
|
||||||
|
description: 'Complete REST API documentation and WebSocket events',
|
||||||
|
icon: FileText,
|
||||||
|
href: '/docs/api',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Troubleshooting',
|
||||||
|
description: 'Common issues, solutions, and debugging tips',
|
||||||
|
icon: Wrench,
|
||||||
|
href: '/docs/troubleshooting',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'Architecture',
|
||||||
|
description: 'Deep dive into system components and technical details',
|
||||||
|
icon: Network,
|
||||||
|
href: '/docs/architecture',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function DocsPage() {
|
||||||
|
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">
|
||||||
|
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||||
|
Documentation
|
||||||
|
</h1>
|
||||||
|
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||||
|
Complete guides and references for using and understanding P2NS
|
||||||
|
</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="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
|
{docSections.map((section) => {
|
||||||
|
const Icon = section.icon;
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
key={section.href}
|
||||||
|
href={section.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">
|
||||||
|
{section.title}
|
||||||
|
</h2>
|
||||||
|
</div>
|
||||||
|
<p className="text-gray-600 dark:text-gray-400">
|
||||||
|
{section.description}
|
||||||
|
</p>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
import type { Metadata } from 'next';
|
||||||
|
import CodeBlock from '@/components/ui/CodeBlock';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Troubleshooting - P2NS Documentation',
|
||||||
|
description: 'Common issues and solutions for P2NS.',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function TroubleshootingPage() {
|
||||||
|
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">
|
||||||
|
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||||
|
Troubleshooting
|
||||||
|
</h1>
|
||||||
|
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||||
|
Common issues and their solutions
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className="py-20 bg-white dark:bg-gray-900">
|
||||||
|
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6">Port Conflicts</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
If you encounter port conflicts, check which processes are using the ports:
|
||||||
|
</p>
|
||||||
|
<CodeBlock code={`# Check ports 53, 80, 443
|
||||||
|
netstat -an | grep LISTEN | grep -E ':(53|80|443)'
|
||||||
|
|
||||||
|
# Or on Linux
|
||||||
|
lsof -i :53
|
||||||
|
lsof -i :80
|
||||||
|
lsof -i :443`} />
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mt-4">
|
||||||
|
<strong>Solution:</strong> Stop conflicting services or set <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">DISABLE_DNS_SERVER=true</code> or <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">DISABLE_PROXY_SERVER=true</code> in your <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">.env</code> file.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Certificate Authority Issues</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
If the root CA isn't trusted, you may see certificate errors in your browser. Verify installation:
|
||||||
|
</p>
|
||||||
|
<CodeBlock code={`# macOS - Check Keychain
|
||||||
|
security find-certificate -c "P2NS Root CA"
|
||||||
|
|
||||||
|
# Linux - Check certificates directory
|
||||||
|
ls /usr/local/share/ca-certificates/p2ns*
|
||||||
|
|
||||||
|
# Windows - Check certificate store
|
||||||
|
certutil -store -user ROOT | findstr P2NS`} />
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mt-4">
|
||||||
|
<strong>Solution:</strong> Manually install the CA from <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">./certs/ca.cert.pem</code> or use the admin interface to regenerate and install.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Holesail Connection Failures</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
If Holesail connections fail, verify the hash is correct:
|
||||||
|
</p>
|
||||||
|
<CodeBlock code={`# Test hash generation
|
||||||
|
holesail --live 80 --public
|
||||||
|
|
||||||
|
# Check Holesail CLI is installed
|
||||||
|
which holesail
|
||||||
|
npm list -g holesail`} />
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mt-4">
|
||||||
|
<strong>Solution:</strong> Ensure Holesail CLI is installed globally (<code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">npm install -g holesail</code>) and the hash is valid.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">DNS Resolution Issues</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
If domains aren't resolving, check several things:
|
||||||
|
</p>
|
||||||
|
<CodeBlock code={`# Test DNS resolution
|
||||||
|
dig @127.0.0.1 example.tld
|
||||||
|
|
||||||
|
# Check if DNS server is running
|
||||||
|
curl -k https://p2ns.admin/api/status
|
||||||
|
|
||||||
|
# Verify peer connections
|
||||||
|
curl -k https://p2ns.admin/api/peers`} />
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mt-4">
|
||||||
|
<strong>Common causes:</strong>
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li>No peers connected - check swarm logs</li>
|
||||||
|
<li>Domain not claimed - verify in domains.json or admin interface</li>
|
||||||
|
<li>DNS conflict - check selector_cache.json preferences</li>
|
||||||
|
<li>Local DNS override - check local_dns.json</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Interface Issues</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
Virtual interface creation requires sudo privileges:
|
||||||
|
</p>
|
||||||
|
<CodeBlock code={`# macOS - Check interfaces
|
||||||
|
ifconfig lo0
|
||||||
|
|
||||||
|
# Linux - Check interfaces
|
||||||
|
ip addr show lo
|
||||||
|
|
||||||
|
# Verify IP assignments
|
||||||
|
curl -k https://p2ns.admin/api/interfaces`} />
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mt-4">
|
||||||
|
<strong>Solution:</strong> Ensure you're running with sudo and the interface name is correct for your platform.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Admin Interface Not Loading</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
If the admin interface doesn't load:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li>Verify <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">p2ns.admin</code> resolves to 127.0.0.1</li>
|
||||||
|
<li>Check WebSocket connection at <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">wss://p2ns.admin/ws</code></li>
|
||||||
|
<li>Verify certificate is trusted</li>
|
||||||
|
<li>Check browser console for errors</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Sync Issues</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-4">
|
||||||
|
If domains aren't syncing across peers:
|
||||||
|
</p>
|
||||||
|
<CodeBlock code={`# Reset storage (WARNING: deletes all data)
|
||||||
|
sudo node p2ns.js --clean --master
|
||||||
|
|
||||||
|
# Check swarm logs for peer events
|
||||||
|
# Look for [Swarm] connection/disconnection messages`} />
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mt-4">
|
||||||
|
<strong>Solution:</strong> Monitor swarm logs, ensure peers are connected, and verify Autopass invites are working.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-6 mt-12">Getting Help</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300">
|
||||||
|
If you're still experiencing issues:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li>Check the logs in the admin interface</li>
|
||||||
|
<li>Review the <a href="/docs/architecture" className="text-blue-600 dark:text-blue-400 hover:underline">Architecture</a> documentation</li>
|
||||||
|
<li>Check the <a href="https://git.ssh.surf/snxraven/p2ns" target="_blank" rel="noopener noreferrer" className="text-blue-600 dark:text-blue-400 hover:underline">repository</a> for known issues</li>
|
||||||
|
<li>Enable debug logging by setting <code className="bg-gray-800 dark:bg-gray-700 text-gray-100 dark:text-gray-200 px-1.5 py-0.5 rounded">LOG_LEVEL=0</code> in your .env</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
@@ -0,0 +1,225 @@
|
|||||||
|
// app/features/page.tsx
|
||||||
|
import type { Metadata } from 'next';
|
||||||
|
import { MotionDiv } from '@/components/ui/MotionDiv';
|
||||||
|
import {
|
||||||
|
Network,
|
||||||
|
Shield,
|
||||||
|
Zap,
|
||||||
|
Globe,
|
||||||
|
Lock,
|
||||||
|
Settings,
|
||||||
|
Server,
|
||||||
|
Users,
|
||||||
|
Check,
|
||||||
|
Code,
|
||||||
|
Database,
|
||||||
|
type LucideIcon,
|
||||||
|
} from 'lucide-react';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'Features - P2NS Peer-to-Peer DNS System',
|
||||||
|
description:
|
||||||
|
'Comprehensive features of P2NS including decentralized DNS, firewall traversal, proxy servers, and more.',
|
||||||
|
};
|
||||||
|
|
||||||
|
type Feature = {
|
||||||
|
name: string;
|
||||||
|
icon: LucideIcon;
|
||||||
|
description: string;
|
||||||
|
benefits: string[];
|
||||||
|
example: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const features: Feature[] = [
|
||||||
|
{
|
||||||
|
name: 'Decentralized DNS Resolution',
|
||||||
|
icon: Network,
|
||||||
|
description: 'Resolve domains to hashes via a P2P core, independent of ICANN or central DNS servers.',
|
||||||
|
benefits: [
|
||||||
|
'No single point of failure',
|
||||||
|
'Censorship-resistant',
|
||||||
|
'User-controlled resolution',
|
||||||
|
'Consensus-based domain claims',
|
||||||
|
],
|
||||||
|
example:
|
||||||
|
'Domains are stored in a distributed ledger accessible by all peers, ensuring resilience and transparency.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Firewall and NAT Traversal',
|
||||||
|
icon: Shield,
|
||||||
|
description: 'Uses Holesail for UDP hole-punching to connect across restrictive networks.',
|
||||||
|
benefits: [
|
||||||
|
'Works behind firewalls',
|
||||||
|
'Traverses NAT and CGNAT',
|
||||||
|
'Supports 4G/5G networks',
|
||||||
|
'Compatible with satellite internet',
|
||||||
|
],
|
||||||
|
example:
|
||||||
|
'Even devices behind multiple layers of NAT can establish direct P2P connections using advanced hole-punching techniques.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Dynamic Local IP Assignment',
|
||||||
|
icon: Zap,
|
||||||
|
description: 'Assigns unique local IPs to domains via virtual network interfaces.',
|
||||||
|
benefits: ['Automatic IP management', 'Seamless routing', 'No manual configuration', 'Clean interface cleanup'],
|
||||||
|
example:
|
||||||
|
'Each domain gets a unique IP from the 192.168.3.x subnet, automatically assigned and managed by the system.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Hybrid DNS Resolution',
|
||||||
|
icon: Globe,
|
||||||
|
description: 'Falls back to public DNS for non-P2P domains with custom local DNS record support.',
|
||||||
|
benefits: ['Best of both worlds', 'Custom DNS records', 'Public DNS fallback', 'Flexible configuration'],
|
||||||
|
example:
|
||||||
|
'P2P domains resolve through the network, while traditional domains use public DNS servers like 1.1.1.1.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'DNS Conflict Selector',
|
||||||
|
icon: Check,
|
||||||
|
description: 'Choose between P2P and public DNS records for domains with both, managed via admin interface.',
|
||||||
|
benefits: ['User choice', 'Persistent preferences', 'Easy management', 'Per-domain control'],
|
||||||
|
example:
|
||||||
|
'If myspace.com exists in both P2P and public DNS, you can choose which version to use and save your preference.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Integrated Proxy Servers',
|
||||||
|
icon: Server,
|
||||||
|
description: 'HTTP/HTTPS proxies with automatic HTTP-to-HTTPS redirection and WebSocket support.',
|
||||||
|
benefits: ['Automatic HTTPS', 'WebSocket support', 'TLS termination', 'Per-domain routing'],
|
||||||
|
example:
|
||||||
|
'Access P2P domains through standard HTTP/HTTPS protocols, with automatic certificate management and secure connections.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Holesail Server and Client Management',
|
||||||
|
icon: Settings,
|
||||||
|
description: 'Persistent Holesail servers and clients for tunneling, manageable via the admin interface.',
|
||||||
|
benefits: ['Persistent tunnels', 'Easy management', 'Log viewing', 'Restart capabilities'],
|
||||||
|
example:
|
||||||
|
'Create and manage Holesail servers that persist across restarts, with full control through the web interface.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Automatic Certificate Management',
|
||||||
|
icon: Lock,
|
||||||
|
description: 'Generates and installs a root CA and per-domain certificates with SANs for secure TLS connections.',
|
||||||
|
benefits: ['Automatic generation', 'Root CA installation', 'SAN support', 'IP inclusion'],
|
||||||
|
example:
|
||||||
|
'The system automatically generates and installs certificates for all domains, including the root CA in your system trust store.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Peer Directory Interface',
|
||||||
|
icon: Users,
|
||||||
|
description: 'Web-based directory at peer.directory for browsing and searching domains.',
|
||||||
|
benefits: ['Easy discovery', 'Search functionality', 'Real-time updates', 'User-friendly interface'],
|
||||||
|
example: 'Browse all available domains in the P2P network through a clean, searchable web interface.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Web-Based Admin Interface',
|
||||||
|
icon: Code,
|
||||||
|
description:
|
||||||
|
'Comprehensive management panel for domains, Holesail servers/clients, local DNS, certificates, and more.',
|
||||||
|
benefits: ['Full system control', 'Real-time updates', 'WebSocket integration', 'Intuitive UI'],
|
||||||
|
example:
|
||||||
|
'Manage all aspects of your P2NS node through a modern web interface with real-time updates and comprehensive controls.',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Stateful Persistence',
|
||||||
|
icon: Database,
|
||||||
|
description: 'Stores data in Corestore, domains in JSON files, and configurations persist across restarts.',
|
||||||
|
benefits: ['Data durability', 'Automatic backups', 'Easy migration', 'Version control'],
|
||||||
|
example:
|
||||||
|
'All domain claims, votes, and configurations are persisted to disk, ensuring your network survives restarts.',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const CheckIcon = Check;
|
||||||
|
|
||||||
|
export default function FeaturesPage() {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen">
|
||||||
|
{/* Hero */}
|
||||||
|
<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 text-center">
|
||||||
|
<h1 className="text-4xl sm:text-5xl font-bold text-gray-900 dark:text-white mb-6">
|
||||||
|
Comprehensive Features
|
||||||
|
</h1>
|
||||||
|
<p className="text-xl text-gray-600 dark:text-gray-300">
|
||||||
|
P2NS provides everything you need to build and manage a decentralized DNS network
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Features List */}
|
||||||
|
<section className="py-20 bg-white dark:bg-gray-900">
|
||||||
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="space-y-24">
|
||||||
|
{features.map((feature, index) => {
|
||||||
|
const Icon = feature.icon;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MotionDiv
|
||||||
|
key={feature.name}
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ duration: 0.5, delay: index * 0.1 }}
|
||||||
|
className="grid md:grid-cols-3 gap-8 items-start"
|
||||||
|
>
|
||||||
|
<div className="md:col-span-1">
|
||||||
|
<div className="inline-flex p-4 rounded-lg bg-gradient-to-r from-blue-500 to-purple-500 mb-4">
|
||||||
|
<Icon className="h-8 w-8 text-white" />
|
||||||
|
</div>
|
||||||
|
<h2 className="text-2xl font-bold text-gray-900 dark:text-white mb-3">
|
||||||
|
{feature.name}
|
||||||
|
</h2>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300">{feature.description}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="md:col-span-2 space-y-6">
|
||||||
|
<div>
|
||||||
|
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-4">
|
||||||
|
Key Benefits
|
||||||
|
</h3>
|
||||||
|
<ul className="grid sm:grid-cols-2 gap-3">
|
||||||
|
{feature.benefits.map((benefit) => (
|
||||||
|
<li key={benefit} className="flex items-center gap-3">
|
||||||
|
<CheckIcon className="h-5 w-5 text-green-500 flex-shrink-0" />
|
||||||
|
<span className="text-gray-600 dark:text-gray-300">{benefit}</span>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="bg-gray-50 dark:bg-gray-800 p-5 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||||
|
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||||||
|
<strong className="text-gray-900 dark:text-white">Example:</strong>{' '}
|
||||||
|
{feature.example}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</MotionDiv>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* CTA */}
|
||||||
|
<section className="py-20 bg-gradient-to-r from-blue-600 to-purple-600">
|
||||||
|
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||||
|
<h2 className="text-3xl font-bold text-white mb-4">Ready to Get Started?</h2>
|
||||||
|
<p className="text-xl text-blue-100 mb-8">
|
||||||
|
Explore the documentation and start building with P2NS today
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||||
|
<a
|
||||||
|
href="/docs"
|
||||||
|
className="px-8 py-3 border-2 border-white rounded-md text-white hover:bg-white hover:text-blue-600 transition-colors font-medium"
|
||||||
|
>
|
||||||
|
View Documentation
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
@import "tailwindcss";
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--background: #000000;
|
||||||
|
--foreground: #171717;
|
||||||
|
--font-inter: 'Inter', system-ui, sans-serif;
|
||||||
|
--font-mono: 'JetBrains Mono', 'Fira Code', monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
--background: #0a0a0a;
|
||||||
|
--foreground: #ededed;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
background: var(--background);
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
color: var(--foreground);
|
||||||
|
background: var(--background);
|
||||||
|
font-family: var(--font-inter);
|
||||||
|
transition: background-color 0.2s ease, color 0.2s ease;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer utilities {
|
||||||
|
.text-balance {
|
||||||
|
text-wrap: balance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Smooth scrolling */
|
||||||
|
html {
|
||||||
|
scroll-behavior: smooth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Focus styles for accessibility */
|
||||||
|
*:focus-visible {
|
||||||
|
outline: 2px solid rgb(59 130 246);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Code block styling */
|
||||||
|
pre {
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: var(--font-mono);
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Prose adjustments */
|
||||||
|
.prose code {
|
||||||
|
background-color: rgb(243 244 246);
|
||||||
|
padding: 0.125rem 0.375rem;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark .prose code {
|
||||||
|
background-color: rgb(31 41 55);
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose pre {
|
||||||
|
background-color: rgb(17 24 39);
|
||||||
|
color: rgb(243 244 246);
|
||||||
|
}
|
||||||
|
|
||||||
|
.prose pre code {
|
||||||
|
background-color: transparent;
|
||||||
|
padding: 0;
|
||||||
|
color: rgb(243 244 246);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
import type { Metadata } from "next";
|
||||||
|
import { Inter } from "next/font/google";
|
||||||
|
import "./globals.css";
|
||||||
|
import Navigation from "@/components/layout/Navigation";
|
||||||
|
import Footer from "@/components/layout/Footer";
|
||||||
|
|
||||||
|
const inter = Inter({
|
||||||
|
subsets: ["latin"],
|
||||||
|
variable: '--font-inter',
|
||||||
|
});
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "P2NS - Peer-to-Peer Decentralized DNS System",
|
||||||
|
description: "A robust, firewall-resistant peer-to-peer DNS resolution system that operates independently of centralized DNS infrastructure.",
|
||||||
|
keywords: ["P2P", "DNS", "decentralized", "peer-to-peer", "NAT traversal", "firewall", "Holesail", "Hyperswarm", "Corestore"],
|
||||||
|
authors: [{ name: "Raven Scott" }],
|
||||||
|
creator: "Raven Scott",
|
||||||
|
publisher: "P2NS",
|
||||||
|
openGraph: {
|
||||||
|
title: "P2NS - Peer-to-Peer Decentralized DNS System",
|
||||||
|
description: "A robust, firewall-resistant peer-to-peer DNS resolution system",
|
||||||
|
type: "website",
|
||||||
|
siteName: "P2NS",
|
||||||
|
},
|
||||||
|
twitter: {
|
||||||
|
card: "summary_large_image",
|
||||||
|
title: "P2NS - Peer-to-Peer Decentralized DNS System",
|
||||||
|
description: "A robust, firewall-resistant peer-to-peer DNS resolution system",
|
||||||
|
},
|
||||||
|
robots: {
|
||||||
|
index: true,
|
||||||
|
follow: true,
|
||||||
|
},
|
||||||
|
alternates: {
|
||||||
|
canonical: "/",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function RootLayout({
|
||||||
|
children,
|
||||||
|
}: Readonly<{
|
||||||
|
children: React.ReactNode;
|
||||||
|
}>) {
|
||||||
|
const jsonLd = {
|
||||||
|
'@context': 'https://schema.org',
|
||||||
|
'@type': 'SoftwareApplication',
|
||||||
|
name: 'P2NS',
|
||||||
|
applicationCategory: 'NetworkApplication',
|
||||||
|
operatingSystem: 'macOS, Linux',
|
||||||
|
description: 'A robust, firewall-resistant peer-to-peer DNS resolution system',
|
||||||
|
url: 'https://git.ssh.surf/snxraven/p2ns',
|
||||||
|
author: {
|
||||||
|
'@type': 'Person',
|
||||||
|
name: 'Raven Scott',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<html lang="en" className="scroll-smooth bg-black dark:bg-gray-900">
|
||||||
|
<body className={`${inter.variable} antialiased min-h-screen flex flex-col bg-black dark:bg-gray-900`}>
|
||||||
|
<script
|
||||||
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||||
|
/>
|
||||||
|
<Navigation />
|
||||||
|
<main className="flex-1" id="main-content">
|
||||||
|
{children}
|
||||||
|
</main>
|
||||||
|
<Footer />
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,222 @@
|
|||||||
|
import type { Metadata } from 'next';
|
||||||
|
import UDPHolePunchingDiagram from '@/components/diagrams/UDPHolePunchingDiagram';
|
||||||
|
import NATTraversalDiagram from '@/components/diagrams/NATTraversalDiagram';
|
||||||
|
import PeerDiscoveryDiagram from '@/components/diagrams/PeerDiscoveryDiagram';
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: 'How P2P Works - Understanding Peer-to-Peer Networking',
|
||||||
|
description: 'Learn about peer-to-peer networking, UDP hole-punching, NAT traversal, and how P2NS uses these technologies.',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function P2PPage() {
|
||||||
|
return (
|
||||||
|
<div className="min-h-screen">
|
||||||
|
{/* Introduction */}
|
||||||
|
<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">
|
||||||
|
Understanding Peer-to-Peer Networking
|
||||||
|
</h1>
|
||||||
|
<p className="text-xl text-gray-600 dark:text-gray-300 leading-relaxed mb-8">
|
||||||
|
Peer-to-peer (P2P) networking is a distributed architecture where participants (peers) share resources
|
||||||
|
and communicate directly without relying on a central server. P2NS leverages P2P technology to create
|
||||||
|
a resilient, decentralized DNS system.
|
||||||
|
</p>
|
||||||
|
<div className="bg-blue-100 dark:bg-blue-900 border-l-4 border-blue-500 p-4 rounded">
|
||||||
|
<p className="text-sm text-blue-800 dark:text-blue-200">
|
||||||
|
<strong>Key Concept:</strong> In a P2P network, each node can act as both a client and a server,
|
||||||
|
enabling direct communication and resource sharing between peers.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* UDP Hole Punching */}
|
||||||
|
<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">
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||||
|
UDP Hole Punching
|
||||||
|
</h2>
|
||||||
|
<p className="text-lg text-gray-600 dark:text-gray-300 mb-8">
|
||||||
|
UDP hole-punching is a technique that allows two peers behind NAT (Network Address Translation)
|
||||||
|
devices to establish a direct connection. This is essential for P2P networking in environments
|
||||||
|
with firewalls or NAT.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<UDPHolePunchingDiagram />
|
||||||
|
|
||||||
|
<div className="mt-8 prose prose-lg dark:prose-invert max-w-none">
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">How It Works</h3>
|
||||||
|
<ol className="list-decimal pl-6 space-y-3 text-gray-600 dark:text-gray-300">
|
||||||
|
<li>
|
||||||
|
<strong>Both peers contact a rendezvous server:</strong> Each peer sends a UDP packet to a
|
||||||
|
publicly accessible server, which records their public IP addresses and ports.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Exchange connection information:</strong> The server shares each peer's public endpoint
|
||||||
|
with the other peer.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Simultaneous connection attempts:</strong> Both peers attempt to send UDP packets to
|
||||||
|
each other's public endpoints at the same time.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>NAT creates a "hole":</strong> The NAT device sees an outgoing packet and creates a
|
||||||
|
temporary mapping, allowing incoming packets from that destination.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<strong>Direct connection established:</strong> Once the hole is punched, peers can communicate
|
||||||
|
directly without the rendezvous server.
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* NAT Traversal */}
|
||||||
|
<section className="py-20 bg-gray-50 dark:bg-gray-800">
|
||||||
|
<div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||||
|
NAT Traversal
|
||||||
|
</h2>
|
||||||
|
<p className="text-lg text-gray-600 dark:text-gray-300 mb-8">
|
||||||
|
Network Address Translation (NAT) is used by routers to share a single public IP address among multiple
|
||||||
|
devices. NAT traversal techniques allow P2P connections to work through these devices.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<NATTraversalDiagram />
|
||||||
|
|
||||||
|
<div className="mt-8 grid md:grid-cols-2 gap-6">
|
||||||
|
<div className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||||
|
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Types of NAT</h3>
|
||||||
|
<ul className="space-y-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li><strong>Full Cone NAT:</strong> Allows any external host to send packets to the mapped port.</li>
|
||||||
|
<li><strong>Restricted Cone NAT:</strong> Only allows packets from previously contacted hosts.</li>
|
||||||
|
<li><strong>Port Restricted Cone NAT:</strong> Similar to restricted, but also checks the port.</li>
|
||||||
|
<li><strong>Symmetric NAT:</strong> Different external ports for different destinations (most challenging).</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||||
|
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">CGNAT Challenges</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-3">
|
||||||
|
Carrier-Grade NAT (CGNAT) adds an additional layer of NAT, making traversal even more complex.
|
||||||
|
P2NS uses Holesail, which is specifically designed to handle these challenging scenarios.
|
||||||
|
</p>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300">
|
||||||
|
Holesail implements advanced techniques including:
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 mt-2 text-gray-600 dark:text-gray-300">
|
||||||
|
<li>Multiple simultaneous connection attempts</li>
|
||||||
|
<li>Protocol-specific optimizations</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Peer Discovery */}
|
||||||
|
<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">
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||||
|
Peer Discovery with Hyperswarm
|
||||||
|
</h2>
|
||||||
|
<p className="text-lg text-gray-600 dark:text-gray-300 mb-8">
|
||||||
|
Hyperswarm is a distributed hash table (DHT) based peer discovery system. It allows peers to find
|
||||||
|
each other without a central directory server.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<PeerDiscoveryDiagram />
|
||||||
|
|
||||||
|
<div className="mt-8 prose prose-lg dark:prose-invert max-w-none">
|
||||||
|
<h3 className="text-2xl font-semibold text-gray-900 dark:text-white mb-4">How Hyperswarm Works</h3>
|
||||||
|
<div className="space-y-4 text-gray-600 dark:text-gray-300">
|
||||||
|
<p>
|
||||||
|
<strong>Topic-based Discovery:</strong> P2NS uses a fixed topic (derived from 'p2ns-dns') to create
|
||||||
|
a discovery channel. All peers interested in P2NS join this topic.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>DHT Lookup:</strong> When a peer wants to find others, it queries the DHT for the topic.
|
||||||
|
The DHT returns a list of peers that have announced themselves for that topic.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Connection Establishment:</strong> Once peers discover each other, they use the UDP
|
||||||
|
hole-punching techniques described above to establish direct connections.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<strong>Automatic Reconnection:</strong> Hyperswarm automatically handles peer churn, reconnecting
|
||||||
|
when peers go offline and come back online.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Corestore & Autopass */}
|
||||||
|
<section className="py-20 bg-gray-50 dark:bg-gray-800">
|
||||||
|
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-4">
|
||||||
|
Decentralized Storage & Security
|
||||||
|
</h2>
|
||||||
|
<div className="grid md:grid-cols-2 gap-8">
|
||||||
|
<div className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||||
|
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Corestore</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-3">
|
||||||
|
Corestore provides decentralized, append-only storage for P2NS. Domain claims and votes are stored
|
||||||
|
in a distributed ledger that all peers can access and verify.
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-1 text-gray-600 dark:text-gray-300">
|
||||||
|
<li>Append-only structure prevents tampering</li>
|
||||||
|
<li>Cryptographically signed entries</li>
|
||||||
|
<li>Automatic replication across peers</li>
|
||||||
|
<li>Conflict resolution through voting</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||||
|
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-3">Autopass</h3>
|
||||||
|
<p className="text-gray-600 dark:text-gray-300 mb-3">
|
||||||
|
Autopass manages secure writer additions to the Corestore. It ensures only authorized peers can
|
||||||
|
write to the ledger, preventing spam and attacks.
|
||||||
|
</p>
|
||||||
|
<ul className="list-disc pl-6 space-y-1 text-gray-600 dark:text-gray-300">
|
||||||
|
<li>Invitation-based access control</li>
|
||||||
|
<li>Master nodes issue invites</li>
|
||||||
|
<li>Cryptographic verification</li>
|
||||||
|
<li>Prevents unauthorized writes</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Glossary */}
|
||||||
|
<section className="py-20 bg-white dark:bg-gray-900">
|
||||||
|
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<h2 className="text-3xl font-bold text-gray-900 dark:text-white mb-8">
|
||||||
|
Glossary
|
||||||
|
</h2>
|
||||||
|
<dl className="space-y-6">
|
||||||
|
{[
|
||||||
|
{ term: 'NAT (Network Address Translation)', definition: 'A method of remapping IP addresses, allowing multiple devices to share a single public IP address.' },
|
||||||
|
{ term: 'CGNAT (Carrier-Grade NAT)', definition: 'A large-scale NAT implementation used by ISPs to conserve IPv4 addresses, adding complexity to P2P connections.' },
|
||||||
|
{ term: 'UDP Hole Punching', definition: 'A technique that allows two peers behind NAT devices to establish a direct connection by coordinating packet timing.' },
|
||||||
|
{ term: 'DHT (Distributed Hash Table)', definition: 'A decentralized key-value store that allows peers to find each other without a central directory.' },
|
||||||
|
{ term: 'Rendezvous Server', definition: 'A publicly accessible server that helps peers behind NAT discover each other\'s public endpoints.' },
|
||||||
|
{ term: 'Peer Discovery', definition: 'The process of finding other peers in a P2P network, typically using DHT or similar mechanisms.' },
|
||||||
|
{ term: 'Consensus', definition: 'A mechanism for agreeing on the state of distributed data, in P2NS achieved through voting on domain claims.' },
|
||||||
|
].map((item) => (
|
||||||
|
<div key={item.term} className="border-l-4 border-blue-500 pl-4">
|
||||||
|
<dt className="text-lg font-semibold text-gray-900 dark:text-white mb-1">
|
||||||
|
{item.term}
|
||||||
|
</dt>
|
||||||
|
<dd className="text-gray-600 dark:text-gray-300">
|
||||||
|
{item.definition}
|
||||||
|
</dd>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</dl>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import Hero from '@/components/sections/Hero';
|
||||||
|
import FeaturesGrid from '@/components/sections/FeaturesGrid';
|
||||||
|
import HowItWorks from '@/components/sections/HowItWorks';
|
||||||
|
import TechnologyStack from '@/components/sections/TechnologyStack';
|
||||||
|
import QuickStart from '@/components/sections/QuickStart';
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Hero />
|
||||||
|
<FeaturesGrid />
|
||||||
|
<HowItWorks />
|
||||||
|
<TechnologyStack />
|
||||||
|
<QuickStart />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
import { MetadataRoute } from 'next';
|
||||||
|
|
||||||
|
export default async function robots(): Promise<MetadataRoute.Robots> {
|
||||||
|
return {
|
||||||
|
rules: {
|
||||||
|
userAgent: '*',
|
||||||
|
allow: '/',
|
||||||
|
disallow: ['/api/'],
|
||||||
|
},
|
||||||
|
sitemap: 'https://p2ns.example.com/sitemap.xml', // Update with your actual domain
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
import { MetadataRoute } from 'next';
|
||||||
|
|
||||||
|
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
|
||||||
|
const baseUrl = 'https://p2ns.example.com'; // Update with your actual domain
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
url: baseUrl,
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: 'monthly',
|
||||||
|
priority: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${baseUrl}/about`,
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: 'monthly',
|
||||||
|
priority: 0.8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${baseUrl}/learn/p2p`,
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: 'monthly',
|
||||||
|
priority: 0.8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${baseUrl}/features`,
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: 'monthly',
|
||||||
|
priority: 0.8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${baseUrl}/docs`,
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: 'weekly',
|
||||||
|
priority: 0.9,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${baseUrl}/docs/getting-started`,
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: 'weekly',
|
||||||
|
priority: 0.9,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${baseUrl}/docs/configuration`,
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: 'weekly',
|
||||||
|
priority: 0.8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${baseUrl}/docs/examples`,
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: 'weekly',
|
||||||
|
priority: 0.8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${baseUrl}/docs/api`,
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: 'weekly',
|
||||||
|
priority: 0.8,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${baseUrl}/docs/troubleshooting`,
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: 'weekly',
|
||||||
|
priority: 0.7,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${baseUrl}/docs/architecture`,
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: 'monthly',
|
||||||
|
priority: 0.7,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${baseUrl}/examples`,
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: 'monthly',
|
||||||
|
priority: 0.7,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
url: `${baseUrl}/community`,
|
||||||
|
lastModified: new Date(),
|
||||||
|
changeFrequency: 'monthly',
|
||||||
|
priority: 0.6,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import { Network, Database, Shield, Server, Globe, Lock } from 'lucide-react';
|
||||||
|
|
||||||
|
const components = [
|
||||||
|
{
|
||||||
|
name: 'Corestore & Autopass',
|
||||||
|
description: 'Decentralized storage and secure writer additions',
|
||||||
|
icon: Database,
|
||||||
|
position: 'top-left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Hyperswarm',
|
||||||
|
description: 'Peer discovery using fixed topic',
|
||||||
|
icon: Network,
|
||||||
|
position: 'top-center',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'DNS Handler',
|
||||||
|
description: 'UDP server for P2P and public DNS resolution',
|
||||||
|
icon: Globe,
|
||||||
|
position: 'top-right',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Proxy Server',
|
||||||
|
description: 'HTTPS/HTTP with WebSocket support',
|
||||||
|
icon: Server,
|
||||||
|
position: 'bottom-left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Holesail',
|
||||||
|
description: 'Secure UDP Holepunched Tunnels',
|
||||||
|
icon: Shield,
|
||||||
|
position: 'bottom-right',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Certificate Authority',
|
||||||
|
description: 'Automatic TLS certificate generation and management',
|
||||||
|
icon: Lock,
|
||||||
|
position: 'bottom-center',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function ArchitectureDiagram() {
|
||||||
|
return (
|
||||||
|
<div className="relative bg-gray-50 dark:bg-gray-800 rounded-lg p-8 border border-gray-200 dark:border-gray-700">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||||
|
{components.map((component, index) => {
|
||||||
|
const Icon = component.icon;
|
||||||
|
return (
|
||||||
|
<motion.div
|
||||||
|
key={component.name}
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ duration: 0.5, delay: index * 0.1 }}
|
||||||
|
className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700 hover:border-blue-500 dark:hover:border-blue-500 transition-colors"
|
||||||
|
>
|
||||||
|
<div className="flex items-center space-x-3 mb-3">
|
||||||
|
<div className="p-2 bg-blue-100 dark:bg-blue-900 rounded-lg">
|
||||||
|
<Icon className="h-6 w-6 text-blue-600 dark:text-blue-400" />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-lg font-semibold text-gray-900 dark:text-white">
|
||||||
|
{component.name}
|
||||||
|
</h3>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||||||
|
{component.description}
|
||||||
|
</p>
|
||||||
|
</motion.div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-8 text-center">
|
||||||
|
<div className="inline-flex items-center space-x-2 px-4 py-2 bg-blue-100 dark:bg-blue-900 rounded-lg">
|
||||||
|
<Network className="h-5 w-5 text-blue-600 dark:text-blue-400" />
|
||||||
|
<span className="text-sm font-medium text-gray-900 dark:text-white">
|
||||||
|
All components work together to create a resilient P2P DNS system
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import { Router, Globe, Shield } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function NATTraversalDiagram() {
|
||||||
|
return (
|
||||||
|
<div className="bg-gray-50 dark:bg-gray-800 rounded-lg p-8 border border-gray-200 dark:border-gray-700">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||||
|
{/* Local Network */}
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700"
|
||||||
|
>
|
||||||
|
<div className="flex items-center space-x-2 mb-4">
|
||||||
|
<Router className="h-6 w-6 text-blue-600 dark:text-blue-400" />
|
||||||
|
<h3 className="font-semibold text-gray-900 dark:text-white">Local Network</h3>
|
||||||
|
</div>
|
||||||
|
<ul className="space-y-2 text-sm text-gray-600 dark:text-gray-400">
|
||||||
|
<li>• Device 1: 192.168.1.10</li>
|
||||||
|
<li>• Device 2: 192.168.1.11</li>
|
||||||
|
<li>• Device 3: 192.168.1.12</li>
|
||||||
|
</ul>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* NAT Device */}
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ delay: 0.2 }}
|
||||||
|
className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700"
|
||||||
|
>
|
||||||
|
<div className="flex items-center space-x-2 mb-4">
|
||||||
|
<Shield className="h-6 w-6 text-purple-600 dark:text-purple-400" />
|
||||||
|
<h3 className="font-semibold text-gray-900 dark:text-white">NAT Router</h3>
|
||||||
|
</div>
|
||||||
|
<div className="text-sm text-gray-600 dark:text-gray-400 space-y-2">
|
||||||
|
<p><strong>Public IP:</strong> 203.0.113.1</p>
|
||||||
|
<p><strong>Function:</strong></p>
|
||||||
|
<ul className="list-disc pl-4 space-y-1">
|
||||||
|
<li>Maps private IPs to public ports</li>
|
||||||
|
<li>Maintains connection state</li>
|
||||||
|
<li>Blocks unsolicited incoming traffic</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Internet */}
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ delay: 0.4 }}
|
||||||
|
className="bg-white dark:bg-gray-900 p-6 rounded-lg border border-gray-200 dark:border-gray-700"
|
||||||
|
>
|
||||||
|
<div className="flex items-center space-x-2 mb-4">
|
||||||
|
<Globe className="h-6 w-6 text-green-600 dark:text-green-400" />
|
||||||
|
<h3 className="font-semibold text-gray-900 dark:text-white">Internet</h3>
|
||||||
|
</div>
|
||||||
|
<div className="text-sm text-gray-600 dark:text-gray-400 space-y-2">
|
||||||
|
<p><strong>Challenge:</strong></p>
|
||||||
|
<ul className="list-disc pl-4 space-y-1">
|
||||||
|
<li>Devices behind NAT can't receive direct connections</li>
|
||||||
|
<li>UDP hole-punching creates temporary openings</li>
|
||||||
|
<li>CGNAT adds additional complexity</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-6 p-4 bg-blue-50 dark:bg-blue-900 rounded-lg border border-blue-200 dark:border-blue-700">
|
||||||
|
<p className="text-sm text-blue-800 dark:text-blue-200">
|
||||||
|
<strong>P2NS Solution:</strong> Holesail uses advanced UDP hole-punching techniques and relay servers
|
||||||
|
to establish connections even through multiple layers of NAT and CGNAT.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import { Network, Search, Users } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function PeerDiscoveryDiagram() {
|
||||||
|
return (
|
||||||
|
<div className="bg-gray-50 dark:bg-gray-800 rounded-lg p-8 border border-gray-200 dark:border-gray-700">
|
||||||
|
<div className="text-center mb-8">
|
||||||
|
<div className="inline-flex items-center space-x-2 px-4 py-2 bg-purple-100 dark:bg-purple-900 rounded-lg mb-4">
|
||||||
|
<Search className="h-5 w-5 text-purple-600 dark:text-purple-400" />
|
||||||
|
<span className="text-sm font-medium text-gray-900 dark:text-white">
|
||||||
|
Topic: sha256('p2ns-dns')
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-4 gap-6">
|
||||||
|
{[
|
||||||
|
{ name: 'Peer 1', status: 'Online' },
|
||||||
|
{ name: 'Peer 2', status: 'Online' },
|
||||||
|
{ name: 'Peer 3', status: 'Online' },
|
||||||
|
{ name: 'Peer 4', status: 'Online' },
|
||||||
|
].map((peer, index) => (
|
||||||
|
<motion.div
|
||||||
|
key={peer.name}
|
||||||
|
initial={{ opacity: 0, scale: 0.9 }}
|
||||||
|
whileInView={{ opacity: 1, scale: 1 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ duration: 0.3, delay: index * 0.1 }}
|
||||||
|
className="bg-white dark:bg-gray-900 p-4 rounded-lg border border-gray-200 dark:border-gray-700 text-center"
|
||||||
|
>
|
||||||
|
<Network className="h-8 w-8 text-blue-600 dark:text-blue-400 mx-auto mb-2" />
|
||||||
|
<h4 className="font-semibold text-gray-900 dark:text-white text-sm mb-1">
|
||||||
|
{peer.name}
|
||||||
|
</h4>
|
||||||
|
<span className="inline-flex items-center px-2 py-1 rounded-full text-xs font-medium bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200">
|
||||||
|
{peer.status}
|
||||||
|
</span>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-8 grid md:grid-cols-3 gap-6">
|
||||||
|
<div className="bg-white dark:bg-gray-900 p-4 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||||
|
<h4 className="font-semibold text-gray-900 dark:text-white mb-2 text-sm">1. Join Topic</h4>
|
||||||
|
<p className="text-xs text-gray-600 dark:text-gray-400">
|
||||||
|
Peers announce themselves to the DHT using the P2NS topic
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="bg-white dark:bg-gray-900 p-4 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||||
|
<h4 className="font-semibold text-gray-900 dark:text-white mb-2 text-sm">2. Discover Peers</h4>
|
||||||
|
<p className="text-xs text-gray-600 dark:text-gray-400">
|
||||||
|
Query the DHT to find other peers interested in the same topic
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="bg-white dark:bg-gray-900 p-4 rounded-lg border border-gray-200 dark:border-gray-700">
|
||||||
|
<h4 className="font-semibold text-gray-900 dark:text-white mb-2 text-sm">3. Connect</h4>
|
||||||
|
<p className="text-xs text-gray-600 dark:text-gray-400">
|
||||||
|
Establish direct connections using UDP hole-punching
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-6 p-4 bg-purple-50 dark:bg-purple-900 rounded-lg border border-purple-200 dark:border-purple-700">
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<Users className="h-5 w-5 text-purple-600 dark:text-purple-400" />
|
||||||
|
<p className="text-sm text-purple-800 dark:text-purple-200">
|
||||||
|
<strong>Hyperswarm</strong> automatically handles peer churn and reconnection, ensuring the network
|
||||||
|
remains connected even as peers join and leave.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import { Network, Server, ArrowRight, ArrowLeft } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function UDPHolePunchingDiagram() {
|
||||||
|
return (
|
||||||
|
<div className="bg-gray-50 dark:bg-gray-800 rounded-lg p-8 border border-gray-200 dark:border-gray-700">
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 items-center">
|
||||||
|
{/* Peer A */}
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, x: -20 }}
|
||||||
|
whileInView={{ opacity: 1, x: 0 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
className="text-center"
|
||||||
|
>
|
||||||
|
<div className="bg-blue-100 dark:bg-blue-900 p-6 rounded-lg mb-4">
|
||||||
|
<Network className="h-12 w-12 text-blue-600 dark:text-blue-400 mx-auto mb-2" />
|
||||||
|
<h3 className="font-semibold text-gray-900 dark:text-white">Peer A</h3>
|
||||||
|
<p className="text-sm text-gray-600 dark:text-gray-400">Behind NAT</p>
|
||||||
|
</div>
|
||||||
|
<div className="text-sm text-gray-600 dark:text-gray-400">
|
||||||
|
<p>Private IP: 192.168.1.10</p>
|
||||||
|
<p>Public: 203.0.113.1:5000</p>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Rendezvous Server */}
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ delay: 0.2 }}
|
||||||
|
className="text-center"
|
||||||
|
>
|
||||||
|
<div className="bg-purple-100 dark:bg-purple-900 p-6 rounded-lg mb-4">
|
||||||
|
<Server className="h-12 w-12 text-purple-600 dark:text-purple-400 mx-auto mb-2" />
|
||||||
|
<h3 className="font-semibold text-gray-900 dark:text-white">Rendezvous</h3>
|
||||||
|
<p className="text-sm text-gray-600 dark:text-gray-400">Server</p>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-2">
|
||||||
|
<div className="flex items-center justify-center space-x-2 text-sm">
|
||||||
|
<ArrowRight className="h-4 w-4 text-green-500" />
|
||||||
|
<span className="text-gray-600 dark:text-gray-400">Exchange info</span>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center justify-center space-x-2 text-sm">
|
||||||
|
<ArrowLeft className="h-4 w-4 text-green-500" />
|
||||||
|
<span className="text-gray-600 dark:text-gray-400">Coordinate</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
{/* Peer B */}
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, x: 20 }}
|
||||||
|
whileInView={{ opacity: 1, x: 0 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ delay: 0.4 }}
|
||||||
|
className="text-center"
|
||||||
|
>
|
||||||
|
<div className="bg-green-100 dark:bg-green-900 p-6 rounded-lg mb-4">
|
||||||
|
<Network className="h-12 w-12 text-green-600 dark:text-green-400 mx-auto mb-2" />
|
||||||
|
<h3 className="font-semibold text-gray-900 dark:text-white">Peer B</h3>
|
||||||
|
<p className="text-sm text-gray-600 dark:text-gray-400">Behind NAT</p>
|
||||||
|
</div>
|
||||||
|
<div className="text-sm text-gray-600 dark:text-gray-400">
|
||||||
|
<p>Private IP: 10.0.0.5</p>
|
||||||
|
<p>Public: 198.51.100.2:6000</p>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-8 pt-8 border-t border-gray-200 dark:border-gray-700">
|
||||||
|
<div className="text-center">
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
whileInView={{ opacity: 1 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ delay: 0.6 }}
|
||||||
|
className="inline-flex items-center space-x-2 px-4 py-2 bg-green-100 dark:bg-green-900 rounded-lg"
|
||||||
|
>
|
||||||
|
<ArrowRight className="h-5 w-5 text-green-600 dark:text-green-400" />
|
||||||
|
<span className="text-sm font-medium text-gray-900 dark:text-white">
|
||||||
|
After hole-punching, peers connect directly
|
||||||
|
</span>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
import Link from 'next/link';
|
||||||
|
import { Github, ExternalLink } from 'lucide-react';
|
||||||
|
|
||||||
|
export default function Footer() {
|
||||||
|
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">
|
||||||
|
<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>
|
||||||
|
<p className="text-sm text-gray-600 dark:text-gray-400 mb-4">
|
||||||
|
A robust, firewall-resistant peer-to-peer DNS resolution system that operates independently of centralized DNS infrastructure.
|
||||||
|
</p>
|
||||||
|
<a
|
||||||
|
href="https://git.ssh.surf/snxraven/p2ns"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="inline-flex items-center space-x-2 text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
|
||||||
|
>
|
||||||
|
<Github size={16} />
|
||||||
|
<span>View on Git</span>
|
||||||
|
<ExternalLink size={14} />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4 className="text-sm font-semibold mb-4 text-gray-900 dark:text-gray-100">Documentation</h4>
|
||||||
|
<ul className="space-y-2">
|
||||||
|
<li>
|
||||||
|
<Link href="/docs" className="text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
|
||||||
|
Getting Started
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Link href="/learn/p2p" className="text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
|
||||||
|
Learn P2P
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Link href="/features" className="text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
|
||||||
|
Features
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4 className="text-sm font-semibold mb-4 text-gray-900 dark:text-gray-100">Community</h4>
|
||||||
|
<ul className="space-y-2">
|
||||||
|
<li>
|
||||||
|
<Link href="/community" className="text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
|
||||||
|
Contributing
|
||||||
|
</Link>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<Link href="/about" className="text-sm text-gray-600 dark:text-gray-400 hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
|
||||||
|
About
|
||||||
|
</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.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,118 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { Menu, X, Ship } from 'lucide-react';
|
||||||
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
|
import PearsIcon from '@/components/ui/PearsIcon';
|
||||||
|
|
||||||
|
const navItems = [
|
||||||
|
{ name: 'Home', href: '/' },
|
||||||
|
{ name: 'About', href: '/about' },
|
||||||
|
{ name: 'Learn P2P', href: '/learn/p2p' },
|
||||||
|
{ name: 'Features', href: '/features' },
|
||||||
|
{ name: 'Docs', href: '/docs' },
|
||||||
|
{ name: 'Community', href: '/community' },
|
||||||
|
];
|
||||||
|
|
||||||
|
const externalNavItems = [
|
||||||
|
{ name: 'Holesail.io', href: 'https://holesail.io', icon: Ship },
|
||||||
|
{ name: 'Built with Pears', href: 'https://pears.com', icon: PearsIcon },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function Navigation() {
|
||||||
|
const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav className="sticky top-0 z-50 w-full border-b border-gray-200 dark:border-gray-800 bg-white/80 dark:bg-gray-900/80 backdrop-blur-sm">
|
||||||
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="flex justify-between items-center h-16">
|
||||||
|
<Link href="/" className="flex items-center space-x-2">
|
||||||
|
<span className="text-2xl font-bold bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
|
||||||
|
P2NS
|
||||||
|
</span>
|
||||||
|
</Link>
|
||||||
|
|
||||||
|
{/* Desktop Navigation */}
|
||||||
|
<div className="hidden md:flex items-center space-x-8">
|
||||||
|
{navItems.map((item) => (
|
||||||
|
<Link
|
||||||
|
key={item.href}
|
||||||
|
href={item.href}
|
||||||
|
className="text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
{externalNavItems.map((item) => {
|
||||||
|
const Icon = item.icon;
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
key={item.href}
|
||||||
|
href={item.href}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-sm font-medium text-gray-700 dark:text-gray-300 hover:text-blue-600 dark:hover:text-blue-400 transition-colors flex items-center space-x-1.5"
|
||||||
|
>
|
||||||
|
<Icon className="h-4 w-4" />
|
||||||
|
<span>{item.name}</span>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Mobile Menu Button */}
|
||||||
|
<button
|
||||||
|
className="md:hidden p-2 rounded-md text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800"
|
||||||
|
onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
|
||||||
|
aria-label="Toggle menu"
|
||||||
|
>
|
||||||
|
{mobileMenuOpen ? <X size={24} /> : <Menu size={24} />}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Mobile Menu */}
|
||||||
|
<AnimatePresence>
|
||||||
|
{mobileMenuOpen && (
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, height: 0 }}
|
||||||
|
animate={{ opacity: 1, height: 'auto' }}
|
||||||
|
exit={{ opacity: 0, height: 0 }}
|
||||||
|
className="md:hidden border-t border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-900"
|
||||||
|
>
|
||||||
|
<div className="px-4 pt-2 pb-4 space-y-1">
|
||||||
|
{navItems.map((item) => (
|
||||||
|
<Link
|
||||||
|
key={item.href}
|
||||||
|
href={item.href}
|
||||||
|
className="block px-3 py-2 rounded-md text-base font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
|
||||||
|
onClick={() => setMobileMenuOpen(false)}
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
{externalNavItems.map((item) => {
|
||||||
|
const Icon = item.icon;
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
key={item.href}
|
||||||
|
href={item.href}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="flex items-center space-x-2 px-3 py-2 rounded-md text-base font-medium text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800 hover:text-blue-600 dark:hover:text-blue-400 transition-colors"
|
||||||
|
onClick={() => setMobileMenuOpen(false)}
|
||||||
|
>
|
||||||
|
<Icon className="h-4 w-4" />
|
||||||
|
<span>{item.name}</span>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
)}
|
||||||
|
</AnimatePresence>
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import {
|
||||||
|
Network,
|
||||||
|
Shield,
|
||||||
|
Zap,
|
||||||
|
Globe,
|
||||||
|
Lock,
|
||||||
|
Settings,
|
||||||
|
Server,
|
||||||
|
Users,
|
||||||
|
} from 'lucide-react';
|
||||||
|
|
||||||
|
const features = [
|
||||||
|
{
|
||||||
|
name: 'Decentralized DNS',
|
||||||
|
description: 'Resolve domains to hashes via P2P core, independent of ICANN or central DNS servers.',
|
||||||
|
icon: Network,
|
||||||
|
color: 'from-blue-500 to-blue-600',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Firewall Traversal',
|
||||||
|
description: 'Uses Holesail for UDP hole-punching to connect across restrictive networks, NAT, and CGNAT.',
|
||||||
|
icon: Shield,
|
||||||
|
color: 'from-green-500 to-green-600',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Dynamic IP Assignment',
|
||||||
|
description: 'Assigns unique local IPs to domains via virtual network interfaces for seamless routing.',
|
||||||
|
icon: Zap,
|
||||||
|
color: 'from-yellow-500 to-yellow-600',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Hybrid DNS Resolution',
|
||||||
|
description: 'Falls back to public DNS for non-P2P domains with custom local DNS record support.',
|
||||||
|
icon: Globe,
|
||||||
|
color: 'from-purple-500 to-purple-600',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Integrated Proxy',
|
||||||
|
description: 'HTTP/HTTPS proxies with automatic redirection, WebSocket support, and TLS management.',
|
||||||
|
icon: Server,
|
||||||
|
color: 'from-red-500 to-red-600',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Certificate Authority',
|
||||||
|
description: 'Automatic certificate generation and installation with root CA and per-domain certificates.',
|
||||||
|
icon: Lock,
|
||||||
|
color: 'from-indigo-500 to-indigo-600',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Admin Interface',
|
||||||
|
description: 'Comprehensive web-based management panel for domains, servers, DNS, and certificates.',
|
||||||
|
icon: Settings,
|
||||||
|
color: 'from-pink-500 to-pink-600',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Peer Directory',
|
||||||
|
description: 'Web-based directory for browsing and searching domains across the P2P network.',
|
||||||
|
icon: Users,
|
||||||
|
color: 'from-cyan-500 to-cyan-600',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function FeaturesGrid() {
|
||||||
|
return (
|
||||||
|
<section className="py-24 bg-white dark:bg-gray-900">
|
||||||
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="text-center mb-16">
|
||||||
|
<h2 className="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
||||||
|
Powerful Features
|
||||||
|
</h2>
|
||||||
|
<p className="text-lg text-gray-600 dark:text-gray-300 max-w-2xl mx-auto">
|
||||||
|
Everything you need to build and manage a decentralized DNS network
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||||
|
{features.map((feature, index) => {
|
||||||
|
const Icon = feature.icon;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<motion.div
|
||||||
|
key={feature.name}
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ duration: 0.5, delay: index * 0.1 }}
|
||||||
|
className="relative group"
|
||||||
|
>
|
||||||
|
<div className="bg-white dark:bg-gray-800 rounded-lg p-6 border border-gray-200 dark:border-gray-700 hover:border-blue-500 dark:hover:border-blue-500 transition-all hover:shadow-lg h-full">
|
||||||
|
<div className={`inline-flex p-3 rounded-lg bg-gradient-to-r ${feature.color} mb-4`}>
|
||||||
|
<Icon className="h-6 w-6 text-white" />
|
||||||
|
</div>
|
||||||
|
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">
|
||||||
|
{feature.name}
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||||||
|
{feature.description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import Link from 'next/link';
|
||||||
|
import { ArrowRight, Zap } from 'lucide-react';
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
|
||||||
|
export default function Hero() {
|
||||||
|
return (
|
||||||
|
<section className="relative overflow-hidden bg-gradient-to-b from-blue-50 via-white to-white dark:from-gray-900 dark:via-gray-900 dark:to-gray-900 py-20 sm:py-32">
|
||||||
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="text-center">
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ duration: 0.5 }}
|
||||||
|
>
|
||||||
|
<h1 className="text-4xl sm:text-5xl md:text-6xl font-bold tracking-tight text-gray-900 dark:text-white mb-6">
|
||||||
|
Decentralized DNS for the
|
||||||
|
<span className="block bg-gradient-to-r from-blue-600 to-purple-600 bg-clip-text text-transparent">
|
||||||
|
Modern Internet
|
||||||
|
</span>
|
||||||
|
</h1>
|
||||||
|
<p className="mt-6 text-lg sm:text-xl text-gray-600 dark:text-gray-300 max-w-3xl mx-auto">
|
||||||
|
P2NS is a robust, firewall-resistant peer-to-peer DNS resolution system that operates independently of centralized DNS infrastructure.
|
||||||
|
Connect across firewalls, NAT, CGNAT, and restricted networks with ease.
|
||||||
|
</p>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
animate={{ opacity: 1, y: 0 }}
|
||||||
|
transition={{ duration: 0.5, delay: 0.2 }}
|
||||||
|
className="mt-10 flex flex-col sm:flex-row gap-4 justify-center"
|
||||||
|
>
|
||||||
|
<Link
|
||||||
|
href="/docs"
|
||||||
|
className="inline-flex items-center justify-center px-6 py-3 border border-transparent text-base font-medium rounded-md text-white bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 transition-all shadow-lg hover:shadow-xl"
|
||||||
|
>
|
||||||
|
Get Started
|
||||||
|
<ArrowRight className="ml-2 h-5 w-5" />
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href="/learn/p2p"
|
||||||
|
className="inline-flex items-center justify-center px-6 py-3 border border-gray-300 dark:border-gray-700 text-base font-medium rounded-md text-gray-700 dark:text-gray-300 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
|
||||||
|
>
|
||||||
|
Learn How P2P Works
|
||||||
|
<Zap className="ml-2 h-5 w-5" />
|
||||||
|
</Link>
|
||||||
|
</motion.div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0 }}
|
||||||
|
animate={{ opacity: 1 }}
|
||||||
|
transition={{ duration: 0.5, delay: 0.4 }}
|
||||||
|
className="mt-16"
|
||||||
|
>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import { Search, Network, Lock, CheckCircle } from 'lucide-react';
|
||||||
|
|
||||||
|
const steps = [
|
||||||
|
{
|
||||||
|
number: '01',
|
||||||
|
title: 'Discover Peers',
|
||||||
|
description: 'Hyperswarm discovers peers using a fixed topic, enabling automatic peer discovery across the network.',
|
||||||
|
icon: Search,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
number: '02',
|
||||||
|
title: 'Establish Connection',
|
||||||
|
description: 'UDP hole-punching via Holesail creates connections across firewalls, NAT, and CGNAT.',
|
||||||
|
icon: Network,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
number: '03',
|
||||||
|
title: 'Resolve Domains',
|
||||||
|
description: 'Domains are resolved to Holesail hashes through the decentralized P2P network with consensus voting.',
|
||||||
|
icon: Lock,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
number: '04',
|
||||||
|
title: 'Route Traffic',
|
||||||
|
description: 'Virtual interfaces assign local IPs, and integrated proxies route traffic through secure tunnels.',
|
||||||
|
icon: CheckCircle,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function HowItWorks() {
|
||||||
|
return (
|
||||||
|
<section className="py-24 bg-gray-50 dark:bg-gray-800">
|
||||||
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="text-center mb-16">
|
||||||
|
<h2 className="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
||||||
|
How It Works
|
||||||
|
</h2>
|
||||||
|
<p className="text-lg text-gray-600 dark:text-gray-300 max-w-2xl mx-auto">
|
||||||
|
P2NS uses cutting-edge P2P technology to create a resilient, decentralized DNS system
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||||
|
{steps.map((step, index) => (
|
||||||
|
<motion.div
|
||||||
|
key={step.number}
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ duration: 0.5, delay: index * 0.1 }}
|
||||||
|
className="relative"
|
||||||
|
>
|
||||||
|
<div className="bg-white dark:bg-gray-900 rounded-lg p-6 border border-gray-200 dark:border-gray-700 h-full">
|
||||||
|
<div className="flex items-center justify-between mb-4">
|
||||||
|
<span className="text-4xl font-bold text-gray-200 dark:text-gray-700">
|
||||||
|
{step.number}
|
||||||
|
</span>
|
||||||
|
<div className="p-3 rounded-lg bg-blue-100 dark:bg-blue-900">
|
||||||
|
<step.icon className="h-6 w-6 text-blue-600 dark:text-blue-400" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h3 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">
|
||||||
|
{step.title}
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||||||
|
{step.description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{index < steps.length - 1 && (
|
||||||
|
<div className="hidden lg:block absolute top-1/2 -right-4 w-8 h-0.5 bg-gray-300 dark:bg-gray-600 transform -translate-y-1/2" />
|
||||||
|
)}
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import { Terminal, Copy, Check } from 'lucide-react';
|
||||||
|
import { useState } from 'react';
|
||||||
|
|
||||||
|
const commands = [
|
||||||
|
{ label: 'Clone repository', command: 'git clone https://git.ssh.surf/snxraven/p2ns.git' },
|
||||||
|
{ label: 'Install dependencies', command: 'npm install' },
|
||||||
|
{ label: 'Run as master node', command: 'sudo node p2ns.js' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function QuickStart() {
|
||||||
|
const [copiedIndex, setCopiedIndex] = useState<number | null>(null);
|
||||||
|
|
||||||
|
const copyToClipboard = (text: string, index: number) => {
|
||||||
|
navigator.clipboard.writeText(text);
|
||||||
|
setCopiedIndex(index);
|
||||||
|
setTimeout(() => setCopiedIndex(null), 2000);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="py-24 bg-gradient-to-b from-gray-50 to-white dark:from-gray-800 dark:to-gray-900">
|
||||||
|
<div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="text-center mb-12">
|
||||||
|
<h2 className="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
||||||
|
Quick Start
|
||||||
|
</h2>
|
||||||
|
<p className="text-lg text-gray-600 dark:text-gray-300">
|
||||||
|
Get P2NS running in minutes
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
{commands.map((item, index) => (
|
||||||
|
<motion.div
|
||||||
|
key={index}
|
||||||
|
initial={{ opacity: 0, x: -20 }}
|
||||||
|
whileInView={{ opacity: 1, x: 0 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ duration: 0.3, delay: index * 0.1 }}
|
||||||
|
className="bg-gray-900 dark:bg-black rounded-lg p-4 border border-gray-800"
|
||||||
|
>
|
||||||
|
<div className="flex items-center justify-between mb-2">
|
||||||
|
<span className="text-sm text-gray-400">{item.label}</span>
|
||||||
|
<button
|
||||||
|
onClick={() => copyToClipboard(item.command, index)}
|
||||||
|
className="p-1 text-gray-400 hover:text-white transition-colors"
|
||||||
|
aria-label="Copy command"
|
||||||
|
>
|
||||||
|
{copiedIndex === index ? (
|
||||||
|
<Check className="h-4 w-4 text-green-500" />
|
||||||
|
) : (
|
||||||
|
<Copy className="h-4 w-4" />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="flex items-center space-x-2">
|
||||||
|
<Terminal className="h-4 w-4 text-green-400" />
|
||||||
|
<code className="text-sm text-gray-300 font-mono">{item.command}</code>
|
||||||
|
</div>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<motion.div
|
||||||
|
initial={{ opacity: 0, y: 20 }}
|
||||||
|
whileInView={{ opacity: 1, y: 0 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ duration: 0.5, delay: 0.4 }}
|
||||||
|
className="mt-8 text-center"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="/docs"
|
||||||
|
className="inline-flex items-center text-blue-600 dark:text-blue-400 hover:underline font-medium"
|
||||||
|
>
|
||||||
|
View full documentation
|
||||||
|
<span className="ml-1">→</span>
|
||||||
|
</a>
|
||||||
|
</motion.div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
|
||||||
|
const technologies = [
|
||||||
|
{ name: 'Corestore', description: 'Decentralized storage' },
|
||||||
|
{ name: 'Hyperswarm', description: 'Peer discovery' },
|
||||||
|
{ name: 'Holesail', description: 'UDP hole-punching' },
|
||||||
|
{ name: 'Autopass', description: 'Secure invitations' },
|
||||||
|
{ name: 'Node.js', description: 'Runtime environment' },
|
||||||
|
{ name: 'Protomux', description: 'Channel multiplexing' },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function TechnologyStack() {
|
||||||
|
return (
|
||||||
|
<section className="py-24 bg-white dark:bg-gray-900">
|
||||||
|
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div className="text-center mb-16">
|
||||||
|
<h2 className="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-white mb-4">
|
||||||
|
Built on Modern Technology
|
||||||
|
</h2>
|
||||||
|
<p className="text-lg text-gray-600 dark:text-gray-300 max-w-2xl mx-auto">
|
||||||
|
P2NS leverages proven P2P technologies to create a robust, scalable DNS system
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-6">
|
||||||
|
{technologies.map((tech, index) => (
|
||||||
|
<motion.div
|
||||||
|
key={tech.name}
|
||||||
|
initial={{ opacity: 0, scale: 0.9 }}
|
||||||
|
whileInView={{ opacity: 1, scale: 1 }}
|
||||||
|
viewport={{ once: true }}
|
||||||
|
transition={{ duration: 0.3, delay: index * 0.1 }}
|
||||||
|
className="text-center p-6 bg-gray-50 dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 hover:border-blue-500 dark:hover:border-blue-500 transition-colors"
|
||||||
|
>
|
||||||
|
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-1">
|
||||||
|
{tech.name}
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-gray-600 dark:text-gray-400">
|
||||||
|
{tech.description}
|
||||||
|
</p>
|
||||||
|
</motion.div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { Copy, Check } from 'lucide-react';
|
||||||
|
|
||||||
|
interface CodeBlockProps {
|
||||||
|
code: string;
|
||||||
|
language?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function CodeBlock({ code, language = 'bash' }: CodeBlockProps) {
|
||||||
|
const [copied, setCopied] = useState(false);
|
||||||
|
|
||||||
|
const copyToClipboard = () => {
|
||||||
|
navigator.clipboard.writeText(code);
|
||||||
|
setCopied(true);
|
||||||
|
setTimeout(() => setCopied(false), 2000);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="relative group">
|
||||||
|
<div className="absolute top-2 right-2">
|
||||||
|
<button
|
||||||
|
onClick={copyToClipboard}
|
||||||
|
className="p-2 bg-gray-700 hover:bg-gray-600 rounded text-gray-300 hover:text-white transition-colors opacity-0 group-hover:opacity-100"
|
||||||
|
aria-label="Copy code"
|
||||||
|
>
|
||||||
|
{copied ? (
|
||||||
|
<Check className="h-4 w-4 text-green-400" />
|
||||||
|
) : (
|
||||||
|
<Copy className="h-4 w-4" />
|
||||||
|
)}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<pre className="bg-gray-900 text-gray-100 p-4 rounded-lg overflow-x-auto">
|
||||||
|
<code className={`language-${language}`}>{code}</code>
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { motion } from 'framer-motion';
|
||||||
|
import type { MotionProps } from 'framer-motion';
|
||||||
|
import { forwardRef } from 'react';
|
||||||
|
|
||||||
|
interface Props extends MotionProps {
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const MotionDiv = forwardRef<HTMLDivElement, Props>(
|
||||||
|
(props, ref) => <motion.div ref={ref} {...props} />
|
||||||
|
);
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
export default function PearsIcon({ className }: { className?: string }) {
|
||||||
|
return (
|
||||||
|
<svg width="22" height="22" viewBox="0 0 127 182" fill="none" xmlns="http://www.w3.org/2000/svg" className={className}>
|
||||||
|
<path d="M58.9658 0H68.0374V17.9736H58.9658V0Z" fill="#B0D944"></path>
|
||||||
|
<path d="M54.4299 23.6604V27.3005H45.3583V31.8506H81.6449V27.3005H72.5732V20.2471H63.5016V23.6604H54.4299Z" fill="#B0D944"></path>
|
||||||
|
<path d="M90.7166 34.124H63.5016V37.5374H36.2866V45.7275H90.7166V34.124Z" fill="#B0D944"></path>
|
||||||
|
<path d="M99.7882 48.0041H63.5016V51.4175H27.215V59.6076H99.7882V48.0041Z" fill="#B0D944"></path>
|
||||||
|
<path d="M99.7882 61.8811H63.5016V65.2944H27.215V73.4846H99.7882V61.8811Z" fill="#B0D944"></path>
|
||||||
|
<path d="M108.86 75.758H63.5016V79.1714H18.1433V87.3615H108.86V75.758Z" fill="#B0D944"></path>
|
||||||
|
<path d="M108.86 89.635H63.5016V93.0483H18.1433V101.238H108.86V89.635Z" fill="#B0D944"></path>
|
||||||
|
<path d="M63.4984 103.512V106.925H9.07166V115.115H117.932V103.512H63.4984Z" fill="#B0D944"></path>
|
||||||
|
<path d="M127 117.392H63.4984V120.805H0V128.996H127V117.392Z" fill="#B0D944"></path>
|
||||||
|
<path d="M127 131.269H63.4984V134.682H0V142.873H127V131.269Z" fill="#B0D944"></path>
|
||||||
|
<path d="M127 145.146H63.4984V148.559H0V156.749H127V145.146Z" fill="#B0D944"></path>
|
||||||
|
<path d="M108.86 159.023H63.5016V162.436H18.1433V170.626H108.86V159.023Z" fill="#B0D944"></path>
|
||||||
|
<path d="M90.7166 172.9H63.5016V176.313H36.2866V182H90.7166V172.9Z" fill="#B0D944"></path>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
website:
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
environment:
|
||||||
|
- NODE_ENV=production
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
import { defineConfig, globalIgnores } from "eslint/config";
|
||||||
|
import nextVitals from "eslint-config-next/core-web-vitals";
|
||||||
|
import nextTs from "eslint-config-next/typescript";
|
||||||
|
|
||||||
|
const eslintConfig = defineConfig([
|
||||||
|
...nextVitals,
|
||||||
|
...nextTs,
|
||||||
|
// Override default ignores of eslint-config-next.
|
||||||
|
globalIgnores([
|
||||||
|
// Default ignores of eslint-config-next:
|
||||||
|
".next/**",
|
||||||
|
"out/**",
|
||||||
|
"build/**",
|
||||||
|
"next-env.d.ts",
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
|
||||||
|
export default eslintConfig;
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/** @type {import('next').NextConfig} */
|
||||||
|
const nextConfig = {
|
||||||
|
reactStrictMode: true,
|
||||||
|
images: {
|
||||||
|
formats: ['image/avif', 'image/webp'],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = nextConfig
|
||||||
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import type { NextConfig } from "next";
|
||||||
|
|
||||||
|
const nextConfig: NextConfig = {
|
||||||
|
/* config options here */
|
||||||
|
};
|
||||||
|
|
||||||
|
export default nextConfig;
|
||||||
Generated
+7275
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"name": "p2ns-website",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"dev": "next dev",
|
||||||
|
"build": "next build",
|
||||||
|
"start": "next start",
|
||||||
|
"lint": "next lint"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"framer-motion": "^11.0.0",
|
||||||
|
"lucide-react": "^0.554.0",
|
||||||
|
"shiki": "^1.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tailwindcss/postcss": "^4.1.17",
|
||||||
|
"@types/node": "^20.19.25",
|
||||||
|
"@types/react": "^19.2.6",
|
||||||
|
"@types/react-dom": "^19.2.3",
|
||||||
|
"autoprefixer": "^10.4.22",
|
||||||
|
"eslint": "^9.39.1",
|
||||||
|
"eslint-config-next": "^16.0.3",
|
||||||
|
"next": "^16.0.3",
|
||||||
|
"postcss": "^8.5.6",
|
||||||
|
"react": "^19.2.0",
|
||||||
|
"react-dom": "^19.2.0",
|
||||||
|
"tailwindcss": "^4.1.17",
|
||||||
|
"typescript": "^5.9.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
const config = {
|
||||||
|
plugins: {
|
||||||
|
"@tailwindcss/postcss": {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>
|
||||||
|
After Width: | Height: | Size: 391 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>
|
||||||
|
After Width: | Height: | Size: 1.0 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1 @@
|
|||||||
|
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>
|
||||||
|
After Width: | Height: | Size: 128 B |
@@ -0,0 +1 @@
|
|||||||
|
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>
|
||||||
|
After Width: | Height: | Size: 385 B |
@@ -0,0 +1,25 @@
|
|||||||
|
import type { Config } from "tailwindcss";
|
||||||
|
|
||||||
|
const config: Config = {
|
||||||
|
content: [
|
||||||
|
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
|
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
|
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
background: "var(--background)",
|
||||||
|
foreground: "var(--foreground)",
|
||||||
|
},
|
||||||
|
fontFamily: {
|
||||||
|
sans: ['var(--font-inter)', 'system-ui', 'sans-serif'],
|
||||||
|
mono: ['var(--font-mono)', 'monospace'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [],
|
||||||
|
darkMode: 'class',
|
||||||
|
};
|
||||||
|
export default config;
|
||||||
|
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2020",
|
||||||
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"esnext"
|
||||||
|
],
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"incremental": true,
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"name": "next"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"paths": {
|
||||||
|
"@/*": [
|
||||||
|
"./*"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
"next-env.d.ts",
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
".next/types/**/*.ts",
|
||||||
|
".next/dev/types/**/*.ts"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user