### Build PasarGuard Subscription Template from Source Source: https://github.com/pasarguard/subscription-template/blob/main/README.md Clone the repository, install dependencies, and build the template. Use the built `index.html` for manual installation. ```sh git clone https://github.com/PasarGuard/subscription-template.git cd subscription-template bun install bun run build ``` ```sh sudo cp dist/index.html /var/lib/pasarguard/templates/subscription/index.html ``` -------------------------------- ### Install PasarGuard Subscription Template Source: https://github.com/pasarguard/subscription-template/blob/main/README.md Use this command to quickly install the subscription template. Specify the fallback language with `--lang` and optionally a version with `--version`. ```sh curl -fsSL https://raw.githubusercontent.com/PasarGuard/subscription-template/main/install.sh | sudo bash -s -- --lang fa ``` -------------------------------- ### Initialize Application Data Source: https://github.com/pasarguard/subscription-template/blob/main/index.html This JavaScript code initializes the global `__INITIAL_DATA__` object with user subscription information, links, and application details. It includes comprehensive user data, proxy settings, and next plan information. It also handles potential errors during data loading. ```javascript try { const obj = { user: {% if user %}{ 'id': user.id, 'username': user.username, 'status': user.status.name if user.status else 'active', 'used_traffic': user.used_traffic, 'lifetime_used_traffic': user.lifetime_used_traffic, 'data_limit': user.data_limit, 'data_limit_reset_strategy': user.data_limit_reset_strategy.name if user.data_limit_reset_strategy else 'no_reset', 'expire': user.expire.isoformat() if user.expire else None, 'on_hold_expire_duration': user.on_hold_expire_duration, 'on_hold_timeout': user.on_hold_timeout.isoformat() if user.on_hold_timeout else None, 'group_ids': user.group_ids, 'created_at': user.created_at.isoformat() if user.created_at else None, 'edit_at': user.edit_at.isoformat() if user.edit_at else None, 'online_at': user.online_at.isoformat() if user.online_at else None, 'proxy_settings': { 'vmess': {'id': user.proxy_settings.vmess.id|string} if user.proxy_settings.vmess else None, 'vless': {'id': user.proxy_settings.vless.id|string, 'flow': user.proxy_settings.vless.flow.name if user.proxy_settings.vless.flow else None} if user.proxy_settings.vless else None, 'trojan': {'password': user.proxy_settings.trojan.password} if user.proxy_settings.trojan else None, 'shadowsocks': {'password': user.proxy_settings.shadowsocks.password, 'method': user.proxy_settings.shadowsocks.method.name if user.proxy_settings.shadowsocks.method else None} if user.proxy_settings.shadowsocks else None, 'wireguard': {'public_key': user.proxy_settings.wireguard.public_key, 'peer_ips': user.proxy_settings.wireguard.peer_ips} if user.proxy_settings.wireguard else None, 'hysteria': {'auth': user.proxy_settings.hysteria.auth|string} if user.proxy_settings.hysteria else None }, 'next_plan': { 'user_template_id': user.next_plan.user_template_id, 'data_limit': user.next_plan.data_limit, 'expire': user.next_plan.expire, 'add_remaining_traffic': user.next_plan.add_remaining_traffic } if user.next_plan else None } %}{{ user_data | tojson | safe }}{% else %}null{% endif %}, links: {{ links | tojson | safe }}, apps: {% if apps %}{ set apps_data = [] }{% for app in apps %}{ if app %}{ set download_links_data = [] }{% for link in app.download_links %}{ if link %}{ set link_dict = { 'name': link.name, 'url': link.url, 'language': link.language } }{% set _ = download_links_data.append(link_dict) %} {% endif %} {% endfor %} {% set app_dict = { 'name': app.name, 'icon_url': app.icon_url, 'import_url': app.import_url, 'description': app.description, 'recommended': app.recommended, 'platform': app.platform, 'download_links': download_links_data } %} {% set _ = apps_data.append(app_dict) %} {% endif %} {% endfor %}{{ apps_data | tojson | safe }}{% else %}null{% endif %}, }; window.__INITIAL_DATA__ = obj; } catch (e) { console.warn("❌ Failed to load initial data:", e); window.__INITIAL_DATA__ = {}; } ``` -------------------------------- ### Manually Download Subscription Template Source: https://github.com/pasarguard/subscription-template/blob/main/README.md Download the latest version of the subscription template's HTML file to the specified directory. ```sh sudo mkdir -p /var/lib/pasarguard/templates/subscription sudo wget -O /var/lib/pasarguard/templates/subscription/index.html \ https://github.com/PasarGuard/subscription-template/releases/latest/download/index.html ``` -------------------------------- ### Customize Template Appearance Source: https://github.com/pasarguard/subscription-template/blob/main/README.md Set environment variables in `.env` to customize the template's primary colors and border radius before building. ```dotenv VITE_PRIMARY_COLOR_LIGHT=oklch(0.48 0.11 250) VITE_PRIMARY_COLOR_DARK=oklch(0.60 0.12 250) VITE_BORDER_RADIUS=0.65rem ``` -------------------------------- ### Configure PasarGuard for Custom Templates Source: https://github.com/pasarguard/subscription-template/blob/main/README.md Update the PasarGuard `.env` file to point to the custom templates directory and specify the subscription page template. ```dotenv CUSTOM_TEMPLATES_DIRECTORY="/var/lib/pasarguard/templates/" SUBSCRIPTION_PAGE_TEMPLATE="subscription/index.html" ``` -------------------------------- ### Restart PasarGuard Service Source: https://github.com/pasarguard/subscription-template/blob/main/README.md Restart the PasarGuard service to apply configuration changes. ```sh pasarguard restart ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.