From f8b3299c1fc99b9a346785c078dde7471497c5dd Mon Sep 17 00:00:00 2001
From: Yury Pikhtarev
Date: Tue, 1 Jul 2025 00:26:49 +0400
Subject: [PATCH] feat: add Docusaurus documentation setup and deployment
workflow
- Introduced Docusaurus for TorrentPier documentation, including configuration files and initial content structure.
- Created a GitHub Actions workflow for automatic deployment of documentation to GitHub Pages upon changes to the 'docs' directory.
- Updated .gitignore to exclude Docusaurus build artifacts and cache directories.
- Added essential scripts in package.json for local development and building of documentation.
- Included initial README and sidebars configuration for documentation navigation.
These changes establish a comprehensive documentation framework for TorrentPier, enhancing accessibility and user guidance.
---
.github/workflows/docs.yml | 64 ++++
.gitignore | 6 +
docs/README.md | 52 ++++
docs/blog/2025-06-30-welcome.md | 51 +++
docs/blog/authors.yml | 23 ++
docs/blog/tags.yml | 14 +
docs/docs/architecture/_category_.json | 8 +
docs/docs/architecture/overview.md | 164 ++++++++++
docs/docs/development/_category_.json | 8 +
docs/docs/development/setup.md | 291 ++++++++++++++++++
docs/docs/getting-started/_category_.json | 8 +
docs/docs/getting-started/installation.md | 198 ++++++++++++
docs/docs/intro.md | 41 +++
docs/docs/migration/_category_.json | 8 +
docs/docs/migration/from-v2.md | 219 +++++++++++++
docs/docusaurus.config.ts | 145 +++++++++
docs/package.json | 47 +++
docs/sidebars.ts | 33 ++
.../src/components/HomepageFeatures/index.tsx | 71 +++++
.../HomepageFeatures/styles.module.css | 11 +
docs/src/css/custom.css | 34 ++
docs/src/pages/index.module.css | 23 ++
docs/src/pages/index.tsx | 44 +++
docs/static/.nojekyll | 0
docs/static/img/favicon.ico | Bin 0 -> 8254 bytes
docs/static/img/logo.svg | 38 +++
docs/static/img/social-card.jpg | Bin 0 -> 152256 bytes
docs/tsconfig.json | 8 +
28 files changed, 1609 insertions(+)
create mode 100644 .github/workflows/docs.yml
create mode 100644 docs/README.md
create mode 100644 docs/blog/2025-06-30-welcome.md
create mode 100644 docs/blog/authors.yml
create mode 100644 docs/blog/tags.yml
create mode 100644 docs/docs/architecture/_category_.json
create mode 100644 docs/docs/architecture/overview.md
create mode 100644 docs/docs/development/_category_.json
create mode 100644 docs/docs/development/setup.md
create mode 100644 docs/docs/getting-started/_category_.json
create mode 100644 docs/docs/getting-started/installation.md
create mode 100644 docs/docs/intro.md
create mode 100644 docs/docs/migration/_category_.json
create mode 100644 docs/docs/migration/from-v2.md
create mode 100644 docs/docusaurus.config.ts
create mode 100644 docs/package.json
create mode 100644 docs/sidebars.ts
create mode 100644 docs/src/components/HomepageFeatures/index.tsx
create mode 100644 docs/src/components/HomepageFeatures/styles.module.css
create mode 100644 docs/src/css/custom.css
create mode 100644 docs/src/pages/index.module.css
create mode 100644 docs/src/pages/index.tsx
create mode 100644 docs/static/.nojekyll
create mode 100644 docs/static/img/favicon.ico
create mode 100644 docs/static/img/logo.svg
create mode 100644 docs/static/img/social-card.jpg
create mode 100644 docs/tsconfig.json
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 000000000..64657ae02
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,64 @@
+name: Deploy Documentation to GitHub Pages
+
+on:
+ push:
+ branches:
+ - dexter
+ paths:
+ - 'docs/**'
+ - '.github/workflows/docs.yml'
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+# Allow only one concurrent deployment
+concurrency:
+ group: "pages"
+ cancel-in-progress: false
+
+jobs:
+ build:
+ name: Build Documentation
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: ./docs
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: Setup Node.js
+ uses: actions/setup-node@v4
+ with:
+ node-version: 18
+ cache: npm
+ cache-dependency-path: ./docs/package-lock.json
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Build website
+ run: npm run build
+ env:
+ NODE_ENV: production
+
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: ./docs/build
+
+ deploy:
+ name: Deploy to GitHub Pages
+ needs: build
+ runs-on: ubuntu-latest
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ steps:
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/.gitignore b/.gitignore
index 7059c9937..910d106da 100644
--- a/.gitignore
+++ b/.gitignore
@@ -174,3 +174,9 @@ $RECYCLE.BIN/
# Claude Code
CLAUDE.local.md
+
+# Docusaurus
+/docs/.docusaurus
+/docs/.cache-loader
+/docs/build
+/docs/node_modules
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 000000000..79fc279ca
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,52 @@
+# TorrentPier Documentation
+
+This directory contains the documentation for TorrentPier, built with [Docusaurus](https://docusaurus.io/).
+
+## Local Development
+
+```bash
+npm install
+npm start
+```
+
+This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
+
+## Build
+
+```bash
+npm run build
+```
+
+This command generates static content into the `build` directory and can be served using any static contents hosting service.
+
+## Deployment
+
+The documentation is automatically deployed to GitHub Pages when changes are pushed to the main branch. The deployment is handled by GitHub Actions.
+
+## Structure
+
+- `/docs` - Main documentation content
+- `/blog` - Development blog posts
+- `/src` - Custom React components and pages
+- `/static` - Static assets like images
+
+## Contributing
+
+1. Create or edit markdown files in the `/docs` directory
+2. Add new pages to the sidebar by updating `sidebars.ts`
+3. Test locally with `npm start`
+4. Submit a pull request
+
+## Writing Documentation
+
+- Use clear, concise language
+- Include code examples where relevant
+- Add screenshots for UI features
+- Keep the audience (developers) in mind
+- Follow the existing structure and style
+
+## Resources
+
+- [Docusaurus Documentation](https://docusaurus.io/docs)
+- [Markdown Guide](https://www.markdownguide.org/)
+- [MDX Documentation](https://mdxjs.com/)
diff --git a/docs/blog/2025-06-30-welcome.md b/docs/blog/2025-06-30-welcome.md
new file mode 100644
index 000000000..ecfe4235f
--- /dev/null
+++ b/docs/blog/2025-06-30-welcome.md
@@ -0,0 +1,51 @@
+---
+slug: welcome
+title: Welcome to the TorrentPier Blog
+authors: [exileum]
+tags: [announcement, laravel, development]
+---
+
+# Welcome to the TorrentPier Development Blog
+
+We're excited to announce the complete rewrite of TorrentPier using modern web technologies. This blog will document our journey, share development updates, and provide insights into the decisions we make along the way.
+
+## Why a Rewrite?
+
+The original TorrentPier v2.x served the community well for many years, but technology has evolved significantly. We decided it was time for a complete modernization to:
+
+- Improve security with modern frameworks
+- Enhance performance and scalability
+- Provide a better user experience
+- Make development and customization easier
+- Support modern deployment practices
+
+## What's New?
+
+The new TorrentPier is built on:
+
+- **Laravel 12**: The latest version of PHP's most popular framework
+- **React 19**: For a dynamic, responsive frontend
+- **TypeScript**: Type-safe code for better reliability
+- **Inertia.js**: Seamless SPA experience without API complexity
+- **Tailwind CSS v4**: Modern, utility-first styling
+
+## What's Next?
+
+We're actively developing core features:
+
+1. User authentication and profiles
+2. Torrent upload and management
+3. Forum functionality
+4. Tracker protocol implementation
+5. Admin panel and moderation tools
+
+## Get Involved
+
+This is an open-source project, and we welcome contributions:
+
+- Check our [GitHub repository](https://github.com/torrentpier/torrentpier)
+- Read the [documentation](/docs/intro)
+- Join discussions on GitHub
+- Submit pull requests
+
+Stay tuned for more updates as we build the future of TorrentPier!
diff --git a/docs/blog/authors.yml b/docs/blog/authors.yml
new file mode 100644
index 000000000..cef26adf2
--- /dev/null
+++ b/docs/blog/authors.yml
@@ -0,0 +1,23 @@
+torrentpier:
+ name: TorrentPier Team
+ title: Core Development Team
+ url: https://github.com/torrentpier
+ image_url: https://github.com/torrentpier.png
+ socials:
+ github: torrentpier
+
+exileum:
+ name: Yury Pikhtarev
+ title: Core Development Team
+ url: https://github.com/exileum
+ image_url: https://github.com/exileum.png
+ socials:
+ github: exileum
+
+belomaxorka:
+ name: Roman Kelesidis
+ title: Core Development Team
+ url: https://github.com/belomaxorka
+ image_url: https://github.com/belomaxorka.png
+ socials:
+ github: belomaxorka
diff --git a/docs/blog/tags.yml b/docs/blog/tags.yml
new file mode 100644
index 000000000..c4bbee04d
--- /dev/null
+++ b/docs/blog/tags.yml
@@ -0,0 +1,14 @@
+announcement:
+ label: Announcement
+ permalink: /announcement
+ description: Announcement tag description
+
+laravel:
+ label: Laravel
+ permalink: /laravel
+ description: Laravel tag description
+
+development:
+ label: Development
+ permalink: /development
+ description: Development tag description
diff --git a/docs/docs/architecture/_category_.json b/docs/docs/architecture/_category_.json
new file mode 100644
index 000000000..9995b4a5f
--- /dev/null
+++ b/docs/docs/architecture/_category_.json
@@ -0,0 +1,8 @@
+{
+ "label": "Architecture",
+ "position": 3,
+ "link": {
+ "type": "generated-index",
+ "description": "Understanding TorrentPier's architecture and design decisions."
+ }
+}
\ No newline at end of file
diff --git a/docs/docs/architecture/overview.md b/docs/docs/architecture/overview.md
new file mode 100644
index 000000000..d883a88d2
--- /dev/null
+++ b/docs/docs/architecture/overview.md
@@ -0,0 +1,164 @@
+---
+sidebar_position: 1
+---
+
+# Architecture Overview
+
+:::warning Work in Progress
+This documentation is currently under development and not yet complete. Some sections may be incomplete or subject to change as the project evolves.
+:::
+
+TorrentPier follows a modern, scalable architecture built on Laravel's proven patterns and best practices.
+
+## Tech Stack
+
+### Backend
+- **Framework**: Laravel 12
+- **Language**: PHP 8.4+
+- **Authentication**: Laravel Sanctum
+- **Search**: Laravel Scout + Meilisearch
+- **Monitoring**: Laravel Telescope
+- **Testing**: Pest PHP
+
+### Frontend
+- **Library**: React 19
+- **Language**: TypeScript
+- **Routing**: Inertia.js
+- **Styling**: Tailwind CSS v4
+- **Components**: shadcn/ui
+- **Build Tool**: Vite
+
+## Application Structure
+
+```
+torrentpier/
+├── app/ # Application code
+│ ├── Http/ # Controllers, Middleware, Requests
+│ ├── Models/ # Eloquent models
+│ └── Providers/ # Service providers
+├── resources/ # Frontend resources
+│ ├── js/ # React components and pages
+│ ├── css/ # Stylesheets
+│ └── views/ # Blade templates
+├── routes/ # Application routes
+├── database/ # Migrations, factories, seeders
+├── config/ # Configuration files
+├── tests/ # Test suites
+└── legacy/ # Legacy codebase (reference)
+```
+
+## Key Design Patterns
+
+### 1. Inertia.js Integration
+
+Inertia.js bridges Laravel and React, providing:
+- Server-side routing with client-side rendering
+- Automatic data synchronization
+- No API development overhead
+- SEO-friendly SSR support
+
+### 2. Component-Based Architecture
+
+Frontend follows a component-based structure:
+- **Pages**: Full-page components in `resources/js/pages/`
+- **Layouts**: Reusable layout wrappers
+- **Components**: Shared UI components using shadcn/ui
+- **Hooks**: Custom React hooks for common functionality
+
+### 3. Laravel Best Practices
+
+- **Repository Pattern**: For complex data operations
+- **Service Classes**: Business logic separation
+- **Form Requests**: Input validation
+- **Resources**: API response transformation
+- **Policies**: Authorization logic
+
+## Data Flow
+
+1. **Request**: Browser sends request to Laravel route
+2. **Controller**: Processes request, queries data
+3. **Inertia**: Renders page component with props
+4. **React**: Renders UI with received data
+5. **Forms**: Submit via Inertia, maintaining SPA feel
+
+## Authentication Flow
+
+```mermaid
+graph LR
+ A[User] --> B[Login Page]
+ B --> C[Laravel Auth]
+ C --> D[Session Created]
+ D --> E[Sanctum Token]
+ E --> F[Authenticated Routes]
+```
+
+## BitTorrent Integration
+
+### Tracker Protocol
+- Announce endpoint: `/announce`
+- Scrape endpoint: `/scrape`
+- Peer management via Redis
+- Stats aggregation with scheduled jobs
+
+### File Handling
+- Torrent parsing and validation
+- Secure file storage
+- NFO file processing
+- Screenshot management
+
+## Performance Optimizations
+
+### Caching Strategy
+- **Redis**: Session storage, cache, queues
+- **Query Caching**: For expensive database queries
+- **Route Caching**: Production optimization
+- **View Caching**: Compiled Blade templates
+
+### Database Optimization
+- Indexed columns for tracker queries
+- Eager loading for N+1 prevention
+- Database query optimization
+- Connection pooling
+
+## Security Architecture
+
+### Application Security
+- CSRF protection
+- XSS prevention
+- SQL injection protection
+- Rate limiting
+- Input validation
+
+### Tracker Security
+- Passkey authentication
+- IP binding options
+- Anti-cheat mechanisms
+- Ratio enforcement
+
+## Scalability Considerations
+
+### Horizontal Scaling
+- Stateless application design
+- Redis for shared state
+- Queue workers for background jobs
+- CDN for static assets
+
+### Vertical Scaling
+- Database read replicas
+- Caching layers
+- Optimized queries
+- Resource monitoring
+
+## Development Workflow
+
+1. **Local Development**: Vite dev server + Laravel
+2. **Testing**: Pest for PHP, Jest for React
+3. **Building**: Vite production build
+4. **Deployment**: Zero-downtime deployments
+
+## Future Considerations
+
+- GraphQL API implementation
+- WebSocket real-time updates
+- Microservice extraction
+- Container orchestration
diff --git a/docs/docs/development/_category_.json b/docs/docs/development/_category_.json
new file mode 100644
index 000000000..23624679f
--- /dev/null
+++ b/docs/docs/development/_category_.json
@@ -0,0 +1,8 @@
+{
+ "label": "Development",
+ "position": 4,
+ "link": {
+ "type": "generated-index",
+ "description": "Development guides and best practices for TorrentPier."
+ }
+}
\ No newline at end of file
diff --git a/docs/docs/development/setup.md b/docs/docs/development/setup.md
new file mode 100644
index 000000000..7478e12b4
--- /dev/null
+++ b/docs/docs/development/setup.md
@@ -0,0 +1,291 @@
+---
+sidebar_position: 1
+---
+
+# Development Setup
+
+:::warning Work in Progress
+This documentation is currently under development and not yet complete. Some sections may be incomplete or subject to change as the project evolves.
+:::
+
+This guide will help you set up a local development environment for TorrentPier.
+
+## Prerequisites
+
+- Git
+- PHP 8.4+
+- Composer
+- Node.js 18+
+- MySQL/PostgreSQL
+- Redis (optional)
+
+## Quick Start
+
+### 1. Clone and Install
+
+```bash
+# Clone the repository
+git clone https://github.com/torrentpier/torrentpier.git
+cd dexter
+
+# Install dependencies
+composer install
+npm install
+
+# Copy environment file
+cp .env.example .env
+
+# Generate application key
+php artisan key:generate
+```
+
+### 2. Database Setup
+
+```bash
+# Create database
+mysql -u root -p -e "CREATE DATABASE torrentpier"
+
+# Run migrations
+php artisan migrate
+
+# Seed with sample data (optional)
+php artisan db:seed
+```
+
+### 3. Start Development Server
+
+```bash
+# Start Laravel and Vite development servers
+composer dev
+```
+
+This runs both the PHP server and Vite dev server concurrently.
+
+## Development Tools
+
+### Laravel Telescope
+
+Telescope is pre-installed for debugging:
+
+```bash
+# Access at http://localhost:8000/telescope
+```
+
+### Code Quality Tools
+
+```bash
+# PHP code style
+./vendor/bin/pint
+
+# JavaScript/TypeScript linting
+npm run lint
+
+# Format code
+npm run format
+
+# Type checking
+npm run types
+```
+
+### Testing
+
+```bash
+# Run all tests
+composer test
+
+# Run specific test
+php artisan test --filter=ExampleTest
+
+# Run with coverage
+php artisan test --coverage
+```
+
+## IDE Setup
+
+### VS Code
+
+Recommended extensions:
+- Laravel Extension Pack
+- Inertia.js
+- Tailwind CSS IntelliSense
+- ESLint
+- Prettier
+
+### PHPStorm
+
+- Install Laravel plugin
+- Configure code style to use Pint
+- Set up Pest integration
+
+## Working with Artisan
+
+### Always Use Artisan Commands
+
+```bash
+# Generate model with all resources
+php artisan make:model Post --all
+
+# Create controller
+php artisan make:controller PostController --resource
+
+# Create React page component manually in resources/js/pages/
+```
+
+### Useful Commands
+
+```bash
+# Clear all caches
+php artisan optimize:clear
+
+# Show routes
+php artisan route:list
+
+# Show model details
+php artisan model:show User
+
+# Interactive tinker shell
+php artisan tinker
+```
+
+## Frontend Development
+
+### Creating Pages
+
+1. Create page component in `resources/js/pages/`
+2. Define route in `routes/web.php`
+3. Return Inertia response from controller
+
+Example:
+
+```php
+// routes/web.php
+Route::get('/posts', [PostController::class, 'index'])->name('posts.index');
+
+// app/Http/Controllers/PostController.php
+public function index()
+{
+ return Inertia::render('Posts/Index', [
+ 'posts' => Post::paginate()
+ ]);
+}
+```
+
+```tsx
+// resources/js/pages/Posts/Index.tsx
+import { Head } from '@inertiajs/react';
+
+export default function Index({ posts }) {
+ return (
+ <>
+
+
+ {/* Your component */}
+
+ >
+ );
+}
+```
+
+### Using shadcn/ui Components
+
+```tsx
+import { Button } from '@/components/ui/button';
+import { Card } from '@/components/ui/card';
+
+export default function MyComponent() {
+ return (
+
+
+
+ );
+}
+```
+
+## Database Development
+
+### Migrations
+
+```bash
+# Create migration
+php artisan make:migration create_posts_table
+
+# Run migrations
+php artisan migrate
+
+# Rollback
+php artisan migrate:rollback
+
+# Fresh migration with seed
+php artisan migrate:fresh --seed
+```
+
+### Working with Models
+
+```php
+// Use artisan to generate models
+php artisan make:model Post -mfsc
+
+// This creates:
+// - Model: app/Models/Post.php
+// - Migration: database/migrations/xxx_create_posts_table.php
+// - Factory: database/factories/PostFactory.php
+// - Seeder: database/seeders/PostSeeder.php
+// - Controller: app/Http/Controllers/PostController.php
+```
+
+## Git Workflow
+
+### Branching Strategy
+
+```bash
+# Create feature branch
+git checkout -b feature/user-profile
+
+# Create bugfix branch
+git checkout -b bugfix/login-issue
+
+# Push branch
+git push -u origin feature/user-profile
+```
+
+### Commit Messages
+
+Follow conventional commits:
+- `feat:` New feature
+- `fix:` Bug fix
+- `docs:` Documentation
+- `style:` Code style
+- `refactor:` Code refactoring
+- `test:` Tests
+- `chore:` Maintenance
+
+## Troubleshooting
+
+### Common Issues
+
+1. **npm install fails**
+ ```bash
+ rm -rf node_modules package-lock.json
+ npm install
+ ```
+
+2. **Composer memory limit**
+ ```bash
+ COMPOSER_MEMORY_LIMIT=-1 composer install
+ ```
+
+3. **Permission errors**
+ ```bash
+ chmod -R 775 storage bootstrap/cache
+ ```
+
+4. **Cache issues**
+ ```bash
+ php artisan optimize:clear
+ ```
+
+## Next Steps
+
+- Review [Coding Standards](/docs/development/coding-standards)
+- Learn about [Testing](/docs/development/testing)
+- Understand [API Development](/docs/api/overview)
diff --git a/docs/docs/getting-started/_category_.json b/docs/docs/getting-started/_category_.json
new file mode 100644
index 000000000..134469394
--- /dev/null
+++ b/docs/docs/getting-started/_category_.json
@@ -0,0 +1,8 @@
+{
+ "label": "Getting Started",
+ "position": 2,
+ "link": {
+ "type": "generated-index",
+ "description": "Everything you need to get up and running with TorrentPier."
+ }
+}
\ No newline at end of file
diff --git a/docs/docs/getting-started/installation.md b/docs/docs/getting-started/installation.md
new file mode 100644
index 000000000..cb7903e8b
--- /dev/null
+++ b/docs/docs/getting-started/installation.md
@@ -0,0 +1,198 @@
+---
+sidebar_position: 1
+---
+
+# Installation
+
+:::warning Work in Progress
+This documentation is currently under development and not yet complete. Some sections may be incomplete or subject to change as the project evolves.
+:::
+
+This guide will help you install and set up TorrentPier on your server.
+
+## Requirements
+
+Before installing TorrentPier, ensure your server meets these requirements:
+
+- **PHP** 8.4 or higher
+- **MySQL** 8.0+ / PostgreSQL 15+ / SQLite 3.8.8+ / SQL Server 2017+
+- **Node.js** 18.0 or higher
+- **Composer** 2.0 or higher
+- **Redis** (optional, for caching and queues)
+
+### PHP Extensions
+
+Ensure the following PHP extensions are installed:
+- BCMath
+- Ctype
+- cURL
+- DOM
+- Fileinfo
+- JSON
+- Mbstring
+- OpenSSL
+- PCRE
+- PDO
+- Tokenizer
+- XML
+
+## Installation Steps
+
+### 1. Clone the Repository
+
+```bash
+git clone https://github.com/torrentpier/torrentpier.git torrentpier
+cd torrentpier
+```
+
+### 2. Install Dependencies
+
+Install PHP dependencies:
+
+```bash
+composer install
+```
+
+Install JavaScript dependencies:
+
+```bash
+npm install
+```
+
+### 3. Environment Configuration
+
+Copy the example environment file:
+
+```bash
+cp .env.example .env
+```
+
+Generate application key:
+
+```bash
+php artisan key:generate
+```
+
+### 4. Configure Database
+
+Edit your `.env` file with your database credentials:
+
+```env
+DB_CONNECTION=mysql
+DB_HOST=127.0.0.1
+DB_PORT=3306
+DB_DATABASE=torrentpier
+DB_USERNAME=your_username
+DB_PASSWORD=your_password
+```
+
+### 5. Run Migrations
+
+Create the database tables:
+
+```bash
+php artisan migrate
+```
+
+Optionally, seed the database with sample data:
+
+```bash
+php artisan db:seed
+```
+
+### 6. Build Frontend Assets
+
+For development:
+
+```bash
+npm run dev
+```
+
+For production:
+
+```bash
+npm run build
+```
+
+### 7. Configure Web Server
+
+#### Apache
+
+Ensure `mod_rewrite` is enabled and point your document root to the `public` directory.
+
+#### Nginx
+
+Example configuration:
+
+```nginx
+server {
+ listen 80;
+ server_name torrentpier.local;
+ root /path/to/torrentpier/public;
+
+ index index.php;
+
+ location / {
+ try_files $uri $uri/ /index.php?$query_string;
+ }
+
+ location ~ \.php$ {
+ fastcgi_pass unix:/var/run/php/php8.4-fpm.sock;
+ fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
+ include fastcgi_params;
+ }
+}
+```
+
+## Post-Installation
+
+### Set Up Cron Jobs
+
+Add the Laravel scheduler to your crontab:
+
+```bash
+* * * * * cd /path/to/torrentpier && php artisan schedule:run >> /dev/null 2>&1
+```
+
+### Configure Queue Workers
+
+If using queues, set up a supervisor configuration:
+
+```ini
+[program:torrentpier-worker]
+process_name=%(program_name)s_%(process_num)02d
+command=php /path/to/torrentpier/artisan queue:work --sleep=3 --tries=3 --max-time=3600
+autostart=true
+autorestart=true
+stopasgroup=true
+killasgroup=true
+user=www-data
+numprocs=8
+redirect_stderr=true
+stdout_logfile=/path/to/torrentpier/storage/logs/worker.log
+```
+
+## Troubleshooting
+
+### Permission Issues
+
+Ensure proper permissions for storage and cache directories:
+
+```bash
+chmod -R 775 storage bootstrap/cache
+chown -R www-data:www-data storage bootstrap/cache
+```
+
+### Clear Caches
+
+If you encounter issues, try clearing all caches:
+
+```bash
+php artisan optimize:clear
+```
+
+## Next Steps
+
+- Configure [Application Settings](/docs/getting-started/configuration)
+- Set up [Email Configuration](/docs/getting-started/email)
+- Review [Security Best Practices](/docs/getting-started/security)
diff --git a/docs/docs/intro.md b/docs/docs/intro.md
new file mode 100644
index 000000000..a1de83c5d
--- /dev/null
+++ b/docs/docs/intro.md
@@ -0,0 +1,41 @@
+---
+sidebar_position: 1
+---
+
+# Welcome to TorrentPier
+
+:::warning Work in Progress
+This documentation is currently under development and not yet complete. Some sections may be incomplete or subject to change as the project evolves.
+:::
+
+TorrentPier is a modern, Laravel-based BitTorrent tracker and open-source software that allows you to run your own private or public torrent community. This is a complete rewrite of the original TorrentPier v2.x, built from the ground up using modern web technologies and best practices. This documentation will guide you through the architecture, features, and development process of the new TorrentPier.
+
+## Key Features
+
+- **Modern Tech Stack**: Built with Laravel 12, React 19, and TypeScript
+- **Real-time Updates**: Powered by Inertia.js for seamless SPA-like experience
+- **Beautiful UI**: Using Tailwind CSS v4 and shadcn/ui components
+- **Enhanced Security**: Laravel Sanctum for authentication
+- **Developer Tools**: Laravel Telescope for debugging and monitoring
+- **Full-text Search**: Laravel Scout with Meilisearch integration
+- **Extensible**: Clean architecture designed for customization
+
+## Project Status
+
+This is an active rewrite of TorrentPier v2.x. The legacy codebase is maintained in the `/legacy` directory for reference while we build the new system using Laravel standards and modern development practices.
+
+## Getting Started
+
+To get started with TorrentPier development:
+
+1. Check out the [Installation Guide](/docs/getting-started/installation)
+2. Review the [Architecture Overview](/docs/architecture/overview)
+3. Explore the [Development Setup](/docs/development/setup)
+
+## Contributing
+
+We welcome contributions! Please see our [Contributing Guide](/docs/contributing) for details on how to get involved.
+
+## License
+
+TorrentPier is open-source software licensed under the MIT license.
diff --git a/docs/docs/migration/_category_.json b/docs/docs/migration/_category_.json
new file mode 100644
index 000000000..02de71f40
--- /dev/null
+++ b/docs/docs/migration/_category_.json
@@ -0,0 +1,8 @@
+{
+ "label": "Migration Guide",
+ "position": 5,
+ "link": {
+ "type": "generated-index",
+ "description": "Guides for migrating from TorrentPier v2.x to the new Laravel version."
+ }
+}
\ No newline at end of file
diff --git a/docs/docs/migration/from-v2.md b/docs/docs/migration/from-v2.md
new file mode 100644
index 000000000..87fcbe3f5
--- /dev/null
+++ b/docs/docs/migration/from-v2.md
@@ -0,0 +1,219 @@
+---
+sidebar_position: 1
+---
+
+# Migrating from TorrentPier v2.x
+
+:::warning Work in Progress
+This documentation is currently under development and not yet complete. Some sections may be incomplete or subject to change as the project evolves.
+:::
+
+This guide helps you migrate from the legacy TorrentPier v2.x to the new Laravel-based version.
+
+## Overview
+
+The new TorrentPier is a complete rewrite with:
+- Modern architecture
+- Improved performance
+- Better security
+- Enhanced user experience
+
+## Pre-Migration Checklist
+
+Before starting migration:
+
+1. **Backup Everything**
+ - Full database backup
+ - All uploaded files (torrents, images)
+ - Configuration files
+ - Custom modifications
+
+2. **Review Requirements**
+ - PHP 8.4+ (vs PHP 7.0+ in v2.x)
+ - MySQL 8.0+ recommended
+ - More server resources needed
+
+3. **Plan Downtime**
+ - Migration can take hours for large sites
+ - Inform your users
+ - Choose low-traffic period
+
+## Migration Steps
+
+### Step 1: Prepare New Installation
+
+```bash
+# Install new TorrentPier
+git clone https://github.com/torrentpier/torrentpier.git torrentpier
+cd torrentpier
+composer install
+npm install && npm run build
+```
+
+### Step 2: Configure Environment
+
+```bash
+cp .env.example .env
+php artisan key:generate
+```
+
+Edit `.env` with your settings:
+```env
+DB_DATABASE=torrentpier
+LEGACY_DB_DATABASE=torrentpier_old
+```
+
+### Step 3: Run Migration Command
+
+```bash
+# This command will guide you through the migration
+php artisan torrentpier:migrate
+```
+
+The migration tool will:
+- Import users and profiles
+- Convert forum structure
+- Migrate topics and posts
+- Import torrents and peers
+- Transfer user statistics
+
+### Step 4: Migrate Files
+
+```bash
+# Copy torrent files
+cp -r /path/to/old/data/torrent_files /path/to/new/storage/app/torrents
+
+# Copy user avatars
+cp -r /path/to/old/data/avatars /path/to/new/storage/app/avatars
+
+# Copy attachments
+cp -r /path/to/old/data/attachments /path/to/new/storage/app/attachments
+```
+
+### Step 5: Update Configuration
+
+Map old settings to new:
+
+| Old Setting | New Setting | Notes |
+|------------|-------------|-------|
+| `$bb_cfg['bt_announce_url']` | `TRACKER_ANNOUNCE_URL` | In .env file |
+| `$bb_cfg['torrent_pass']` | Auto-generated | More secure |
+| `$bb_cfg['ratio_enabled']` | `TRACKER_RATIO_ENABLED` | Boolean |
+
+### Step 6: Test Migration
+
+```bash
+# Run in staging environment first
+php artisan migrate:status
+php artisan torrentpier:verify
+```
+
+## Data Mapping
+
+### Users Table
+
+| v2.x Column | New Column | Changes |
+|-------------|------------|---------|
+| `user_id` | `id` | Same data |
+| `username` | `username` | Validated |
+| `user_password` | `password` | Re-hashed |
+| `user_email` | `email` | Verified |
+
+### Torrents Table
+
+| v2.x Column | New Column | Changes |
+|-------------|------------|---------|
+| `topic_id` | `id` | New IDs |
+| `info_hash` | `info_hash` | Same |
+| `size` | `size` | Bigint |
+
+## Post-Migration
+
+### 1. Verify Data Integrity
+
+```bash
+# Check user counts
+php artisan torrentpier:check users
+
+# Check torrent counts
+php artisan torrentpier:check torrents
+
+# Verify statistics
+php artisan torrentpier:check stats
+```
+
+### 2. Update DNS
+
+Point your domain to the new installation.
+
+### 3. Monitor Performance
+
+- Watch error logs
+- Monitor tracker announces
+- Check user reports
+
+### 4. Clean Up
+
+After successful migration:
+```bash
+# Remove migration flags
+php artisan cache:clear
+
+# Optimize
+php artisan optimize
+```
+
+## Rollback Plan
+
+If issues occur:
+
+1. Stop new installation
+2. Restore DNS to old server
+3. Investigate issues
+4. Fix and retry
+
+Keep old installation running until confident.
+
+## Common Issues
+
+### Password Reset Required
+
+Users must reset passwords due to improved hashing.
+
+### Missing Features
+
+Some v2.x features may be pending:
+- Check roadmap
+- Request features
+- Contribute code
+
+### Performance Differences
+
+New version may need tuning:
+- Configure Redis
+- Optimize database
+- Use queue workers
+
+## Custom Modifications
+
+If you had custom mods in v2.x:
+
+1. Document modifications
+2. Evaluate if still needed
+3. Reimplement using Laravel patterns
+4. Submit as pull requests
+
+## Getting Help
+
+- GitHub Issues
+- Community Forum
+- Documentation
+- Discord Channel
+
+## Next Steps
+
+After successful migration:
+- Configure new features
+- Train moderators
+- Update user guides
+- Monitor feedback
diff --git a/docs/docusaurus.config.ts b/docs/docusaurus.config.ts
new file mode 100644
index 000000000..b97067b6d
--- /dev/null
+++ b/docs/docusaurus.config.ts
@@ -0,0 +1,145 @@
+import {themes as prismThemes} from 'prism-react-renderer';
+import type {Config} from '@docusaurus/types';
+import type * as Preset from '@docusaurus/preset-classic';
+
+// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...)
+
+const config: Config = {
+ title: 'TorrentPier Documentation',
+ tagline: 'Modern Laravel-based BitTorrent tracker',
+ favicon: 'img/favicon.ico',
+
+ // Future flags, see https://docusaurus.io/docs/api/docusaurus-config#future
+ future: {
+ v4: true, // Improve compatibility with the upcoming Docusaurus v4
+ },
+
+ // Set the production url of your site here
+ url: 'https://docs.torrentpier.com',
+ // Set the // pathname under which your site is served
+ // For GitHub pages deployment, it is often '//'
+ baseUrl: '/',
+
+ // GitHub pages deployment config.
+ // If you aren't using GitHub pages, you don't need these.
+ organizationName: 'torrentpier', // Usually your GitHub org/user name.
+ projectName: 'torrentpier.github.io', // Usually your repo name.
+ trailingSlash: false,
+
+ onBrokenLinks: 'throw',
+ onBrokenMarkdownLinks: 'warn',
+
+ // Even if you don't use internationalization, you can use this field to set
+ // useful metadata like html lang. For example, if your site is Chinese, you
+ // may want to replace "en" with "zh-Hans".
+ i18n: {
+ defaultLocale: 'en',
+ locales: ['en'],
+ },
+
+ presets: [
+ [
+ 'classic',
+ {
+ docs: {
+ sidebarPath: './sidebars.ts',
+ // Please change this to your repo.
+ // Remove this to remove the "edit this page" links.
+ editUrl:
+ 'https://github.com/torrentpier/torrentpier/tree/dexter/docs/',
+ },
+ blog: {
+ showReadingTime: true,
+ feedOptions: {
+ type: ['rss', 'atom'],
+ xslt: true,
+ },
+ // Please change this to your repo.
+ // Remove this to remove the "edit this page" links.
+ editUrl:
+ 'https://github.com/torrentpier/torrentpier/tree/dexter/docs/',
+ // Useful options to enforce blogging best practices
+ onInlineTags: 'warn',
+ onInlineAuthors: 'warn',
+ onUntruncatedBlogPosts: 'warn',
+ },
+ theme: {
+ customCss: './src/css/custom.css',
+ },
+ } satisfies Preset.Options,
+ ],
+ ],
+
+ themeConfig: {
+ // Replace with your project's social card
+ image: 'img/social-card.jpg',
+ navbar: {
+ title: 'TorrentPier',
+ logo: {
+ alt: 'TorrentPier Logo',
+ src: 'img/logo.svg',
+ },
+ items: [
+ {to: '/blog/welcome', label: 'Blog', position: 'left'},
+ {
+ type: 'docSidebar',
+ sidebarId: 'tutorialSidebar',
+ position: 'left',
+ label: 'Documentation',
+ },
+ {
+ href: 'https://github.com/torrentpier/torrentpier',
+ label: 'GitHub',
+ position: 'right',
+ },
+ ],
+ },
+ footer: {
+ style: 'dark',
+ links: [
+ {
+ title: 'Docs',
+ items: [
+ {
+ label: 'Getting Started',
+ to: '/docs/intro',
+ },
+ ],
+ },
+ {
+ title: 'Community',
+ items: [
+ {
+ label: 'Discussions',
+ href: 'https://github.com/torrentpier/torrentpier/discussions',
+ },
+ {
+ label: 'Issues',
+ href: 'https://github.com/torrentpier/torrentpier/issues',
+ },
+ ],
+ },
+ {
+ title: 'More',
+ items: [
+ {
+ label: 'Blog',
+ to: '/blog',
+ },
+ {
+ label: 'GitHub',
+ href: 'https://github.com/torrentpier/torrentpier',
+ },
+ ],
+ },
+ ],
+ copyright: `Copyright © ${new Date().getFullYear()} TorrentPier. Built with Docusaurus.`,
+ },
+ prism: {
+ theme: prismThemes.github,
+ darkTheme: prismThemes.dracula,
+ },
+ } satisfies Preset.ThemeConfig,
+};
+
+export default config;
diff --git a/docs/package.json b/docs/package.json
new file mode 100644
index 000000000..27c6942cc
--- /dev/null
+++ b/docs/package.json
@@ -0,0 +1,47 @@
+{
+ "name": "docs",
+ "version": "0.0.0",
+ "private": true,
+ "scripts": {
+ "docusaurus": "docusaurus",
+ "start": "docusaurus start",
+ "build": "docusaurus build",
+ "swizzle": "docusaurus swizzle",
+ "deploy": "docusaurus deploy",
+ "clear": "docusaurus clear",
+ "serve": "docusaurus serve",
+ "write-translations": "docusaurus write-translations",
+ "write-heading-ids": "docusaurus write-heading-ids",
+ "typecheck": "tsc"
+ },
+ "dependencies": {
+ "@docusaurus/core": "3.8.1",
+ "@docusaurus/preset-classic": "3.8.1",
+ "@mdx-js/react": "^3.0.0",
+ "clsx": "^2.0.0",
+ "prism-react-renderer": "^2.3.0",
+ "react": "^19.0.0",
+ "react-dom": "^19.0.0"
+ },
+ "devDependencies": {
+ "@docusaurus/module-type-aliases": "3.8.1",
+ "@docusaurus/tsconfig": "3.8.1",
+ "@docusaurus/types": "3.8.1",
+ "typescript": "~5.6.2"
+ },
+ "browserslist": {
+ "production": [
+ ">0.5%",
+ "not dead",
+ "not op_mini all"
+ ],
+ "development": [
+ "last 3 chrome version",
+ "last 3 firefox version",
+ "last 5 safari version"
+ ]
+ },
+ "engines": {
+ "node": ">=18.0"
+ }
+}
diff --git a/docs/sidebars.ts b/docs/sidebars.ts
new file mode 100644
index 000000000..289713975
--- /dev/null
+++ b/docs/sidebars.ts
@@ -0,0 +1,33 @@
+import type {SidebarsConfig} from '@docusaurus/plugin-content-docs';
+
+// This runs in Node.js - Don't use client-side code here (browser APIs, JSX...)
+
+/**
+ * Creating a sidebar enables you to:
+ - create an ordered group of docs
+ - render a sidebar for each doc of that group
+ - provide next/previous navigation
+
+ The sidebars can be generated from the filesystem, or explicitly defined here.
+
+ Create as many sidebars as you want.
+ */
+const sidebars: SidebarsConfig = {
+ // By default, Docusaurus generates a sidebar from the docs folder structure
+ tutorialSidebar: [{type: 'autogenerated', dirName: '.'}],
+
+ // But you can create a sidebar manually
+ /*
+ tutorialSidebar: [
+ 'intro',
+ 'hello',
+ {
+ type: 'category',
+ label: 'Tutorial',
+ items: ['tutorial-basics/create-a-document'],
+ },
+ ],
+ */
+};
+
+export default sidebars;
diff --git a/docs/src/components/HomepageFeatures/index.tsx b/docs/src/components/HomepageFeatures/index.tsx
new file mode 100644
index 000000000..c6b68eb8b
--- /dev/null
+++ b/docs/src/components/HomepageFeatures/index.tsx
@@ -0,0 +1,71 @@
+import type {ReactNode} from 'react';
+import clsx from 'clsx';
+import Heading from '@theme/Heading';
+import styles from './styles.module.css';
+
+type FeatureItem = {
+ title: string;
+ Svg: React.ComponentType>;
+ description: ReactNode;
+};
+
+const FeatureList: FeatureItem[] = [
+ {
+ title: 'Modern Architecture',
+ Svg: require('@site/static/img/logo.svg').default,
+ description: (
+ <>
+ Built with Laravel 12 and React 19, TorrentPier leverages the latest
+ web technologies for performance, security, and developer experience.
+ >
+ ),
+ },
+ {
+ title: 'Feature Rich',
+ Svg: require('@site/static/img/logo.svg').default,
+ description: (
+ <>
+ Complete BitTorrent tracker with user management, forums, statistics,
+ anti-cheat protection, and extensive moderation tools out of the box.
+ >
+ ),
+ },
+ {
+ title: 'Easy to Customize',
+ Svg: require('@site/static/img/logo.svg').default,
+ description: (
+ <>
+ Clean codebase following Laravel best practices. Extend functionality
+ with plugins, themes, and custom modifications easily.
+ >
+ ),
+ },
+];
+
+function Feature({title, Svg, description}: FeatureItem) {
+ return (
+
+
+
+
+
+
{title}
+
{description}
+
+
+ );
+}
+
+export default function HomepageFeatures(): ReactNode {
+ return (
+
+
+
+ {FeatureList.map((props, idx) => (
+
+ ))}
+
+
+
+ );
+}
diff --git a/docs/src/components/HomepageFeatures/styles.module.css b/docs/src/components/HomepageFeatures/styles.module.css
new file mode 100644
index 000000000..b248eb2e5
--- /dev/null
+++ b/docs/src/components/HomepageFeatures/styles.module.css
@@ -0,0 +1,11 @@
+.features {
+ display: flex;
+ align-items: center;
+ padding: 2rem 0;
+ width: 100%;
+}
+
+.featureSvg {
+ height: 200px;
+ width: 200px;
+}
diff --git a/docs/src/css/custom.css b/docs/src/css/custom.css
new file mode 100644
index 000000000..ae1261a1a
--- /dev/null
+++ b/docs/src/css/custom.css
@@ -0,0 +1,34 @@
+/**
+ * Any CSS included here will be global. The classic template
+ * bundles Infima by default. Infima is a CSS framework designed to
+ * work well for content-centric websites.
+ */
+
+/* You can override the default Infima variables here. */
+:root {
+ --ifm-color-primary: #2563eb;
+ --ifm-color-primary-dark: #1d4ed8;
+ --ifm-color-primary-darker: #1e40af;
+ --ifm-color-primary-darkest: #1e3a8a;
+ --ifm-color-primary-light: #3b82f6;
+ --ifm-color-primary-lighter: #60a5fa;
+ --ifm-color-primary-lightest: #93bbfc;
+ --ifm-code-font-size: 95%;
+ --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1);
+}
+
+/* For readability concerns, you should choose a lighter palette in dark mode. */
+[data-theme='dark'] {
+ --ifm-color-primary: #60a5fa;
+ --ifm-color-primary-dark: #3b82f6;
+ --ifm-color-primary-darker: #2563eb;
+ --ifm-color-primary-darkest: #1d4ed8;
+ --ifm-color-primary-light: #93bbfc;
+ --ifm-color-primary-lighter: #a5c8fd;
+ --ifm-color-primary-lightest: #dbeafe;
+ --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3);
+}
+
+.navbar__logo {
+ height: 2.5rem;
+}
diff --git a/docs/src/pages/index.module.css b/docs/src/pages/index.module.css
new file mode 100644
index 000000000..9f71a5da7
--- /dev/null
+++ b/docs/src/pages/index.module.css
@@ -0,0 +1,23 @@
+/**
+ * CSS files with the .module.css suffix will be treated as CSS modules
+ * and scoped locally.
+ */
+
+.heroBanner {
+ padding: 4rem 0;
+ text-align: center;
+ position: relative;
+ overflow: hidden;
+}
+
+@media screen and (max-width: 996px) {
+ .heroBanner {
+ padding: 2rem;
+ }
+}
+
+.buttons {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
diff --git a/docs/src/pages/index.tsx b/docs/src/pages/index.tsx
new file mode 100644
index 000000000..467c94b6e
--- /dev/null
+++ b/docs/src/pages/index.tsx
@@ -0,0 +1,44 @@
+import type {ReactNode} from 'react';
+import clsx from 'clsx';
+import Link from '@docusaurus/Link';
+import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
+import Layout from '@theme/Layout';
+import HomepageFeatures from '@site/src/components/HomepageFeatures';
+import Heading from '@theme/Heading';
+
+import styles from './index.module.css';
+
+function HomepageHeader() {
+ const {siteConfig} = useDocusaurusContext();
+ return (
+
+
+
+ {siteConfig.title}
+
+
{siteConfig.tagline}
+
+
+ Get Started →
+
+
+
+
+ );
+}
+
+export default function Home(): ReactNode {
+ const {siteConfig} = useDocusaurusContext();
+ return (
+
+
+
+
+
+
+ );
+}
diff --git a/docs/static/.nojekyll b/docs/static/.nojekyll
new file mode 100644
index 000000000..e69de29bb
diff --git a/docs/static/img/favicon.ico b/docs/static/img/favicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..25f33e05b2f1be97cb0cedade0069d98659df95f
GIT binary patch
literal 8254
zcmeH~+f$Qw8prXf|AE8ZI^KvEozCoRN6-Z#YB(Ft$AkbPAOZp!6r(kQl(o3FBemPv
zo$l7D({9z)?mBj~we7m=LPha_c!1ahav}$a1OsAkzWY4y$(O)Pr&GIE36tc_WQO18
z{XF02`TY_Tvx5Fst%{+?s+c%>UrASS!l#%R4ZYL1^h%Fa!t2X=S>fr(j+@%8jRP<7
ze|&fjKSUAK2%X4u!B5%!zXyM3l~?XQjC?a5p1>MXFjExEzTgF1N4TjA@-0x=-4
zCoLFg)mmp-Hm!cy9G?I7e@Z!`V{|S9c-Yo%!%s@*px~!?!OBerDL6hN)I9rgv?2
z48$j`{iPhPcPkRyCo6iLZ|gnIKbFDyRteM$?nAi}19?y}_;+b>eSNa$(rfFEo%+qI
z2|t&^nx6j3SXQpnR#y~sy;A}A2?Jd3=;1uZ45cE&5!pj7JVGtV1J!~(_*znNZtZU|
z5U)Xhd{S^=U6Pak=TC72&g@v@KV5(3u`VBDx;%{Lj+lmLN*|@LG
z!o4l@+?;{oP3d@;p9%L~9UM(ra5iLMC~*sJ{(ci~Y)HZ2`i=NLK|?G_xRIE2<=XEy
ztcm1!`gzOR;Q6M$z?p`zz$f)^9X7&o*Z_N1IUMG4OmviCyuB3mJ;iujlP_@GS2!{;
zv_*@7)D+xJNyi;c8g3`2Vkn6i5;x-paSU$QNcGU*`}kz$80(Ku?345H^zxpS(-)dU
z(_b`U>a(372Kb4=f4UC7Q`_PF>o!dOr5c|1E8#h5#Q6SFJWMAaDi^m>(l9`4u?vA=
zBQa=FaVuFXxgZY71#_^A{&k6=|E^!Z(tptu`{c_O1TXA@!tm)1c>lB=lgDY@W0i0p
zHNw?XK~Do52g@*;l|wbjAr7iX8r6eb+?8rEyeUIqxJwK#Trh|1B1LqOkc`3CHL=3_
zms=53Go0NCM@1>d3yNXSFM=(v5VqU`*vgCGI8=_Y>^vbCqs$=XVt8{VhKXTB$OTxaKH#m;=a8&58^i46a2#`I^6a2A)sQB@WE;vg4~P8CiMn*%Jpyw
z97|oux%h!{!5mhe8B`CR7qSZ>pHiPL%EdK>V(nkaKCqDQPWx7dZfp7u=IyZx3z
z;r^dJIE-iaESMt?b3+FZ9@vj3b=&Dl9zNJ5^u<(HJp$XS;jf{ZR2ebJ`ING$^r~DB
z$;J3GE^Jl#a7lZ&y#B(YE_H>(&$&fG~_DD0T71MujLZGJ>
z{x@piGt>UGgXRVGs>rcSE_jCX{4OZOcv}&jABu>f0Cv8AyCwFy^#~LO@(}KBM)=Y`
zA(L`nESgc5XuqI28RS|0Ik9}W1OAh>@b%H2WvNo;mNGjj7wp2Wr?rn!W{=W2>P`Cm
zR$(k2_pbcW)*TWVIt35&!-p_`n>^g4T3nZU^FMoq`4IZ{g@@op+B2EqJnh}*Xz!+d
z)BiE;+aD3jhs1KS8m?wN9D17JWhHPlmcn(M@5
zJu)VEpgaf+avo%cYmp4JXDwl%^Mi^(I6wSZJU`G`60Q^aG3W8JKF`~RCFj!xTi2TB
z)~>V6ut0fWhB?^-&!~Q$Q8cF`^1!taJv2%ln4wz|
zF<4K$vhb+WNesbx%B0X2Tnp8l6d1ly*Ft2NIxjPDE$AHeQEkw7s>W$O(e#t&&q$8>
zhn)!v_bt7|;88p%wctIg9W#saAZC&o0_Pe%l!sp5$8|sZ{2j^heAE(03{EAJN-b#5
z`WNrr5gz{0?3}vL$Ui|}>SJNpvYHsI;h_V;@b-9=I
+
\ No newline at end of file
diff --git a/docs/static/img/social-card.jpg b/docs/static/img/social-card.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..5370429352dd734d10aa67df711ee6f25ce9a7bc
GIT binary patch
literal 152256
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