Files
sub-router/CLAUDE.md
2026-03-31 13:11:54 +08:00

3.4 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

Sub Router is a Surge proxy subscription management system. It aggregates nodes from upstream subscriptions, allows adding custom static nodes and rules, and generates a combined Surge configuration file served at /surge.

Commands

# Development (starts both server and web dev server concurrently)
npm run dev

# Server only (port 3456, hot-reload via tsx watch)
npm run dev:server

# Frontend only (port 5173, proxies /api and /surge to :3456)
npm run dev:web

# Build frontend for production
npm run build:web

# Production start (serves built frontend + API on port 3456)
npm run start

# Type check frontend
cd web && npx tsc --noEmit

# Docker
docker compose up -d

Architecture

Monorepo with NPM Workspaces: server/ (Express + better-sqlite3) and web/ (React + Vite). In production, Express serves the built frontend static files and API from a single port (3456).

Key data flow

  1. User adds upstream subscription URLs → backend fetches and parses nodes into fetched_nodes table
  2. User adds static nodes via URI (ss://, vmess://, trojan://) → parsed and stored in static_nodes table
  3. GET /surgegenerator.ts rebuilds the Surge config:
    • Takes first enabled subscription's raw_config as base template
    • Replaces [Proxy] section entirely with only enabled nodes (static first, then fetched)
    • Rebuilds [Proxy Group] select groups with only enabled node names
    • Injects user rules at the top of [Rule] section
    • Rewrites #!MANAGED-CONFIG URL

Auth model

/surge endpoint requires no auth (for Surge client access). All /api/* routes require Bearer token auth, except /api/auth/login and /api/auth/status. Password is stored in the config table. Token is the raw password sent via Authorization: Bearer <password>.

Database

SQLite with WAL mode at server/data/sub-router.db. Five tables: subscriptions, fetched_nodes (FK to subscriptions, CASCADE delete), static_nodes, rules, config (KV store for password).

Parsers (server/src/parsers/)

Convert protocol URIs to Surge proxy lines. Each parser returns { name, type, server, port, surgeLine }. The subscription content parser handles both base64-encoded URI lists and raw Surge config format (extracting from [Proxy] section).

  • SS: No TLS wrapping (Surge doesn't support SS over TLS; SS 2022 has built-in encryption)
  • VMess/Trojan: skip-cert-verify=false (strict TLS verification)

Frontend

Five panels: Subscriptions (CRUD + fetch trigger), Static Nodes (paste URI, custom naming, double-click to rename), Node Selector (per-subscription toggle with regex batch operations), Rules (CRUD + drag reorder), Output (subscription URL + config preview). Dark cyberpunk theme with CSS variables, JetBrains Mono font.

Route ordering matters

In server/src/routes/: specific paths like /reorder and /fetched/batch must be registered before parameterized /:id routes to avoid being captured by Express route matching.

Deployment

The Content-Disposition header on /surge controls the config profile name in Surge client (currently IPLC.MAX.conf). Docker mounts ./data volume for SQLite persistence. Certificate renewal uses acme.sh with dns_cf (Cloudflare DNS API validation).