The templates sat at the end of the syntax reference, behind five
collapsed sections, and the settings row and dialog were titled by the
bare name RoutingA. The dialog header now has a Templates menu next to
the reference button, in two groups: four full rule sets that replace the
rules after a confirmation (China direct; sites outside China through
the proxy; everything through the proxy; only common foreign services
through the proxy) and thirteen additions inserted at the cursor (ads,
streaming, social media, Telegram, AI, developer services, Chinese
endpoints of Apple/Google/Microsoft/Steam, Apple and Microsoft direct,
game platforms, speed tests, LAN, BitTorrent direct, block QUIC). The
reference is a syntax reference again. The settings row and the dialog
are titled "RoutingA rules" in every locale.
Every template uses only v2fly geosite/geoip categories and the three
built-in outbounds; a spec runs each through the editor's checker, and
on the VM each of the seventeen applied through the API while the core
was running.
The app bar's status button carries the spacing to the group button
itself: the class on the OutboundMenu component landed on the menu, not
its activator, so the two sat flush at every width below 1200.
The documentation site's domain has expired and its pages described a
2021 v2rayA. The page now carries its own docs, written against the
current code and shipped with the build, so what a user reads matches the
binary they run: quick start, transparent proxy, routing rules, inbounds
and sharing, flags and environment, troubleshooting. English and
Simplified Chinese; the other locales read the English text and say so.
The sections are Markdown under gui/src/docs/<locale>/, compiled to HTML
at build time by a small vite plugin around marked (a devDependency; the
bundle carries no parser) and loaded on demand, so the first load does not
grow. Headings get ids from their text. The flag table is not written by
hand: GET /api/params reads conf.Params' struct tags (id, short, default,
desc) through reflection, the same tags gonfig parses, and the page renders
it, so a new flag documents itself.
"#docs" and "#docs/<section>" open the page; the RoutingA dialog's help
button, the About page and small book icons in the settings sections and
the inbound dialogs point there instead of at the dead site or the wiki.
The navigation gains a fifth destination.
The toolchain of the rewrite: Vite with vite-plugin-pwa (autoUpdate,
/api/ never cached), vue-tsc, ESLint's flat config, Vitest with
happy-dom and a mount helper, an i18n check and a gzip size gate in CI,
Red Hat Text self-hosted under /static/fonts.
lucide-static's stylesheet declares eot, woff2, woff, ttf and a legacy SVG
font for all 2112 icons, so Vite copied every format into web/ and the
embedded binary grew from about 26 MB to 48 MB; the SVG font alone is 20 MB of
glyph outlines. The interface uses 44 icons.
A Vite plugin (gui/build/lucide-subset.mjs) scans src/ for icon names — class
usage, icon props, dialog options and the Buefy pack's internalIcons — subsets
lucide.woff2 to those glyphs with subset-font and serves the result as a
virtual stylesheet with the 8 KB font inlined. A name the font does not have
fails the build naming it, where it used to render an empty box.
lucide-static's font CSS references all five webfont formats (eot, ttf,
svg, woff, woff2), so Vite emitted ~23 MB of icon fonts into the web panel;
the SVG font alone was ~20.6 MB. All of them render the same glyphs.
scripts/lucide-font.mjs now regenerates src/assets/lucide-font.css from the
upstream CSS with a woff-only @font-face (woff is supported by every
browser since IE9) and runs automatically via the prebuild/preserve hooks,
so a lucide-static upgrade stays in sync. The build output drops from
~23 MB of font files to a single ~414 KB woff while keeping all icon
classes.