feat: redesign Awesome Remnawave page

This commit is contained in:
kastov
2025-10-10 05:50:01 +03:00
parent 86766a0b53
commit 1d1e5870ae
30 changed files with 2724 additions and 733 deletions

4
.gitignore vendored
View File

@@ -158,4 +158,6 @@ yarn-debug.log*
yarn-error.log*
.wip/
.wip/
samples/

View File

@@ -1,731 +0,0 @@
---
sidebar_position: 7
title: ❤️ Awesome Remnawave
---
# ❤️ Awesome Remnawave
### Xray Checker
Xray Checker is a tool for monitoring proxy server availability with support for VLESS, VMess, Trojan, and Shadowsocks protocols. It automatically tests connections through Xray Core and provides metrics for Prometheus, as well as API endpoints for integration with various monitoring systems.
Author: [kutovoys](https://github.com/kutovoys)
<div style={{ display: 'flex', justifyContent: 'center', gap: '1rem' }}>
<Button label="Github repository" link="https://github.com/kutovoys/xray-checker" variant="secondary" size="md" outline />
<Button label="Documentation" link="https://xray-checker.kutovoy.dev/" variant="secondary" size="md" outline />
</div>
<br />
<div style={{ display: 'flex', justifyContent: 'center' }}>
<img src="/awesome/xray-checker.webp" alt="Xray Checker" width="600" />
</div>
---
### Geo File Viewer
A utility for viewing the contents of geoip and geofile (.dat) files in the v2fly format.
<div style={{ display: 'flex', justifyContent: 'center', gap: '1rem' }}>
<Button label="Github repository" link="https://jomertix.github.io/geofileviewer" variant="secondary" size="md" outline />
</div>
<br />
<div style={{ display: 'flex', justifyContent: 'center' }}>
<img src="/awesome/geofileviewer.webp" alt="GeoFileViewer" width="600" />
</div>
---
### Remnawave Management Scripts by DigneZzZ
Comprehensive bash scripts for **Remnawave Panel**, **Remnawave Node**, and **Reality Selfsteal** with full automation support. Features Docker integration, intelligent backup/restore system with version checking, advanced monitoring, and complete lifecycle management.
📦 **Key Features:**
- 🚀 **One-line installation** for Panel, Node, and Selfsteal configurations
- 🎛️ **Interactive menus** with real-time status monitoring and guided operations
- 💾 **Smart backup system** with version compatibility checking and safety rollbacks
- 🔄 **Complete lifecycle management** - install, update, backup, restore, uninstall
- 🎯 **Reality masking** with 11 AI-generated website templates
📦 Full info, updates, and examples: [**/remnawave-scripts**](https://github.com/DigneZzZ/remnawave-scripts)
Author: [DigneZzZ](https://github.com/DigneZzZ)
Project: [GIG.ovh](https://gig.ovh)
---
<details>
<summary>🚀 Quick Install Commands</summary>
**Remnawave Panel (v3.5.5+):**
```bash
bash <(curl -Ls https://github.com/DigneZzZ/remnawave-scripts/raw/main/remnawave.sh) @ install
```
**Remnawave Node (v3.1.2+):**
```bash
bash <(curl -Ls https://github.com/DigneZzZ/remnawave-scripts/raw/main/remnanode.sh) @ install
```
**Reality Selfsteal (v2.1.3+):**
```bash
bash <(curl -Ls https://github.com/DigneZzZ/remnawave-scripts/raw/main/selfsteal.sh) @ install
```
**Options:**
- Add `--dev` for development version
- Add `--name customname` for custom directory (default: `/opt/remnawave`, `/opt/remnanode`)
**For existing installations:**
Use `install-script` to add CLI wrapper only:
```bash
bash <(curl -Ls https://github.com/DigneZzZ/remnawave-scripts/raw/main/remnawave.sh) @ install-script
```
```bash
bash <(curl -Ls https://github.com/DigneZzZ/remnawave-scripts/raw/main/remnanode.sh) @ install-script
```
</details>
<details>
<summary>⚙️ Available CLI Commands</summary>
**Installation & Management:**
- `install`, `update`, `uninstall`
- `install-script`, `uninstall-script`
**Service Control:**
- `up`, `down`, `restart`, `status`, `logs`
**Node-specific Commands:**
- `core-update` - Manual Update/Install Xray-core to latest version
- `xray-log-out`, `xray-log-err` - View Xray logs
- `setup-logs` - Configure log rotation
**Configuration:**
- `edit`, `edit-env`, `console` (Panel only)
**Interactive Menus:**
- Run `remnawave`, `remnanode`, or `selfsteal` without arguments for interactive menu
- Real-time status monitoring and resource usage
- Step-by-step guided operations
**Backup & Restore (Panel):**
- `backup` - Create manual backup
- `schedule` - Configure automated backups
- `restore` - Restore from backup archive
**Reality Selfsteal:**
- Choose from 11 AI-generated website templates
- Automatic SSL certificate management by Caddy
- DNS validation before start
Run `remnawave help`, `remnanode help`, or `selfsteal help` for detailed usage.
</details>
<details>
<summary>💾 Intelligent Backup & Restore System</summary>
**🔄 Smart Backup Features:**
- **Version-aware backups** with compatibility checking
- **Safety restore** with automatic rollback protection
- **Scheduled automation** with cron integration
- **Telegram notifications** with file delivery and alerts
- **Cross-server migration** support with detailed instructions
- **Compressed archives** with unified structure
**📦 What's Backed Up:**
- PostgreSQL database as `db_backup.sql`
- Configuration files: `docker-compose.yml`, `.env`, `app-config.json`
- Optional: full directory backup with selective restore
**🎯 Quick Commands:**
```bash
remnawave backup # Create instant backup
remnawave schedule # Setup automated backups
remnawave restore # Intelligent restore with version checks
```
**🛡️ Safety Features:**
- Automatic version compatibility verification
- Safety backup before restore operations
- Rollback capability if restore fails
- Real-time status monitoring during operations
**📋 Restore Options:**
- Full restore (replace all files and database)
- Database-only restore (keep existing files)
- Custom directory restoration
- Manual restore commands included in each backup archive
**Legacy Standalone Scripts:**
Available for users who need legacy standalone backup/restore tools:
- [remnawave-backup.sh](https://github.com/DigneZzZ/remnawave-scripts/raw/main/remnawave-backup.sh) - Standalone backup script
- [restore.sh](https://github.com/DigneZzZ/remnawave-scripts/raw/main/restore.sh) - Standalone restore script
</details>
<br />
<div style={{ display: 'flex', justifyContent: 'center' }}>
<img src="/awesome/remnawave-script.webp" alt="Remnawave Management Scripts" width="600" />
</div>
---
### Remnawave Reverse Proxy from eGames
Server Setup Using NGINX Reverse Proxy. This script is designed to streamline the setup of a reverse proxy server using NGINX and Xray, as well as to automate the installation of the Remnawave control panel and node. In this configuration, Xray operates directly on port 443, forwarding traffic through a socket that NGINX listens to.
Author: [eGamesAPI](https://github.com/eGamesAPI)
#### Installation Guidelines
Please read the [Installation Guidelines](https://github.com/eGamesAPI/remnawave-reverse-proxy/blob/main/README.md) or the [wiki](https://wiki.egam.es) before proceeding with the installation.
#### Installation
```bash
bash <(curl -Ls https://raw.githubusercontent.com/eGamesAPI/remnawave-reverse-proxy/refs/heads/main/install_remnawave.sh)
```
Features:
- Support for automatic configuration updates via subscription
- NGINX reverse proxy setup in combination with Xray
- Cloudflare SSL certificates with automatic renewal
- UFW setup for access management
- BBR optimization for TCP connections
<div style={{ display: 'flex', justifyContent: 'center', gap: '1rem', flexWrap: 'wrap' }}>
<Button label="Github repository" link="https://github.com/eGamesAPI/remnawave-reverse-proxy" variant="secondary" size="md" outline />
<Button label="Documentation" link="https://wiki.egam.es" variant="secondary" size="md" outline />
<Button label="Telegram Chat" link="https://t.me/+G8GtPf9dW9FlMWVi" variant="secondary" size="md" outline />
</div>
<br />
<div style={{ display: 'flex', justifyContent: 'center' }}>
<img src="/awesome/remnawave-reverse-proxy.webp" alt="REMNAWAVE-REVERSE-PROXY" width="600" />
</div>
---
### Remnawave Telegram Subscription Mini App
This is a Telegram Subscription Mini App that allows users to view their subscriptions directly through Telegram. As a requirement for using the page, the Telegram ID must be set in the user's profile to ensure proper identification and linking of subscriptions.
Features:
- View your subscriptions in the mini app
- Multi-language support (English, Russian)
Author: [maposia](https://github.com/maposia)
<details>
<summary>Installation instructions</summary>
#### Environment Variables
The application requires the following environment variables to be set:
| Variable | Description |
|-------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `REMNAWAVE_PANEL_URL` | Remnawave Panel URL, can be `http://remnawave:3000` or `https://panel.example.com` |
| `REMNAWAVE_TOKEN` | Authentication token for Remnawave API |
| `BUY_LINK` | The URL for purchase actions |
| `CRYPTO_LINK` | Allows using encrypted links (currently supported Happ application) |
| `REDIRECT_LINK` | Allows you to specify a **custom redirect page URL** for deep links. Useful for handling protocols like `v2box://` in Telegram Desktop (Windows). For more details and examples, see [Telegram Deep Link Redirect](https://github.com/maposia/redirect-page/tree/main) |
| `AUTH_API_KEY` | If you use "Caddy with security" or TinyAuth for Nginx addon, you can place here X-Api-Key, which will be applied to requests to Remnawave Panel. |
#### Install and Run
1. Create a new directory for the mini app
```bash
mkdir /opt/remnawave-telegram-sub-mini-app && cd /opt/remnawave-telegram-sub-mini-app
```
2. Download the sample environment variables.
```bash
curl -o .env https://raw.githubusercontent.com/maposia/remnawave-telegram-mini-bot/refs/heads/main/.env.example
```
3. Configure the environment variables.
```bash
nano .env
```
4. Create docker-compose.yml file
```bash
nano docker-compose.yml
```
Example below:
```yaml
services:
remnawave-mini-app:
image: ghcr.io/maposia/remnawave-telegram-sub-mini-app:latest
container_name: remnawave-telegram-mini-app
hostname: remnawave-telegram-mini-app
env_file:
- .env
restart: always
# volumes:
# - ./app-config.json:/app/public/assets/app-config.json
ports:
- '127.0.0.1:3020:3020'
# networks:
# - remnawave-network
#networks:
# remnawave-network:
# name: remnawave-network
# driver: bridge
# external: true
```
Uncomment if you want to use your own template downloaded from the Remnawave panel.
P.S. File must be placed in the same directory as this `docker-compose.yml` file
```yaml
volumes:
- ./app-config.json:/app/public/assets/app-config.json
```
Uncomment if you want to use local connection via single network in docker
```yaml
networks:
- remnawave-network
networks:
remnawave-network:
name: remnawave-network
driver: bridge
external: true
```
1. Run containers.
```bash
docker compose up -d && docker compose logs -f
```
2. Mini app is now running on http://127.0.0.1:3020
Now we are ready to move on to Reverse Proxy installation.
</details>
<div style={{ display: 'flex', justifyContent: 'center', gap: '1rem' }}>
<Button label="Github repository" link="https://github.com/maposia/remnawave-telegram-sub-mini-app" variant="secondary" size="md" outline />
</div>
<br />
<div style={{ display: 'flex', justifyContent: 'center' }}>
<img src="/awesome/remnawave-telegram-sub-mini-app.webp" alt="Remnawave Telegram Subscription Mini App" width="600" />
</div>
---
### Ansible playbook for Install Remnawave
This project helps install Remnawave via Ansible.
Author: [iphizic](https://github.com/iphizic)
<details>
<summary>Installation instructions</summary>
#### Clone repo and change dir
```bash
git clone https://github.com/iphizic/remna-playbook.git
cd remna-playbook
```
#### Now make Python .env:
```bash
python3 -m venv .env
```
#### Activate .env:
```bash
source .env/bin/activate
```
#### Install Ansible and requirements:
```bash
pip install -r requirements.txt
ansible-galaxy install -r requirements.yml
```
#### Make inventory and other vars
Make inventory like inventory.yml.example in inventory dir
In directory group_vars make all.yml like all.yml.example
#### `Optional` Make some user but not root
:::warning
To run this playbook, the GitHub username must match the username in all.yml
:::
```bash
ansible-playbook prepare-playbook.yml -u root -k
```
First question it is root password
Second question it is password for the created user
#### Run install Remnaware:
```bash
ansible-playbook playbook.yml -K
```
</details>
<div style={{ display: 'flex', justifyContent: 'center', gap: '1rem' }}>
<Button label="Github repository" link="https://github.com/iphizic/remna-playbook" variant="secondary" size="md" outline />
</div>
<br />
<div style={{ display: 'flex', justifyContent: 'center' }}>
<img src="/awesome/ansible.webp" alt="Ansible playbook for installation" width="600" />
</div>
---
### Remnawave Telegram Shop Bot
A Telegram bot for selling subscriptions with integration to Remnawave. This service allows users to purchase and manage subscriptions through Telegram with multiple payment system options. YooKass | Telegram Stars | CryptoBot
Author: [jolymmiles](https://github.com/Jolymmiles)
<div style={{ display: 'flex', justifyContent: 'center', gap: '1rem', flexWrap: 'wrap' }}>
<Button label="Github repository" link="https://github.com/Jolymmiels/remnawave-telegram-shop" variant="secondary" size="md" outline />
<Button label="Documentation" link="https://github.com/Jolymmiels/remnawave-telegram-shop/wiki" variant="secondary" size="md" outline />
<Button label="Telegram Chat" link="https://t.me/remnawavetelegramshop" variant="secondary" size="md" outline />
</div>
<br />
<div style={{ display: 'flex', justifyContent: 'center' }}>
<img src="/awesome/remnawave-telegram-shop-bot.webp" alt="Remnawave Telegram Shop Bot" width="600" />
</div>
---
### RemnaSetup 🛠️
Universal script for automatic installation, configuration, and updating of Remnawave and Remnanode infrastructure. Includes installation of the control panel, node, subscription page, Caddy setup, Tblocker, BBR, WARP, and an automatic backup system with Telegram integration.
Author: [Capybara-z](https://github.com/Capybara-z)
<details>
<summary>Quick Start</summary>
**Option 1:**
```bash
bash <(curl -fsSL raw.githubusercontent.com/Capybara-z/RemnaSetup/refs/heads/main/install.sh)
```
**Option 2:**
```bash
curl -fsSL https://raw.githubusercontent.com/Capybara-z/RemnaSetup/refs/heads/main/install.sh -o install.sh && chmod +x install.sh && sudo bash ./install.sh
```
</details>
**🔥 Main Features:**
- 📦 Complete Remnawave installation + Subscription page + Caddy
- 🌐 Remnanode installation with Caddy, Tblocker, BBR, and WARP
- 💾 Backup system with Telegram integration
- ♻️ Recovery from local backups and Telegram
- 🔄 Automatic component updates
<div style={{ display: 'flex', justifyContent: 'center', gap: '1rem' }}>
<Button label="Github repository" link="https://github.com/Capybara-z/RemnaSetup" variant="secondary" size="md" outline />
</div>
<br />
<div style={{ display: 'flex', justifyContent: 'center' }}>
<img src="/awesome/remnasetup.webp" alt="RemnaSetup" width="600" />
</div>
---
### Remnawave Backup & Restore by distillium
The script automates backups and performs a restore of the Remnawave database.
**Author:** [distillium](https://github.com/distillium)
<details>
<summary>Instruction</summary>
#### Installation
```bash
curl -o ~/backup-restore.sh https://raw.githubusercontent.com/distillium/remnawave-backup-restore/main/backup-restore.sh && chmod +x ~/backup-restore.sh && ~/backup-restore.sh
```
:::danger
As a precaution, use the restore function on the same panel version from which the backup was made (or create the backup from the latest panel version).
:::
:::warning
This script is designed to perform meaningful maintenance operations on the Remnawave database. Although it has been thoroughly tested, its functions affect the entire database and its components. It is recommended that you carefully follow the scripts instructions before executing any commands.
:::
:::tip
The script backups and restores only the entire database, as well as the .env and .env-node files (if they exist in the /opt/remnawave/ or /root/remnawave/ directory). The backup and recovery of all other files and configurations are entirely the responsibility of the user.
:::
</details>
**Features:**
- creating a manual backup and configuring automatic scheduled backups
- notifications in Telegram with backup file attached
- supports sending backup to Google Drive
- restore from backup
- backups retention policy (7 days) implemented
- quick access from anywhere on the system with the `rw-backup` command
<div style={{ display: 'flex', justifyContent: 'center', gap: '1rem' }}>
<Button label="Github repository" link="https://github.com/distillium/remnawave-backup-restore" variant="secondary" size="md" outline />
</div>
<br />
<div style={{ display: 'flex', justifyContent: 'center' }}>
<img src="/awesome/remnawave-backup-restore.webp" alt="REMNAWAVE-BACKUP-RESTORE" width="600" />
</div>
---
### WARP Native Installer
This script installs Cloudflare WARP in “native” mode via `WireGuard`, without using `warp-cli`.
**Script Author:** [distillium](https://github.com/distillium) <br />
**Ansible Role Author:** [TheMelbine](https://github.com/TheMelbine)
It automates:
- Installing the necessary packages (`wireguard`, `resolvconf`)
- Downloading and configuring `wgcf`
- Generating and modifying the WireGuard configuration
- Connecting and checking status
- Enabling autorun of the `warp` interface
**Installing:** <br />
**Option 1: Shell Script (performed on each desired node):**
```bash
bash <(curl -fsSL https://raw.githubusercontent.com/distillium/warp-native/main/install.sh)
```
<div style={{ display: 'flex', justifyContent: 'center', gap: '1rem' }}>
<Button label="Shell Script Github Repository" link="https://github.com/distillium/warp-native" variant="secondary" size="md" outline />
</div>
<br />
**Option 2: Ansible Role (Recommended for automation)**
```bash
ansible-galaxy install themelbine.warp_native
```
<details>
<summary>📝 Show example playbook</summary>
```yaml
- hosts: warp_servers
become: yes
roles:
- themelbine.warp_native
vars:
warp_native_state: present
warp_native_modify_resolv: true
```
</details>
<div style={{ display: 'flex', justifyContent: 'center', gap: '1rem' }}>
<Button label="Ansible Role Github Repository" link="https://github.com/TheMelbine/ansible-role-warp-native" variant="secondary" size="md" outline />
</div>
<br /><br />
**Templates for Xray configuration**
<details>
<summary>📝 Show example outbound</summary>
```json
{
"tag": "warp-out",
"protocol": "freedom",
"settings": {},
"streamSettings": {
"sockopt": {
"interface": "warp",
"tcpFastOpen": true
}
}
}
```
</details>
<details>
<summary>📝 Show example routing rule</summary>
```json
{
"type": "field",
"domain": [
"netflix.com",
"youtube.com",
"twitter.com"
],
"inboundTag": [
"Node-1",
"Node-2"
],
"outboundTag": "warp-out"
}
```
</details>
<br />
**Interface management**
<details>
<summary>⚙️ Commands</summary>
| Operation | Command |
|------------------------|----------------------------------------|
| Check service status | `systemctl status wg-quick@warp` |
| View interface status | `wg show warp` |
| Stop the interface | `systemctl stop wg-quick@warp` |
| Start the interface | `systemctl start wg-quick@warp` |
| Restart the interface | `systemctl restart wg-quick@warp` |
| Disable autorun | `systemctl disable wg-quick@warp` |
| Enable autorun | `systemctl enable wg-quick@warp` |
</details>
<br />
**Uninstall:** <br />
**Shell Script Method:**
```bash
bash <(curl -fsSL https://raw.githubusercontent.com/distillium/warp-native/main/uninstall.sh)
```
**Ansible Role Method:**
<details>
<summary>📝 Show</summary>
```yaml
- hosts: warp_servers
become: yes
roles:
- themelbine.warp_native
vars:
warp_native_state: absent
```
</details>
<div style={{ display: 'flex', justifyContent: 'center' }}>
<img src="/awesome/warp-native.webp" alt="warp-native" width="600" />
</div>
---
### Remnawave TG Shop
A Telegram bot for selling and managing Remnawave subscriptions. It supports user registration, trial periods, promo codes, referral programs, subscription management. Payments are accepted through YooKassa | CryptoPay | Telegram Stars | Tribute. Admins get access to a secure panel with statistics, user management, promo code creation, broadcast messaging and other functions
Author: [machka pasla](https://github.com/machka-pasla)
<div style={{ display: 'flex', justifyContent: 'center', gap: '1rem', flexWrap: 'wrap' }}>
<Button label="Github repository" link="https://github.com/machka-pasla/remnawave-tg-shop" variant="secondary" size="md" outline />
<Button label="Telegram Chat" link="https://t.me/remnawave_tg_shop" variant="secondary" size="md" outline />
</div>
<br />
<div style={{ display: 'flex', justifyContent: 'center' }}>
<img src="/awesome/remnawave-tg-shop.webp" alt="Remnawave TG Shop" width="600" />
</div>
---
### Remnawave Bedolaga Bot
Modern Telegram bot for automating VPN business through Remnawave API. Full-featured solution with user management, multi-channel payments, referral system, detailed analytics, Web API, and Telegram Mini App integration.
Author: [Fr1ngg](https://github.com/Fr1ngg)
<div style={{ display: 'flex', justifyContent: 'center', gap: '1rem', flexWrap: 'wrap' }}>
<Button label="Github repository" link="https://github.com/Fr1ngg/remnawave-bedolaga-telegram-bot" variant="secondary" size="md" outline />
<Button label="Test Bot" link="https://t.me/FringVPN_bot" variant="secondary" size="md" outline />
<Button label="Telegram Chat" link="https://t.me/+wTdMtSWq8YdmZmVi" variant="secondary" size="md" outline />
</div>
<br />
**🔥 Key Features:**
- 💰 **Multi-channel payments** - Telegram Stars, Tribute, YooKassa (SBP + receipts), CryptoBot, MulenPay, PayPalych
- 🎯 **Full automation** - from registration to subscription renewals
- 🎁 **Advanced promo system** - flexible promo codes (balance/days/extended trial), advertising campaigns with automatic bonuses, detailed usage statistics
- 📊 **Powerful analytics** - comprehensive statistics for users, payments, and servers
- 🛡️ **Enterprise ready** - AsyncIO, PostgreSQL, Redis, panel protection via cookies
- 🗄️ **Backup system** - automatic backups with Telegram notifications
- 🌐 **Multi-language** - Russian and English support
- 🔧 **Flexible configuration** - customizable plans, traffic packages, devices, servers
- 🌐 **Web API** - RESTful API for external integrations and custom admin panels
- 📱 **Telegram Mini App** - built-in subscription page with deep links
<div style={{ display: 'flex', justifyContent: 'center' }}>
<img src="/awesome/bedolaga.webp" alt="Remnawave Bedolaga Bot" width="600" />
</div>
---
## Add project to the list
If you want to add your project to the list, please open a PR on [GitHub](https://github.com/remnawave/panel/blob/main/docs/awesome-remnawave.md).
Make sure that the target branch is `main`.
Also, the following requirements must be met:
- [x] Project must be open source.
- [x] Project must be related to Remnawave or **useful for Remnawave users**.
The following format must be used:
```md
### Project name
Short project description.
[Project link or repository link](https://project.com)
![Project image](/awesome/project-name.webp)
```
Use the examples above to add your project to the list.
:::info
Please, use [https://squoosh.app/](https://squoosh.app/) to compress the image. Format must be `webp`.
Add the image to the `static/awesome` directory.
:::

288
docs/awesome-remnawave.mdx Normal file
View File

@@ -0,0 +1,288 @@
---
sidebar_position: 7
title: ❤️ Awesome Remnawave
hide_title: true
hide_table_of_contents: true
description: 'Discover the amazing ecosystem of tools, scripts, and integrations built by the Remnawave community. From monitoring solutions to automation scripts, find everything you need to enhance your Remnawave experience.'
image: '/awesome/awesome-preview.webp'
---
import Button from '@site/src/components/Button'
import ProjectCard from '@site/src/components/ProjectCard'
import ProjectsGrid from '@site/src/components/ProjectsGrid'
import HeroSection from '@site/src/components/HeroSection'
import CategoryNav from '@site/src/components/CategoryNav'
import RemnavaweTelegramMiniAppGuide from '/docs/awesome-remnawave/\_install-guides/remnawave-telegram-mini-app.md'
import RemnawaveManagementScriptsGuide from '/docs/awesome-remnawave/\_install-guides/remnawave-management-scripts.md'
import RemnasetupGuide from '/docs/awesome-remnawave/\_install-guides/remnasetup.md'
import AnsiblePlaybookGuide from '/docs/awesome-remnawave/\_install-guides/ansible-playbook.md'
import RemnawaveReverseProxyGuide from '/docs/awesome-remnawave/\_install-guides/remnawave-reverse-proxy.md'
import RemnawaveBackupRestoreGuide from '/docs/awesome-remnawave/\_install-guides/remnawave-backup-restore.md'
import WarpNativeInstallerGuide from '/docs/awesome-remnawave/\_install-guides/warp-native-installer.md'
import RemnavaweBedolagaBotGuide from '/docs/awesome-remnawave/\_install-guides/remnawave-bedolaga-bot.md'
<HeroSection
title="❤️ Awesome Remnawave"
subtitle="Discover the amazing ecosystem of tools, scripts, and integrations built by the Remnawave community. From monitoring solutions to automation scripts, find everything you need to enhance your Remnawave experience."
/>
<CategoryNav
categories={[
{ id: 'monitoring-analytics', icon: '📊', title: 'Monitoring & Analytics' },
{ id: 'commerce', icon: '💰', title: 'Commerce' },
{ id: 'auto-installers', icon: '🚀', title: 'Auto-installers' },
{ id: 'backup-restore', icon: '💾', title: 'Backup & Restore' },
{ id: 'misc', icon: '🔧', title: 'Misc' }
]}
/>
<CategorySection
id="monitoring-analytics"
title="Monitoring & Analytics"
description="Tools for monitoring, analyzing, and visualizing your Remnawave infrastructure"
icon="📊"
columns={1}
>
<ProjectCard
id="xray-checker"
title="Xray Checker"
description="Xray Checker is a tool for monitoring proxy server availability with support for VLESS, VMess, Trojan, and Shadowsocks protocols. It automatically tests connections through Xray Core and provides metrics for Prometheus, as well as API endpoints for integration with various monitoring systems."
author="kutovoys"
authorLink="https://github.com/kutovoys"
image="/awesome/xray-checker.webp"
githubRepo="kutovoys/xray-checker"
links={{
github: 'https://github.com/kutovoys/xray-checker',
docs: 'https://xray-checker.kutovoy.dev/'
}}
/>
</CategorySection>
<CategorySection
id="commerce"
title="Commerce"
description="Telegram bots and mini apps made for commerce with Remnawave."
icon="📦"
columns={2}
>
<ProjectCard
id="remnawave-telegram-shop-bot"
title="Remnawave Telegram Shop Bot"
description="A Telegram bot for selling subscriptions with integration to Remnawave. This service allows users to purchase and manage subscriptions through Telegram with multiple payment system options."
author="jolymmiles"
authorLink="https://github.com/Jolymmiles"
image="/awesome/remnawave-telegram-shop-bot.webp"
githubRepo="Jolymmiels/remnawave-telegram-shop"
links={{
github: 'https://github.com/Jolymmiels/remnawave-telegram-shop',
docs: 'https://github.com/Jolymmiels/remnawave-telegram-shop/wiki',
telegram: 'https://t.me/remnawavetelegramshop'
}}
featured={true}
/>
<ProjectCard
id="remnawave-telegram-mini-app"
title="Remnawave Telegram Subscription Mini App"
description="This is a Telegram Subscription Mini App that allows users to view their subscriptions directly through Telegram. As a requirement for using the page, the Telegram ID must be set in the user's profile to ensure proper identification and linking of subscriptions."
author="maposia"
authorLink="https://github.com/maposia"
image="/awesome/remnawave-telegram-sub-mini-app.webp"
githubRepo="maposia/remnawave-telegram-sub-mini-app"
links={{
github: 'https://github.com/maposia/remnawave-telegram-sub-mini-app'
}}
>
<RemnavaweTelegramMiniAppGuide />
</ProjectCard>
<ProjectCard
id="remnawave-tg-shop"
title="Remnawave TG Shop"
description="A Telegram bot for selling and managing Remnawave subscriptions. It supports user registration, trial periods, promo codes, referral programs, subscription management. Payments are accepted through YooKassa, CryptoPay, Telegram Stars, Tribute. Admins get access to a secure panel with statistics, user management, promo code creation, broadcast messaging and other functions"
author="machka pasla"
authorLink="https://github.com/machka-pasla"
image="/awesome/remnawave-tg-shop.webp"
githubRepo="machka-pasla/remnawave-tg-shop"
links={{
github: 'https://github.com/machka-pasla/remnawave-tg-shop',
telegram: 'https://t.me/remnawave_tg_shop'
}}
/>
<ProjectCard
id="remnawave-bedolaga-bot"
title="Remnawave Bedolaga Bot"
description="Modern Telegram bot for automating VPN business through Remnawave API. Full-featured solution with user management, multi-channel payments, referral system, detailed analytics, Web API, and Telegram Mini App integration."
author="Fr1ngg"
authorLink="https://github.com/Fr1ngg"
image="/awesome/bedolaga.webp"
githubRepo="Fr1ngg/remnawave-bedolaga-telegram-bot"
links={{
github: 'https://github.com/Fr1ngg/remnawave-bedolaga-telegram-bot',
website: 'https://t.me/FringVPN_bot',
telegram: 'https://t.me/+wTdMtSWq8YdmZmVi'
}}
>
<RemnavaweBedolagaBotGuide />
</ProjectCard>
</CategorySection>
<CategorySection
id="auto-installers"
title="Auto-installers"
description="Automated installation, configuration, and deployment tools for Remnawave infrastructure."
icon="🚀 "
columns={2}
>
<ProjectCard
id="remnawave-reverse-proxy"
title="Remnawave Reverse Proxy"
description="Server Setup Using NGINX Reverse Proxy. This script is designed to streamline the setup of a reverse proxy server using NGINX and Xray, as well as to automate the installation of the Remnawave control panel and node. In this configuration, Xray operates directly on port 443, forwarding traffic through a socket that NGINX listens to."
author="eGamesAPI"
authorLink="https://github.com/eGamesAPI"
image="/awesome/remnawave-reverse-proxy.webp"
githubRepo="eGamesAPI/remnawave-reverse-proxy"
links={{
github: 'https://github.com/eGamesAPI/remnawave-reverse-proxy',
docs: 'https://wiki.egam.es',
telegram: 'https://t.me/+G8GtPf9dW9FlMWVi'
}}
featured={true}
>
<RemnawaveReverseProxyGuide />
</ProjectCard>
<ProjectCard
id="remnawave-management-scripts"
title="Remnawave Management Scripts"
description="Comprehensive bash scripts for Remnawave Panel, Remnawave Node, and Reality Selfsteal with full automation support. Features Docker integration, intelligent backup/restore system with version checking, advanced monitoring, and complete lifecycle management."
author="DigneZzZ"
authorLink="https://github.com/DigneZzZ"
image="/awesome/remnawave-script.webp"
githubRepo="DigneZzZ/remnawave-scripts"
links={{
github: 'https://github.com/DigneZzZ/remnawave-scripts'
}}
>
<RemnawaveManagementScriptsGuide />
</ProjectCard>
<ProjectCard
id="remnasetup"
title="RemnaSetup"
description="Universal script for automatic installation, configuration, and updating of Remnawave and Remnanode infrastructure. Includes installation of the control panel, node, subscription page, Caddy setup, Tblocker, BBR, WARP, and an automatic backup system with Telegram integration."
author="Capybara-z"
authorLink="https://github.com/Capybara-z"
image="/awesome/remnasetup.webp"
githubRepo="Capybara-z/RemnaSetup"
links={{
github: 'https://github.com/Capybara-z/RemnaSetup'
}}
>
<RemnasetupGuide />
</ProjectCard>
<ProjectCard
id="ansible-playbook"
title="Ansible playbook for Install Remnawave"
description="This project helps install Remnawave via Ansible."
author="iphizic"
authorLink="https://github.com/iphizic"
image="/awesome/ansible.webp"
githubRepo="iphizic/remna-playbook"
links={{
github: 'https://github.com/iphizic/remna-playbook'
}}
>
<AnsiblePlaybookGuide />
</ProjectCard>
</CategorySection>
<CategorySection
id="backup-restore"
title="Backup & Restore"
description="Tools for backing up and restoring your Remnawave database and configurations"
icon="💾"
columns={1}
>
<ProjectCard
id="remnawave-backup-restore"
title="Remnawave Backup & Restore"
description="The script automates backups and performs a restore of the Remnawave database."
author="distillium"
authorLink="https://github.com/distillium"
image="/awesome/remnawave-backup-restore.webp"
githubRepo="distillium/remnawave-backup-restore"
links={{
github: 'https://github.com/distillium/remnawave-backup-restore'
}}
>
<RemnawaveBackupRestoreGuide />
</ProjectCard>
</CategorySection>
<CategorySection
id="misc"
title="Misc"
description="Utilities, tools, and integrations that don't fit into other categories."
icon="🔧"
columns={2}
>
<ProjectCard
id="warp-native-installer"
title="WARP Native Installer"
description="This script installs Cloudflare WARP in 'native' mode via WireGuard, without using warp-cli. Automates package installation, wgcf configuration, and enables autorun. Available as both shell script and Ansible role."
author="distillium & TheMelbine"
authorLink="https://github.com/distillium"
image="/awesome/warp-native.webp"
githubRepo="distillium/warp-native"
links={{
github: 'https://github.com/distillium/warp-native'
}}
>
<WarpNativeInstallerGuide />
</ProjectCard>
<ProjectCard
id="geo-file-viewer"
title="Geo File Viewer"
description="A utility for viewing the contents of geoip and geofile (.dat) files in the v2fly format."
image="/awesome/geofileviewer.webp"
links={{
website: 'https://jomertix.github.io/geofileviewer'
}}
/>
</CategorySection>
---
## 🎯 Add Your Project
Want to showcase your Remnawave-related project? We'd love to see it!
**Requirements:**
- ✅ Project must be open source
- ✅ Project must be related to Remnawave or useful for Remnawave users
**How to submit:**
1. Open a PR on [GitHub](https://github.com/remnawave/panel/blob/main/docs/awesome-remnawave.md)
2. Make sure the target branch is `main`
:::info Image Requirements
Please use [https://squoosh.app/](https://squoosh.app/) to compress your image.
Format must be `webp` and placed in the `static/awesome` directory.
:::
---
<div
style={{
textAlign: 'center',
marginTop: '4rem',
padding: '2rem',
borderRadius: '12px'
}}
>
<h3>🌟 Thank you to all contributors!</h3>
<p>The Remnawave community thrives because of amazing developers like you.</p>
</div>

View File

@@ -0,0 +1,51 @@
### Installation instructions
#### Clone repo and change dir
```bash
git clone https://github.com/iphizic/remna-playbook.git
cd remna-playbook
```
#### Now make Python .env:
```bash
python3 -m venv .env
```
#### Activate .env:
```bash
source .env/bin/activate
```
#### Install Ansible and requirements:
```bash
pip install -r requirements.txt
ansible-galaxy install -r requirements.yml
```
#### Make inventory and other vars
Make inventory like inventory.yml.example in inventory dir
In directory group_vars make all.yml like all.yml.example
#### `Optional` Make some user but not root
:::warning
To run this playbook, the GitHub username must match the username in all.yml
:::
```bash
ansible-playbook prepare-playbook.yml -u root -k
```
First question it is root password
Second question it is password for the created user
#### Run install Remnaware:
```bash
ansible-playbook playbook.yml -K
```

View File

@@ -0,0 +1,21 @@
### 🔥 Main Features
- 📦 Complete Remnawave installation + Subscription page + Caddy
- 🌐 Remnanode installation with Caddy, Tblocker, BBR, and WARP
- 💾 Backup system with Telegram integration
- ♻️ Recovery from local backups and Telegram
- 🔄 Automatic component updates
### Quick Start
#### Option 1
```bash
bash <(curl -fsSL raw.githubusercontent.com/Capybara-z/RemnaSetup/refs/heads/main/install.sh)
```
#### Option 2
```bash
curl -fsSL https://raw.githubusercontent.com/Capybara-z/RemnaSetup/refs/heads/main/install.sh -o install.sh && chmod +x install.sh && sudo bash ./install.sh
```

View File

@@ -0,0 +1,26 @@
### Features
- creating a manual backup and configuring automatic scheduled backups
- notifications in Telegram with backup file attached
- supports sending backup to Google Drive
- restore from backup
- backups retention policy (7 days) implemented
- quick access from anywhere on the system with the `rw-backup` command
### Installation
```bash
curl -o ~/backup-restore.sh https://raw.githubusercontent.com/distillium/remnawave-backup-restore/main/backup-restore.sh && chmod +x ~/backup-restore.sh && ~/backup-restore.sh
```
:::danger
As a precaution, use the restore function on the same panel version from which the backup was made (or create the backup from the latest panel version).
:::
:::warning
This script is designed to perform meaningful maintenance operations on the Remnawave database. Although it has been thoroughly tested, its functions affect the entire database and its components. It is recommended that you carefully follow the script's instructions before executing any commands.
:::
:::tip
The script backups and restores only the entire database, as well as the .env and .env-node files (if they exist in the /opt/remnawave/ or /root/remnawave/ directory). The backup and recovery of all other files and configurations are entirely the responsibility of the user.
:::

View File

@@ -0,0 +1,12 @@
### 🔥 Key Features
- 💰 **Multi-channel payments** - Telegram Stars, Tribute, YooKassa (SBP + receipts), CryptoBot, MulenPay, PayPalych
- 🎯 **Full automation** - from registration to subscription renewals
- 🎁 **Advanced promo system** - flexible promo codes (balance/days/extended trial), advertising campaigns with automatic bonuses, detailed usage statistics
- 📊 **Powerful analytics** - comprehensive statistics for users, payments, and servers
- 🛡️ **Enterprise ready** - AsyncIO, PostgreSQL, Redis, panel protection via cookies
- 🗄️ **Backup system** - automatic backups with Telegram notifications
- 🌐 **Multi-language** - Russian and English support
- 🔧 **Flexible configuration** - customizable plans, traffic packages, devices, servers
- 🌐 **Web API** - RESTful API for external integrations and custom admin panels
- 📱 **Telegram Mini App** - built-in subscription page with deep links

View File

@@ -0,0 +1,136 @@
### 📦 Key Features
- 🚀 **One-line installation** for Panel, Node, and Selfsteal configurations
- 🎛️ **Interactive menus** with real-time status monitoring and guided operations
- 💾 **Smart backup system** with version compatibility checking and safety rollbacks
- 🔄 **Complete lifecycle management** - install, update, backup, restore, uninstall
- 🎯 **Reality masking** with 11 AI-generated website templates
### Quick Install Commands
#### Remnawave Panel (v3.5.5+)
```bash
bash <(curl -Ls https://github.com/DigneZzZ/remnawave-scripts/raw/main/remnawave.sh) @ install
```
#### Remnawave Node (v3.1.2+)
```bash
bash <(curl -Ls https://github.com/DigneZzZ/remnawave-scripts/raw/main/remnanode.sh) @ install
```
#### Reality Selfsteal (v2.1.3+)
```bash
bash <(curl -Ls https://github.com/DigneZzZ/remnawave-scripts/raw/main/selfsteal.sh) @ install
```
:::info Options
- Add `--dev` for development version
- Add `--name customname` for custom directory (default: `/opt/remnawave`, `/opt/remnanode`)
:::
#### For existing installations
Use `install-script` to add CLI wrapper only:
```bash
bash <(curl -Ls https://github.com/DigneZzZ/remnawave-scripts/raw/main/remnawave.sh) @ install-script
```
```bash
bash <(curl -Ls https://github.com/DigneZzZ/remnawave-scripts/raw/main/remnanode.sh) @ install-script
```
### Available CLI Commands
**Installation & Management:**
- `install`, `update`, `uninstall`
- `install-script`, `uninstall-script`
**Service Control:**
- `up`, `down`, `restart`, `status`, `logs`
**Node-specific Commands:**
- `core-update` - Manual Update/Install Xray-core to latest version
- `xray-log-out`, `xray-log-err` - View Xray logs
- `setup-logs` - Configure log rotation
**Configuration:**
- `edit`, `edit-env`, `console` (Panel only)
**Interactive Menus:**
- Run `remnawave`, `remnanode`, or `selfsteal` without arguments for interactive menu
- Real-time status monitoring and resource usage
- Step-by-step guided operations
**Backup & Restore (Panel):**
- `backup` - Create manual backup
- `schedule` - Configure automated backups
- `restore` - Restore from backup archive
**Reality Selfsteal:**
- Choose from 11 AI-generated website templates
- Automatic SSL certificate management by Caddy
- DNS validation before start
Run `remnawave help`, `remnanode help`, or `selfsteal help` for detailed usage.
### 💾 Intelligent Backup & Restore System
**🔄 Smart Backup Features:**
- **Version-aware backups** with compatibility checking
- **Safety restore** with automatic rollback protection
- **Scheduled automation** with cron integration
- **Telegram notifications** with file delivery and alerts
- **Cross-server migration** support with detailed instructions
- **Compressed archives** with unified structure
**📦 What's Backed Up:**
- PostgreSQL database as `db_backup.sql`
- Configuration files: `docker-compose.yml`, `.env`, `app-config.json`
- Optional: full directory backup with selective restore
**🎯 Quick Commands:**
```bash
remnawave backup # Create instant backup
remnawave schedule # Setup automated backups
remnawave restore # Intelligent restore with version checks
```
**🛡️ Safety Features:**
- Automatic version compatibility verification
- Safety backup before restore operations
- Rollback capability if restore fails
- Real-time status monitoring during operations
**📋 Restore Options:**
- Full restore (replace all files and database)
- Database-only restore (keep existing files)
- Custom directory restoration
- Manual restore commands included in each backup archive
**Legacy Standalone Scripts:**
Available for users who need legacy standalone backup/restore tools:
- [remnawave-backup.sh](https://github.com/DigneZzZ/remnawave-scripts/raw/main/remnawave-backup.sh) - Standalone backup script
- [restore.sh](https://github.com/DigneZzZ/remnawave-scripts/raw/main/restore.sh) - Standalone restore script
📦 Full info, updates, and examples: [**remnawave-scripts**](https://github.com/DigneZzZ/remnawave-scripts)
Project: [GIG.ovh](https://gig.ovh)

View File

@@ -0,0 +1,19 @@
### Installation Guidelines
:::warning
Please read the [Installation Guidelines](https://github.com/eGamesAPI/remnawave-reverse-proxy/blob/main/README.md) or the [wiki](https://wiki.egam.es) before proceeding with the installation.
:::
### Installation
```bash
bash <(curl -Ls https://raw.githubusercontent.com/eGamesAPI/remnawave-reverse-proxy/refs/heads/main/install_remnawave.sh)
```
### Features
- Support for automatic configuration updates via subscription
- NGINX reverse proxy setup in combination with Xray
- Cloudflare SSL certificates with automatic renewal
- UFW setup for access management
- BBR optimization for TCP connections

View File

@@ -0,0 +1,136 @@
### 📦 Key Features
- 🚀 **One-line installation** for Panel, Node, and Selfsteal configurations
- 🎛️ **Interactive menus** with real-time status monitoring and guided operations
- 💾 **Smart backup system** with version compatibility checking and safety rollbacks
- 🔄 **Complete lifecycle management** - install, update, backup, restore, uninstall
- 🎯 **Reality masking** with 11 AI-generated website templates
### Quick Install Commands
#### Remnawave Panel (v3.5.5+)
```bash
bash <(curl -Ls https://github.com/DigneZzZ/remnawave-scripts/raw/main/remnawave.sh) @ install
```
#### Remnawave Node (v3.1.2+)
```bash
bash <(curl -Ls https://github.com/DigneZzZ/remnawave-scripts/raw/main/remnanode.sh) @ install
```
#### Reality Selfsteal (v2.1.3+)
```bash
bash <(curl -Ls https://github.com/DigneZzZ/remnawave-scripts/raw/main/selfsteal.sh) @ install
```
:::info Options
- Add `--dev` for development version
- Add `--name customname` for custom directory (default: `/opt/remnawave`, `/opt/remnanode`)
:::
#### For existing installations
Use `install-script` to add CLI wrapper only:
```bash
bash <(curl -Ls https://github.com/DigneZzZ/remnawave-scripts/raw/main/remnawave.sh) @ install-script
```
```bash
bash <(curl -Ls https://github.com/DigneZzZ/remnawave-scripts/raw/main/remnanode.sh) @ install-script
```
### Available CLI Commands
**Installation & Management:**
- `install`, `update`, `uninstall`
- `install-script`, `uninstall-script`
**Service Control:**
- `up`, `down`, `restart`, `status`, `logs`
**Node-specific Commands:**
- `core-update` - Manual Update/Install Xray-core to latest version
- `xray-log-out`, `xray-log-err` - View Xray logs
- `setup-logs` - Configure log rotation
**Configuration:**
- `edit`, `edit-env`, `console` (Panel only)
**Interactive Menus:**
- Run `remnawave`, `remnanode`, or `selfsteal` without arguments for interactive menu
- Real-time status monitoring and resource usage
- Step-by-step guided operations
**Backup & Restore (Panel):**
- `backup` - Create manual backup
- `schedule` - Configure automated backups
- `restore` - Restore from backup archive
**Reality Selfsteal:**
- Choose from 11 AI-generated website templates
- Automatic SSL certificate management by Caddy
- DNS validation before start
Run `remnawave help`, `remnanode help`, or `selfsteal help` for detailed usage.
### 💾 Intelligent Backup & Restore System
**🔄 Smart Backup Features:**
- **Version-aware backups** with compatibility checking
- **Safety restore** with automatic rollback protection
- **Scheduled automation** with cron integration
- **Telegram notifications** with file delivery and alerts
- **Cross-server migration** support with detailed instructions
- **Compressed archives** with unified structure
**📦 What's Backed Up:**
- PostgreSQL database as `db_backup.sql`
- Configuration files: `docker-compose.yml`, `.env`, `app-config.json`
- Optional: full directory backup with selective restore
**🎯 Quick Commands:**
```bash
remnawave backup # Create instant backup
remnawave schedule # Setup automated backups
remnawave restore # Intelligent restore with version checks
```
**🛡️ Safety Features:**
- Automatic version compatibility verification
- Safety backup before restore operations
- Rollback capability if restore fails
- Real-time status monitoring during operations
**📋 Restore Options:**
- Full restore (replace all files and database)
- Database-only restore (keep existing files)
- Custom directory restoration
- Manual restore commands included in each backup archive
**Legacy Standalone Scripts:**
Available for users who need legacy standalone backup/restore tools:
- [remnawave-backup.sh](https://github.com/DigneZzZ/remnawave-scripts/raw/main/remnawave-backup.sh) - Standalone backup script
- [restore.sh](https://github.com/DigneZzZ/remnawave-scripts/raw/main/restore.sh) - Standalone restore script
📦 Full info, updates, and examples: [**remnawave-scripts**](https://github.com/DigneZzZ/remnawave-scripts)
Project: [GIG.ovh](https://gig.ovh)

View File

@@ -0,0 +1,100 @@
### Features
- View your subscriptions in the mini app
- Multi-language support (English, Russian)
### Environment Variables
The application requires the following environment variables to be set:
| Variable | Description |
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `REMNAWAVE_PANEL_URL` | Remnawave Panel URL, can be `http://remnawave:3000` or `https://panel.example.com` |
| `REMNAWAVE_TOKEN` | Authentication token for Remnawave API |
| `BUY_LINK` | The URL for purchase actions |
| `CRYPTO_LINK` | Allows using encrypted links (currently supported Happ application) |
| `REDIRECT_LINK` | Allows you to specify a **custom redirect page URL** for deep links. Useful for handling protocols like `v2box://` in Telegram Desktop (Windows). For more details and examples, see [Telegram Deep Link Redirect](https://github.com/maposia/redirect-page/tree/main) |
| `AUTH_API_KEY` | If you use "Caddy with security" or TinyAuth for Nginx addon, you can place here X-Api-Key, which will be applied to requests to Remnawave Panel. |
### Install and Run
#### 1. Create a new directory for the mini app
```bash
mkdir /opt/remnawave-telegram-sub-mini-app && cd /opt/remnawave-telegram-sub-mini-app
```
#### 2. Download the sample environment variables
```bash
curl -o .env https://raw.githubusercontent.com/maposia/remnawave-telegram-mini-bot/refs/heads/main/.env.example
```
#### 3. Configure the environment variables
```bash
nano .env
```
#### 4. Create docker-compose.yml file
```bash
nano docker-compose.yml
```
**Example below:**
```yaml
services:
remnawave-mini-app:
image: ghcr.io/maposia/remnawave-telegram-sub-mini-app:latest
container_name: remnawave-telegram-mini-app
hostname: remnawave-telegram-mini-app
env_file:
- .env
restart: always
# volumes:
# - ./app-config.json:/app/public/assets/app-config.json
ports:
- '127.0.0.1:3020:3020'
# networks:
# - remnawave-network
#networks:
# remnawave-network:
# name: remnawave-network
# driver: bridge
# external: true
```
Uncomment if you want to use your own template downloaded from the Remnawave panel.
P.S. File must be placed in the same directory as this `docker-compose.yml` file
```yaml
volumes:
- ./app-config.json:/app/public/assets/app-config.json
```
Uncomment if you want to use local connection via single network in docker
```yaml
networks:
- remnawave-network
networks:
remnawave-network:
name: remnawave-network
driver: bridge
external: true
```
#### 5. Run containers
```bash
docker compose up -d && docker compose logs -f
```
#### 6. Access the mini app
Mini app is now running on `http://127.0.0.1:3020`
Now we are ready to move on to Reverse Proxy installation.

View File

@@ -0,0 +1,98 @@
**Script Author:** [distillium](https://github.com/distillium)
**Ansible Role Author:** [TheMelbine](https://github.com/TheMelbine)
### It automates
- Installing the necessary packages (`wireguard`, `resolvconf`)
- Downloading and configuring `wgcf`
- Generating and modifying the WireGuard configuration
- Connecting and checking status
- Enabling autorun of the `warp` interface
### Installing
#### Option 1: Shell Script (performed on each desired node)
```bash
bash <(curl -fsSL https://raw.githubusercontent.com/distillium/warp-native/main/install.sh)
```
#### Option 2: Ansible Role (Recommended for automation)
```bash
ansible-galaxy install themelbine.warp_native
```
**Example playbook:**
```yaml
- hosts: warp_servers
become: yes
roles:
- themelbine.warp_native
vars:
warp_native_state: present
warp_native_modify_resolv: true
```
[Ansible Role Github Repository](https://github.com/TheMelbine/ansible-role-warp-native)
### Templates for Xray configuration
**Example outbound:**
```json
{
"tag": "warp-out",
"protocol": "freedom",
"settings": {},
"streamSettings": {
"sockopt": {
"interface": "warp",
"tcpFastOpen": true
}
}
}
```
**Example routing rule:**
```json
{
"type": "field",
"domain": ["netflix.com", "youtube.com", "twitter.com"],
"inboundTag": ["Node-1", "Node-2"],
"outboundTag": "warp-out"
}
```
### Interface management
| Operation | Command |
| --------------------- | --------------------------------- |
| Check service status | `systemctl status wg-quick@warp` |
| View interface status | `wg show warp` |
| Stop the interface | `systemctl stop wg-quick@warp` |
| Start the interface | `systemctl start wg-quick@warp` |
| Restart the interface | `systemctl restart wg-quick@warp` |
| Disable autorun | `systemctl disable wg-quick@warp` |
| Enable autorun | `systemctl enable wg-quick@warp` |
### Uninstall
**Shell Script Method:**
```bash
bash <(curl -fsSL https://raw.githubusercontent.com/distillium/warp-native/main/uninstall.sh)
```
**Ansible Role Method:**
```yaml
- hosts: warp_servers
become: yes
roles:
- themelbine.warp_native
vars:
warp_native_state: absent
```

View File

@@ -0,0 +1,48 @@
import React from 'react'
import styles from './styles.module.css'
interface Category {
icon: string
id: string
title: string
}
interface CategoryNavProps {
categories: Category[]
}
export default function CategoryNav({ categories }: CategoryNavProps) {
const scrollToCategory = (id: string) => {
const element = document.getElementById(id)
if (element) {
const offset = 80
const elementPosition = element.getBoundingClientRect().top
const offsetPosition = elementPosition + window.pageYOffset - offset
window.scrollTo({
top: offsetPosition,
behavior: 'smooth'
})
}
}
return (
<div className={styles.categoryNav}>
<h3 className={styles.navTitle}>📚 Browse by Category</h3>
<div className={styles.categories}>
{categories.map((category) => (
<button
className={styles.categoryButton}
key={category.id}
onClick={() => scrollToCategory(category.id)}
type="button"
>
<span className={styles.categoryIcon}>{category.icon}</span>
<span className={styles.categoryTitle}>{category.title}</span>
</button>
))}
</div>
</div>
)
}

View File

@@ -0,0 +1,128 @@
.categoryNav {
margin: 3rem 0;
padding: 2rem;
background: var(--ifm-card-background-color);
border: 1px solid var(--ifm-color-emphasis-200);
border-radius: 16px;
}
.navTitle {
margin: 0 0 1.5rem 0;
text-align: center;
font-size: 1.4rem;
font-weight: 700;
color: var(--ifm-heading-color);
}
.categories {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
}
.categoryButton {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.75rem;
padding: 1.5rem 1rem;
background: var(--ifm-color-emphasis-100);
border: 2px solid transparent;
border-radius: 12px;
cursor: pointer;
transition: all 0.3s ease;
text-decoration: none;
}
.categoryButton:hover {
background: var(--ifm-color-primary-lightest);
border-color: var(--ifm-color-primary);
transform: translateY(-4px);
box-shadow: 0 8px 16px rgba(var(--ifm-color-primary-rgb), 0.2);
}
.categoryButton:active {
transform: translateY(-2px);
}
.categoryIcon {
font-size: 2.5rem;
line-height: 1;
transition: transform 0.3s ease;
}
.categoryButton:hover .categoryIcon {
transform: scale(1.1) rotate(5deg);
}
.categoryTitle {
font-size: 1rem;
font-weight: 600;
color: var(--ifm-heading-color);
text-align: center;
line-height: 1.3;
}
[data-theme='dark'] .categoryButton {
background: var(--ifm-color-emphasis-200);
}
[data-theme='dark'] .categoryButton:hover {
background: var(--ifm-color-emphasis-300);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
}
[data-theme='dark'] .categoryTitle {
color: var(--ifm-font-color-base);
}
[data-theme='dark'] .navTitle {
color: var(--ifm-font-color-base);
}
@media (max-width: 996px) {
.categories {
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
.categoryButton {
padding: 1.25rem 0.75rem;
}
.categoryIcon {
font-size: 2rem;
}
.categoryTitle {
font-size: 0.9rem;
}
}
@media (max-width: 768px) {
.categoryNav {
padding: 1.5rem;
margin: 2rem 0;
}
.navTitle {
font-size: 1.2rem;
margin-bottom: 1rem;
}
.categories {
grid-template-columns: repeat(2, 1fr);
gap: 0.75rem;
}
.categoryButton {
padding: 1rem 0.5rem;
}
.categoryIcon {
font-size: 1.75rem;
}
.categoryTitle {
font-size: 0.85rem;
}
}

View File

@@ -0,0 +1,47 @@
import React from 'react'
import styles from './styles.module.css'
interface CategorySectionProps {
children: React.ReactNode
columns?: 1 | 2 | 3
description?: string
icon?: string
id?: string
title: string
}
export default function CategorySection({
title,
description,
icon,
children,
columns = 3,
id
}: CategorySectionProps) {
const sectionId =
id ||
title
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-+|-+$/g, '')
return (
<section className={styles.categorySection}>
<div className={styles.categoryHeader}>
<div className={styles.categoryTitleWrapper} id={sectionId}>
{icon && <span className={styles.categoryIcon}>{icon}</span>}
<h2 className={styles.categoryTitle}>
<a className={styles.anchorLink} href={`#${sectionId}`}>
{title}
</a>
</h2>
</div>
{description && <p className={styles.categoryDescription}>{description}</p>}
</div>
<div className={styles.categoryContent} data-columns={columns}>
{children}
</div>
</section>
)
}

View File

@@ -0,0 +1,112 @@
.categorySection {
margin: 4rem 0;
scroll-margin-top: 80px;
}
.categoryHeader {
text-align: center;
margin-bottom: 3rem;
}
.categoryTitleWrapper {
display: flex;
align-items: center;
justify-content: center;
gap: 1rem;
margin-bottom: 1rem;
scroll-margin-top: 80px;
}
.anchorLink {
color: inherit;
text-decoration: none;
}
.categoryIcon {
font-size: 2.5rem;
line-height: 1;
}
.categoryTitle {
margin: 0;
font-size: 2.5rem;
font-weight: 800;
background: var(--ifm-color-white);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.categoryTitle:hover {
background: var(--ifm-color-primary);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.categoryDescription {
margin: 0;
font-size: 1.1rem;
color: var(--ifm-color-emphasis-700);
max-width: 700px;
margin: 0 auto;
line-height: 1.6;
}
.categoryContent {
display: grid;
gap: 2rem;
}
.categoryContent[data-columns='1'] {
grid-template-columns: 1fr;
max-width: 800px;
margin: 0 auto;
}
.categoryContent[data-columns='2'] {
grid-template-columns: repeat(2, 1fr);
}
.categoryContent[data-columns='3'] {
grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 996px) {
.categoryContent[data-columns='3'] {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 768px) {
.categorySection {
margin: 3rem 0;
}
.categoryHeader {
margin-bottom: 2rem;
}
.categoryTitleWrapper {
flex-direction: column;
gap: 0.5rem;
}
.categoryTitle {
font-size: 2rem;
}
.categoryDescription {
font-size: 1rem;
}
.categoryContent {
gap: 1.5rem;
}
.categoryContent[data-columns='1'],
.categoryContent[data-columns='2'],
.categoryContent[data-columns='3'] {
grid-template-columns: 1fr;
}
}

View File

@@ -0,0 +1,29 @@
import React from 'react'
import styles from './styles.module.css'
interface Feature {
description: string
icon: string
title: string
}
interface FeatureHighlightProps {
features: Feature[]
}
export default function FeatureHighlight({ features }: FeatureHighlightProps) {
return (
<div className={styles.featureGrid}>
{features.map((feature, index) => (
<div className={styles.featureCard} key={index}>
<div className={styles.iconWrapper}>
<span className={styles.icon}>{feature.icon}</span>
</div>
<h3 className={styles.title}>{feature.title}</h3>
<p className={styles.description}>{feature.description}</p>
</div>
))}
</div>
)
}

View File

@@ -0,0 +1,88 @@
.featureGrid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 2rem;
margin: 3rem 0;
}
.featureCard {
text-align: center;
padding: 2rem;
background: var(--ifm-card-background-color);
border: 1px solid var(--ifm-color-emphasis-200);
border-radius: 12px;
transition: all 0.3s ease;
}
.featureCard:hover {
transform: translateY(-4px);
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
border-color: var(--ifm-color-primary);
}
[data-theme='dark'] .featureCard:hover {
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
}
.iconWrapper {
display: inline-flex;
align-items: center;
justify-content: center;
width: 80px;
height: 80px;
background: linear-gradient(
135deg,
var(--ifm-color-primary-lightest) 0%,
var(--ifm-color-secondary-lightest) 100%
);
border-radius: 20px;
margin-bottom: 1.5rem;
transition: transform 0.3s ease;
}
.featureCard:hover .iconWrapper {
transform: scale(1.1) rotate(5deg);
}
.icon {
font-size: 2.5rem;
line-height: 1;
}
.title {
margin: 0 0 1rem 0;
font-size: 1.2rem;
font-weight: 700;
color: var(--ifm-heading-color);
}
.description {
margin: 0;
color: var(--ifm-color-emphasis-700);
line-height: 1.6;
font-size: 0.95rem;
}
@media (max-width: 768px) {
.featureGrid {
grid-template-columns: 1fr;
gap: 1.5rem;
}
.featureCard {
padding: 1.5rem;
}
.iconWrapper {
width: 60px;
height: 60px;
}
.icon {
font-size: 2rem;
}
.title {
font-size: 1.1rem;
}
}

View File

@@ -0,0 +1,89 @@
import React, { useEffect, useState } from 'react'
import styles from './styles.module.css'
interface GitHubStarsProps {
repo: string // Format: "owner/repo"
}
export default function GitHubStars({ repo }: GitHubStarsProps) {
const [stars, setStars] = useState<null | number>(null)
const [loading, setLoading] = useState(true)
useEffect(() => {
const cacheKey = `github-stars-${repo}`
const cached = localStorage.getItem(cacheKey)
if (cached) {
const { stars: cachedStars, timestamp } = JSON.parse(cached)
if (Date.now() - timestamp < 3600000) {
setStars(cachedStars)
setLoading(false)
return
}
}
fetch(`https://api.github.com/repos/${repo}`)
.then((res) => res.json())
.then((data) => {
if (data.stargazers_count !== undefined) {
setStars(data.stargazers_count)
localStorage.setItem(
cacheKey,
JSON.stringify({
stars: data.stargazers_count,
timestamp: Date.now()
})
)
}
setLoading(false)
})
.catch(() => {
// Silently fail - stars are not critical
setLoading(false)
})
}, [repo])
if (loading) {
return (
<span className={styles.stars}>
<svg
className={styles.icon}
fill="currentColor"
height="15"
viewBox="0 0 16 16"
width="15"
>
<path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25z" />
</svg>
<span className={styles.skeleton}>···</span>
</span>
)
}
if (stars === null) {
return null
}
const formatStars = (count: number): string => {
if (count >= 1000) {
return `${(count / 1000).toFixed(1)}k`
}
return count.toString()
}
return (
<span className={styles.stars}>
<svg
className={styles.icon}
fill="currentColor"
height="15"
viewBox="0 0 16 16"
width="15"
>
<path d="M8 .25a.75.75 0 0 1 .673.418l1.882 3.815 4.21.612a.75.75 0 0 1 .416 1.279l-3.046 2.97.719 4.192a.751.751 0 0 1-1.088.791L8 12.347l-3.766 1.98a.75.75 0 0 1-1.088-.79l.72-4.194L.818 6.374a.75.75 0 0 1 .416-1.28l4.21-.611L7.327.668A.75.75 0 0 1 8 .25z" />
</svg>
<span className={styles.count}>{formatStars(stars)}</span>
</span>
)
}

View File

@@ -0,0 +1,40 @@
.stars {
display: inline-flex;
align-items: center;
gap: 0.4rem;
font-size: 0.8rem;
font-weight: 700;
line-height: 1;
color: inherit;
}
.icon {
color: #daaa3f;
flex-shrink: 0;
}
.count {
font-weight: 700;
color: inherit;
line-height: 1;
}
.skeleton {
color: rgba(255, 255, 255, 0.6);
animation: pulse 1.5s ease-in-out infinite;
line-height: 1;
}
@keyframes pulse {
0%,
100% {
opacity: 0.6;
}
50% {
opacity: 1;
}
}
[data-theme='dark'] .icon {
color: #f1c40f;
}

View File

@@ -0,0 +1,25 @@
import React from 'react'
import styles from './styles.module.css'
interface HeroSectionProps {
gradient?: boolean
subtitle?: string
title: string
}
export default function HeroSection({ title, subtitle, gradient = true }: HeroSectionProps) {
return (
<div className={`${styles.hero} ${gradient ? styles.gradient : ''}`}>
<div className={styles.content}>
<h1 className={styles.title}>{title}</h1>
{subtitle && <p className={styles.subtitle}>{subtitle}</p>}
</div>
<div className={styles.decoration}>
<div className={styles.circle1}></div>
<div className={styles.circle2}></div>
<div className={styles.circle3}></div>
</div>
</div>
)
}

View File

@@ -0,0 +1,170 @@
.hero {
position: relative;
padding: 4rem 2rem;
margin: -2rem -2rem 4rem -2rem;
overflow: hidden;
border-radius: 0 0 24px 24px;
}
.gradient {
background: linear-gradient(
135deg,
var(--ifm-color-primary-lightest) 0%,
var(--ifm-color-primary-lighter) 50%,
var(--ifm-color-secondary-lighter) 100%
);
}
[data-theme='dark'] .gradient {
background: linear-gradient(
135deg,
rgba(var(--ifm-color-primary-rgb), 0.15) 0%,
rgba(var(--ifm-color-primary-rgb), 0.1) 50%,
rgba(var(--ifm-color-secondary-rgb), 0.1) 100%
);
}
.content {
position: relative;
z-index: 2;
text-align: center;
max-width: 800px;
margin: 0 auto;
}
.title {
font-size: 3.5rem;
font-weight: 900;
margin: 0 0 1rem 0;
background: linear-gradient(
120deg,
var(--ifm-color-primary-darkest) 0%,
var(--ifm-color-primary) 50%,
var(--ifm-color-secondary) 100%
);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
line-height: 1.2;
}
.subtitle {
font-size: 1.3rem;
color: var(--ifm-color-emphasis-800);
margin: 0;
line-height: 1.6;
font-weight: 500;
}
.decoration {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1;
pointer-events: none;
}
.circle1,
.circle2,
.circle3 {
position: absolute;
border-radius: 50%;
background: radial-gradient(
circle,
rgba(var(--ifm-color-primary-rgb), 0.1) 0%,
transparent 70%
);
}
.circle1 {
width: 400px;
height: 400px;
top: -200px;
left: -100px;
animation: float 20s ease-in-out infinite;
}
.circle2 {
width: 300px;
height: 300px;
bottom: -150px;
right: -50px;
animation: float 15s ease-in-out infinite reverse;
}
.circle3 {
width: 250px;
height: 250px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
animation: pulse 10s ease-in-out infinite;
}
@keyframes float {
0%,
100% {
transform: translate(0, 0) scale(1);
}
50% {
transform: translate(30px, -30px) scale(1.1);
}
}
@keyframes pulse {
0%,
100% {
transform: translate(-50%, -50%) scale(1);
opacity: 0.5;
}
50% {
transform: translate(-50%, -50%) scale(1.2);
opacity: 0.3;
}
}
@media (max-width: 996px) {
.hero {
padding: 3rem 1.5rem;
margin: -1rem -1rem 3rem -1rem;
}
.title {
font-size: 2.5rem;
}
.subtitle {
font-size: 1.1rem;
}
.circle1 {
width: 300px;
height: 300px;
}
.circle2 {
width: 200px;
height: 200px;
}
.circle3 {
width: 150px;
height: 150px;
}
}
@media (max-width: 768px) {
.hero {
padding: 2rem 1rem;
}
.title {
font-size: 2rem;
}
.subtitle {
font-size: 1rem;
}
}

View File

@@ -0,0 +1,228 @@
import GitHubStars from '@site/src/components/GitHubStars'
import Link from '@docusaurus/Link'
import React from 'react'
import clsx from 'clsx'
import styles from './styles.module.css'
interface ProjectCardProps {
aiPowered?: boolean
author?: string
authorLink?: string
children?: React.ReactNode
description: string
featured?: boolean
githubRepo?: string
id?: string
image?: string
links?: {
docs?: string
github?: string
telegram?: string
website?: string
}
tags?: string[]
title: string
}
export default function ProjectCard({
title,
description,
author,
authorLink,
image,
links,
featured = false,
aiPowered = false,
githubRepo,
id,
children
}: ProjectCardProps) {
const [isModalOpen, setIsModalOpen] = React.useState(false)
const [isClosing, setIsClosing] = React.useState(false)
const projectId =
id ||
title
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-+|-+$/g, '')
const handleClose = () => {
setIsClosing(true)
setTimeout(() => {
setIsModalOpen(false)
setIsClosing(false)
}, 200)
}
return (
<>
<div className={clsx(styles.projectCard, featured && styles.featured)} id={projectId}>
<div className={styles.badgesContainer}>
{aiPowered && (
<div
className={styles.aiPoweredBadge}
data-tooltip="Author reported that AI was used in development of this product"
>
<svg fill="currentColor" height="16" viewBox="0 0 24 24" width="16">
<path d="M12 2L2 7L12 12L22 7L12 2Z" />
<path d="M2 17L12 22L22 17V12L12 17L2 12V17Z" opacity="0.7" />
</svg>
<span>AI</span>
</div>
)}
{githubRepo && links?.github && (
<Link className={styles.starsBadge} to={links.github}>
<GitHubStars repo={githubRepo} />
</Link>
)}
</div>
{image && (
<div className={styles.imageContainer}>
<img alt={title} className={styles.projectImage} src={image} />
</div>
)}
<div className={styles.cardContent}>
<div className={styles.cardHeader}>
<div className={styles.titleWrapper}>
<h3 className={styles.projectTitle}>
<a className={styles.projectAnchor} href={`#${projectId}`}>
{title}
</a>
</h3>
{author && (
<div className={styles.authorInfo}>
<span className={styles.byText}>by</span>
{authorLink ? (
<Link className={styles.authorLink} to={authorLink}>
{author}
</Link>
) : (
<span className={styles.authorName}>{author}</span>
)}
</div>
)}
</div>
{featured && <span className={styles.featuredBadge}> Featured</span>}
</div>
<p className={styles.description}>{description}</p>
{(links || children) && (
<div className={styles.links}>
{children && (
<button
className={clsx(styles.link, styles.installButton)}
onClick={() => setIsModalOpen(true)}
type="button"
>
<svg
fill="currentColor"
height="16"
viewBox="0 0 16 16"
width="16"
>
<path d="M1 2.828c.885-.37 2.154-.769 3.388-.893 1.33-.134 2.458.063 3.112.752v9.746c-.935-.53-2.12-.603-3.213-.493-1.18.12-2.37.461-3.287.811V2.828zm7.5-.141c.654-.689 1.782-.886 3.112-.752 1.234.124 2.503.523 3.388.893v9.923c-.918-.35-2.107-.692-3.287-.81-1.094-.111-2.278-.039-3.213.492V2.687zM8 1.783C7.015.936 5.587.81 4.287.94c-1.514.153-3.042.672-3.994 1.105A.5.5 0 0 0 0 2.5v11a.5.5 0 0 0 .707.455c.882-.4 2.303-.881 3.68-1.02 1.409-.142 2.59.087 3.223.877a.5.5 0 0 0 .78 0c.633-.79 1.814-1.019 3.222-.877 1.378.139 2.8.62 3.681 1.02A.5.5 0 0 0 16 13.5v-11a.5.5 0 0 0-.293-.455c-.952-.433-2.48-.952-3.994-1.105C10.413.809 8.985.936 8 1.783z" />
</svg>
Features & More Info
</button>
)}
{links?.github && (
<Link
className={clsx(styles.link, styles.githubLink)}
to={links.github}
>
<svg
fill="currentColor"
height="16"
viewBox="0 0 16 16"
width="16"
>
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z" />
</svg>
GitHub
</Link>
)}
{links?.docs && (
<Link
className={clsx(styles.link, styles.docsLink)}
to={links.docs}
>
<svg
fill="currentColor"
height="16"
viewBox="0 0 16 16"
width="16"
>
<path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v13.5a.5.5 0 0 1-.777.416L8 13.101l-5.223 2.815A.5.5 0 0 1 2 15.5V2zm2-1a1 1 0 0 0-1 1v12.566l4.723-2.482a.5.5 0 0 1 .554 0L13 14.566V2a1 1 0 0 0-1-1H4z" />
</svg>
Docs
</Link>
)}
{links?.telegram && (
<Link
className={clsx(styles.link, styles.telegramLink)}
to={links.telegram}
>
<svg
fill="currentColor"
height="16"
viewBox="0 0 16 16"
width="16"
>
<path d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zM8.287 5.906c-.778.324-2.334.994-4.666 2.01-.378.15-.577.298-.595.442-.03.243.275.339.69.47l.175.055c.408.133.958.288 1.243.294.26.006.549-.1.868-.32 2.179-1.471 3.304-2.214 3.374-2.23.05-.012.12-.026.166.016.047.041.042.12.037.141-.03.129-1.227 1.241-1.846 1.817-.193.18-.33.307-.358.336a8.154 8.154 0 0 1-.188.186c-.38.366-.664.64.015 1.088.327.216.589.393.85.571.284.194.568.387.936.629.093.06.183.125.27.187.331.236.63.448.997.414.214-.02.435-.22.547-.82.265-1.417.786-4.486.906-5.751a1.426 1.426 0 0 0-.013-.315.337.337 0 0 0-.114-.217.526.526 0 0 0-.31-.093c-.3.005-.763.166-2.984 1.09z" />
</svg>
Telegram
</Link>
)}
{links?.website && (
<Link
className={clsx(styles.link, styles.websiteLink)}
to={links.website}
>
<svg
fill="currentColor"
height="16"
viewBox="0 0 16 16"
width="16"
>
<path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8zm7.5-6.923c-.67.204-1.335.82-1.887 1.855A7.97 7.97 0 0 0 5.145 4H7.5V1.077zM4.09 4a9.267 9.267 0 0 1 .64-1.539 6.7 6.7 0 0 1 .597-.933A7.025 7.025 0 0 0 2.255 4H4.09zm-.582 3.5c.03-.877.138-1.718.312-2.5H1.674a6.958 6.958 0 0 0-.656 2.5h2.49zM4.847 5a12.5 12.5 0 0 0-.338 2.5H7.5V5H4.847zM8.5 5v2.5h2.99a12.495 12.495 0 0 0-.337-2.5H8.5zM4.51 8.5a12.5 12.5 0 0 0 .337 2.5H7.5V8.5H4.51zm3.99 0V11h2.653c.187-.765.306-1.608.338-2.5H8.5zM5.145 12c.138.386.295.744.468 1.068.552 1.035 1.218 1.65 1.887 1.855V12H5.145zm.182 2.472a6.696 6.696 0 0 1-.597-.933A9.268 9.268 0 0 1 4.09 12H2.255a7.024 7.024 0 0 0 3.072 2.472zM3.82 11a13.652 13.652 0 0 1-.312-2.5h-2.49c.062.89.291 1.733.656 2.5H3.82zm6.853 3.472A7.024 7.024 0 0 0 13.745 12H11.91a9.27 9.27 0 0 1-.64 1.539 6.688 6.688 0 0 1-.597.933zM8.5 12v2.923c.67-.204 1.335-.82 1.887-1.855.173-.324.33-.682.468-1.068H8.5zm3.68-1h2.146c.365-.767.594-1.61.656-2.5h-2.49a13.65 13.65 0 0 1-.312 2.5zm2.802-3.5a6.959 6.959 0 0 0-.656-2.5H12.18c.174.782.282 1.623.312 2.5h2.49zM11.27 2.461c.247.464.462.98.64 1.539h1.835a7.024 7.024 0 0 0-3.072-2.472c.218.284.418.598.597.933zM10.855 4a7.966 7.966 0 0 0-.468-1.068C9.835 1.897 9.17 1.282 8.5 1.077V4h2.355z" />
</svg>
Website
</Link>
)}
</div>
)}
</div>
</div>
{isModalOpen && children && (
<div
className={`${styles.modalOverlay} ${isClosing ? styles.closing : ''}`}
onClick={handleClose}
>
<div
className={`${styles.modalContent} ${isClosing ? styles.closing : ''}`}
onClick={(e) => e.stopPropagation()}
>
<div className={styles.modalHeader}>
<h2 className={styles.modalTitle}>
<span className={styles.installIcon}>🚀</span>
Features & More Info
</h2>
<button
className={styles.closeButton}
onClick={handleClose}
type="button"
>
</button>
</div>
<div className={styles.modalBody}>{children}</div>
</div>
</div>
)}
</>
)
}

View File

@@ -0,0 +1,654 @@
.projectCard {
background: var(--ifm-card-background-color);
border: 1px solid var(--ifm-color-emphasis-200);
border-radius: 12px;
overflow: visible;
transition: all 0.3s ease;
height: 100%;
display: flex;
flex-direction: column;
position: relative;
max-width: 100%;
scroll-margin-top: 100px;
}
.projectCard:hover {
transform: translateY(-4px);
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15);
border-color: var(--ifm-color-primary);
}
[data-theme='dark'] .projectCard:hover {
box-shadow: 0 12px 24px rgba(0, 0, 0, 0.4);
}
.featured {
border: 2px solid var(--ifm-color-primary);
background: linear-gradient(
135deg,
var(--ifm-card-background-color) 0%,
rgba(var(--ifm-color-primary-rgb), 0.03) 100%
);
}
.badgesContainer {
position: absolute;
top: 12px;
right: 12px;
z-index: 10;
display: flex;
gap: 0.5rem;
}
.aiPoweredBadge {
display: flex;
align-items: center;
gap: 0.35rem;
padding: 0.4rem 0.75rem;
background: var(--ifm-color-emphasis-200);
color: var(--ifm-color-emphasis-800);
border: 1px solid var(--ifm-color-emphasis-300);
border-radius: 6px;
font-size: 0.7rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.5px;
cursor: help;
transition: all 0.2s ease;
}
.starsBadge {
display: flex;
align-items: center;
padding: 0.45rem 0.85rem;
background: #24292e;
color: white;
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 6px;
font-size: 0.8rem;
font-weight: 600;
transition: all 0.2s ease;
text-decoration: none;
cursor: pointer;
}
.starsBadge:hover {
background: #1a1e22;
border-color: rgba(255, 255, 255, 0.2);
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
color: white;
text-decoration: none;
}
.aiPoweredBadge::before {
content: attr(data-tooltip);
position: absolute;
bottom: calc(100% + 10px);
right: 0;
padding: 0.6rem 0.9rem;
background: var(--ifm-color-emphasis-900);
color: white;
border-radius: 6px;
font-size: 0.8rem;
font-weight: 500;
text-transform: none;
letter-spacing: normal;
white-space: nowrap;
opacity: 0;
pointer-events: none;
transition:
opacity 0.2s ease,
transform 0.2s ease;
transform: translateY(5px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
z-index: 1000;
}
.aiPoweredBadge::after {
content: '';
position: absolute;
bottom: calc(100% + 2px);
right: 20px;
border: 6px solid transparent;
border-top-color: var(--ifm-color-emphasis-900);
opacity: 0;
pointer-events: none;
transition: opacity 0.2s ease;
}
.aiPoweredBadge:hover::before {
opacity: 1;
transform: translateY(0);
}
.aiPoweredBadge:hover::after {
opacity: 1;
}
.aiPoweredBadge:hover {
background: var(--ifm-color-emphasis-300);
border-color: var(--ifm-color-emphasis-400);
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.aiPoweredBadge svg {
width: 13px;
height: 13px;
opacity: 0.8;
}
[data-theme='dark'] .aiPoweredBadge::before {
background: var(--ifm-color-emphasis-100);
color: var(--ifm-color-emphasis-900);
}
[data-theme='dark'] .aiPoweredBadge::after {
border-top-color: var(--ifm-color-emphasis-100);
}
[data-theme='dark'] .aiPoweredBadge {
background: var(--ifm-color-emphasis-300);
color: var(--ifm-color-emphasis-900);
border-color: var(--ifm-color-emphasis-400);
}
[data-theme='dark'] .aiPoweredBadge:hover {
background: var(--ifm-color-emphasis-400);
border-color: var(--ifm-color-emphasis-500);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
[data-theme='dark'] .starsBadge {
background: #2d333b;
color: white;
border-color: rgba(255, 255, 255, 0.15);
}
[data-theme='dark'] .starsBadge:hover {
background: #373e47;
border-color: rgba(255, 255, 255, 0.25);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
color: white;
}
@media (max-width: 768px) {
.badgesContainer {
top: 8px;
right: 8px;
gap: 0.4rem;
}
.aiPoweredBadge {
padding: 0.3rem 0.55rem;
font-size: 0.65rem;
}
.aiPoweredBadge svg {
width: 11px;
height: 11px;
}
.starsBadge {
padding: 0.3rem 0.55rem;
font-size: 0.7rem;
}
}
.imageContainer {
width: 100%;
height: 280px;
overflow: hidden;
background: var(--ifm-color-emphasis-100);
display: flex;
align-items: center;
justify-content: center;
border-radius: 12px 12px 0 0;
}
.projectImage {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center;
transition: transform 0.3s ease;
}
.projectCard:hover .projectImage {
transform: scale(1.05);
}
.cardContent {
padding: 1.5rem;
flex: 1;
display: flex;
flex-direction: column;
gap: 1rem;
}
.cardHeader {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 0.5rem;
}
.titleWrapper {
flex: 1;
display: flex;
flex-direction: column;
gap: 0.6rem;
}
.projectTitle {
margin: 0;
font-size: 1.3rem;
font-weight: 700;
color: var(--ifm-heading-color);
line-height: 1.3;
}
.projectAnchor {
color: inherit;
text-decoration: none;
}
.projectAnchor:hover {
color: var(--ifm-color-primary);
text-decoration: none;
}
.featuredBadge {
display: inline-flex;
align-items: center;
padding: 0.25rem 0.75rem;
background: var(--ifm-color-primary);
color: white;
border-radius: 12px;
font-size: 0.75rem;
font-weight: 600;
white-space: nowrap;
flex-shrink: 0;
}
.authorInfo {
display: flex;
align-items: center;
gap: 0.4rem;
font-size: 0.9rem;
}
.byText {
color: var(--ifm-color-emphasis-600);
font-weight: 400;
}
.authorLink {
color: var(--ifm-color-primary);
text-decoration: none;
font-weight: 600;
transition: all 0.2s ease;
position: relative;
}
.authorLink::after {
content: '';
position: absolute;
bottom: -2px;
left: 0;
width: 0;
height: 2px;
background: var(--ifm-color-primary);
transition: width 0.2s ease;
}
.authorLink:hover::after {
width: 100%;
}
.authorLink:hover {
text-decoration: none;
color: var(--ifm-color-primary-dark);
}
.authorName {
color: var(--ifm-color-emphasis-800);
font-weight: 600;
}
[data-theme='dark'] .byText {
color: var(--ifm-color-emphasis-500);
}
[data-theme='dark'] .authorName {
color: var(--ifm-color-emphasis-700);
}
.description {
flex: 1;
margin: 0;
color: var(--ifm-color-emphasis-800);
line-height: 1.6;
font-size: 0.95rem;
}
.tags {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.tag {
display: inline-block;
padding: 0.25rem 0.75rem;
background: var(--ifm-color-emphasis-100);
color: var(--ifm-color-emphasis-800);
border-radius: 6px;
font-size: 0.8rem;
font-weight: 500;
transition: background 0.2s ease;
}
.tag:hover {
background: var(--ifm-color-emphasis-200);
}
.links {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
margin-top: auto;
padding-top: 0.5rem;
border-top: 1px solid var(--ifm-color-emphasis-200);
text-decoration: none;
}
.link {
display: inline-flex;
align-items: center;
gap: 0.4rem;
padding: 0.5rem 1rem;
border-radius: 6px;
font-size: 0.9rem;
font-weight: 500;
text-decoration: none;
transition: all 0.2s ease;
}
.githubLink {
background: #24292e;
color: white;
}
.githubLink:hover {
background: #1a1e22;
color: white;
text-decoration: none;
box-shadow: 0 2px 8px rgba(36, 41, 46, 0.3);
}
[data-theme='dark'] .githubLink {
background: #2d333b;
color: white;
}
[data-theme='dark'] .githubLink:hover {
background: #404852;
color: white;
text-decoration: none;
box-shadow: 0 2px 8px rgba(64, 72, 82, 0.3);
}
.docsLink {
background: var(--ifm-color-primary-lightest);
color: var(--ifm-color-primary-darker);
}
.docsLink:hover {
background: var(--ifm-color-primary);
color: white;
text-decoration: none;
}
.telegramLink {
background: #0088cc;
color: white;
}
.telegramLink:hover {
background: #006699;
color: white;
text-decoration: none;
box-shadow: 0 2px 8px rgba(0, 136, 204, 0.3);
}
[data-theme='dark'] .telegramLink {
background: #0088cc;
color: white;
}
[data-theme='dark'] .telegramLink:hover {
background: #33adff;
color: white;
}
.websiteLink {
background: #0097a7;
color: white;
}
.websiteLink:hover {
background: #00838f;
color: white;
text-decoration: none;
box-shadow: 0 2px 8px rgba(0, 151, 167, 0.3);
}
[data-theme='dark'] .websiteLink {
background: #00acc1;
color: white;
}
[data-theme='dark'] .websiteLink:hover {
background: #00bcd4;
color: white;
}
.installButton {
background: linear-gradient(
135deg,
var(--ifm-color-primary) 0%,
var(--ifm-color-primary-dark) 100%
);
color: white;
border: none;
cursor: pointer;
font-weight: 600;
}
.installButton:hover {
background: linear-gradient(
135deg,
var(--ifm-color-primary-dark) 0%,
var(--ifm-color-primary-darker) 100%
);
color: white;
text-decoration: none;
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(var(--ifm-color-primary-rgb), 0.3);
}
/* Modal styles */
.modalOverlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
backdrop-filter: blur(4px);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
padding: 1rem;
animation: fadeIn 0.2s ease;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
.modalOverlay.closing {
animation: fadeOut 0.2s ease;
}
.modalContent {
background: var(--ifm-card-background-color);
border-radius: 16px;
max-width: 800px;
width: 100%;
max-height: 85vh;
overflow: hidden;
display: flex;
flex-direction: column;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
animation: slideUp 0.3s ease;
}
@keyframes slideUp {
from {
transform: translateY(20px);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
@keyframes slideDown {
from {
transform: translateY(0);
opacity: 1;
}
to {
transform: translateY(20px);
opacity: 0;
}
}
.modalContent.closing {
animation: slideDown 0.2s ease;
}
.modalHeader {
display: flex;
justify-content: space-between;
align-items: center;
padding: 1.5rem 2rem;
border-bottom: 1px solid var(--ifm-color-emphasis-200);
background: var(--ifm-color-emphasis-100);
}
.modalTitle {
margin: 0;
font-size: 1.3rem;
font-weight: 700;
color: var(--ifm-heading-color);
display: flex;
align-items: center;
gap: 0.75rem;
}
.installIcon {
font-size: 1.5rem;
line-height: 1;
}
.closeButton {
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
background: transparent;
border: none;
border-radius: 6px;
font-size: 1.5rem;
cursor: pointer;
color: var(--ifm-color-emphasis-700);
transition: all 0.2s ease;
flex-shrink: 0;
}
.closeButton:hover {
background: var(--ifm-color-emphasis-200);
color: var(--ifm-color-emphasis-900);
}
.modalBody {
padding: 2rem;
overflow-y: auto;
flex: 1;
background: var(--ifm-color-emphasis-100);
}
[data-theme='dark'] .modalOverlay {
background: rgba(0, 0, 0, 0.85);
}
[data-theme='dark'] .closeButton:hover {
background: var(--ifm-color-emphasis-300);
}
@media (max-width: 768px) {
.cardContent {
padding: 1rem;
}
.projectTitle {
font-size: 1.1rem;
}
.imageContainer {
height: 200px;
}
.modalContent {
max-width: 100%;
max-height: 90vh;
border-radius: 12px;
}
.modalHeader {
padding: 1rem 1.5rem;
}
.modalTitle {
font-size: 1.1rem;
}
.installIcon {
font-size: 1.25rem;
}
.modalBody {
padding: 1.5rem;
}
}

View File

@@ -0,0 +1,16 @@
import React from 'react'
import styles from './styles.module.css'
interface ProjectsGridProps {
children: React.ReactNode
columns?: 1 | 2 | 3
}
export default function ProjectsGrid({ children, columns = 3 }: ProjectsGridProps) {
return (
<div className={styles.projectsGrid} data-columns={columns}>
{children}
</div>
)
}

View File

@@ -0,0 +1,40 @@
.projectsGrid {
display: grid;
gap: 2rem;
margin: 2rem 0 4rem 0;
}
.projectsGrid[data-columns='1'] {
grid-template-columns: 1fr;
max-width: 800px;
margin-left: auto;
margin-right: auto;
}
.projectsGrid[data-columns='2'] {
grid-template-columns: repeat(2, 1fr);
}
.projectsGrid[data-columns='3'] {
grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 996px) {
.projectsGrid[data-columns='2'],
.projectsGrid[data-columns='3'] {
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
}
@media (max-width: 768px) {
.projectsGrid {
gap: 1.5rem;
margin: 1.5rem 0 3rem 0;
}
.projectsGrid[data-columns='1'],
.projectsGrid[data-columns='2'],
.projectsGrid[data-columns='3'] {
grid-template-columns: 1fr;
}
}

View File

@@ -0,0 +1,29 @@
import React from 'react'
import styles from './styles.module.css'
interface Stat {
icon?: string
label: string
value: string
}
interface StatsBarProps {
stats: Stat[]
}
export default function StatsBar({ stats }: StatsBarProps) {
return (
<div className={styles.statsBar}>
{stats.map((stat, index) => (
<div className={styles.statItem} key={index}>
{stat.icon && <span className={styles.icon}>{stat.icon}</span>}
<div className={styles.statContent}>
<div className={styles.value}>{stat.value}</div>
<div className={styles.label}>{stat.label}</div>
</div>
</div>
))}
</div>
)
}

View File

@@ -0,0 +1,74 @@
.statsBar {
display: flex;
justify-content: center;
gap: 3rem;
padding: 2rem;
margin: 3rem 0;
background: var(--ifm-color-emphasis-100);
border-radius: 12px;
flex-wrap: wrap;
}
.statItem {
display: flex;
align-items: center;
gap: 1rem;
}
.icon {
font-size: 2.5rem;
line-height: 1;
}
.statContent {
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.value {
font-size: 2rem;
font-weight: 800;
background: linear-gradient(
120deg,
var(--ifm-color-primary) 0%,
var(--ifm-color-primary-dark) 100%
);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
line-height: 1;
}
.label {
font-size: 0.9rem;
color: var(--ifm-color-emphasis-700);
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.5px;
}
@media (max-width: 768px) {
.statsBar {
gap: 2rem;
padding: 1.5rem;
}
.statItem {
flex-direction: column;
text-align: center;
gap: 0.5rem;
}
.icon {
font-size: 2rem;
}
.value {
font-size: 1.5rem;
}
.label {
font-size: 0.8rem;
}
}

View File

@@ -1,7 +1,23 @@
import FeatureHighlight from '@site/src/components/FeatureHighlight'
import CategorySection from '@site/src/components/CategorySection'
import ProjectsGrid from '@site/src/components/ProjectsGrid'
import HeroSection from '@site/src/components/HeroSection'
import CategoryNav from '@site/src/components/CategoryNav'
import GitHubStars from '@site/src/components/GitHubStars'
import ProjectCard from '@site/src/components/ProjectCard'
import MDXComponents from '@theme-original/MDXComponents'
import StatsBar from '@site/src/components/StatsBar'
import Button from '@site/src/components/Button'
export default {
...MDXComponents,
Button
Button,
CategoryNav,
GitHubStars,
ProjectCard,
ProjectsGrid,
CategorySection,
HeroSection,
StatsBar,
FeatureHighlight
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB