The marketing site and wiki for The Disruptor Proxy, a proxy client built on Xray-core.
This is the public, static marketing site — landing page, per-platform download hub, donation page, and a markdown-driven wiki. It has no backend and no build secrets; it's meant to be trivially deployable to any static host. The app itself is closed-source and lives in a separate private repository — this repo only covers the public-facing site.
- Frontend: AzerothJS (
.azerothcomponents, fine-grained reactivity) + Tailwind CSS v4, bundled with Vite. - Content: the wiki is markdown-driven — drop a
.mdfile incontent/wiki/, it's picked up automatically viaimport.meta.globand rendered throughmarked. No CMS, no build step per article. - i18n: 10 languages (English, Persian, Arabic, Chinese, Russian, Turkish, Hindi, Spanish, Vietnamese, Indonesian), including full RTL support for Persian and Arabic. Every UI string goes through a typed
Stringsinterface (src/lib/i18n/types.ts) — a locale missing a key is a build error, not a silent fallback to English. - Design system: ported directly from the desktop app's own OKLCH color tokens and glass-morphism utilities (
src/styles.css), so the site is visually consistent with the app it's promoting rather than a reinterpretation of it.
npm install
npm run dev
| Script | Does |
|---|---|
npm run dev |
Vite dev server |
npm run typecheck |
azeroth-tsc across the whole site |
npm run lint / npm run lint:fix |
ESLint (including .azeroth files) |
npm run build |
Typecheck plus production build |
npm run preview |
Preview the production build locally |
src/
app/ shell (nav bar + mobile drawer), router
pages/ one file per route (home, download, donate, wiki index, wiki article)
components/ shared UI primitives (cards, language menu, icon helpers)
stores/ app state (theme, locale) - createStore-based, one file per domain
lib/
i18n/ Strings interface + one dictionary file per locale
wiki/ markdown loading + frontmatter parsing
downloads.ts per-platform, multi-channel download data (single source of truth)
releases.ts shared GitHub Releases URL constant
assets/ logo, screenshots
content/
wiki/ one markdown file per wiki article, frontmatter for title/description
Drop a new file in content/wiki/, e.g. content/wiki/faq-billing.md:
---
title: Billing FAQ
description: One-line summary shown on the wiki index.
---
## Your first heading
Article body in plain markdown.The slug is the filename (faq-billing.md → /wiki/faq-billing). It shows up on the wiki index automatically — no route to register, no import to add. Article bodies are English-only for now; translating them into all 10 locales is real content work and hasn't been done yet, so non-English readers see an inline notice on the article page instead of silently reading English.
Every platform's download links live in one place, src/lib/downloads.ts — a platform can have multiple channels (e.g. Android lists both Google Play and a direct GitHub APK). A channel's href is null until a real, working URL exists for it; the UI never shows a live-looking link for something that doesn't exist yet. Flipping a channel live is a one-line edit in that file — both the home page's compact grid and the full /download page read from the same array, so there's nothing else to update.
The gallery on the home page is real screenshots of the app, captured against clean, seeded demo data — never a real user's actual servers or subscriptions.
Pushing to main builds and deploys automatically via .github/workflows/deploy-pages.yml (typecheck + lint + build, then publish dist/ to GitHub Pages). One manual, one-time step is required first: Settings → Pages → Source → GitHub Actions on this repo, or the workflow has nothing to deploy to.
The site is served from https://<org>.github.io/Wiki/, not the domain root, so two things are configured to match:
vite.config.ts'sbase: '/Wiki/'- every built asset URL carries this prefix.router.ts'sbase: '/Wiki'- every internal route and<Link to>stays base-relative in app code; the router adds/strips the prefix against the real browser URL automatically.
GitHub Pages has no server-side rewrites, so a direct load or refresh of a client-side route (e.g. /Wiki/wiki/installation) would otherwise 404 - the workflow copies the built index.html to 404.html, which Pages falls back to for any unmatched path, letting the app's own router take over from there.
If this ever moves to a custom domain, both base values go back to / (a domain serves from its own root, not a subpath) and the 404.html copy step is no longer strictly necessary, though it's harmless to leave in.
