Public status page for StealthSurf VPN. Polls GET /public/status every 60
seconds and shows:
- overall platform health (all operational / degraded / major outage),
- a soft red banner listing currently unavailable servers,
- a soft amber banner for planned maintenance,
- categories (countries, paid-options, private servers) as accordions — ones with incidents auto-expand,
- a live "Updated N seconds ago" timestamp.
The page:
- is public — no authorization required;
- is iOS-styled via VKUI (
platform="ios"); - supports light / dark via
prefers-color-scheme; - disables text selection (
user-select: none); - has a demo mode (
?demo=1) with a frozen snapshot.
- Vite + React 18
- TypeScript (strict)
@vkontakte/vkui(cssm build — only used-component CSS is shipped)@vkontakte/icons- Plain SCSS (sass-embedded, modern compiler API)
- Biome — formatter and linter
npm install
npm run dev # http://localhost:3100
npm run build # tsc -b && vite build → dist/
npm run preview # preview the built bundle
npm run format # Biome formatter
npm run lint # Biome linter
npm run typecheck # tsc --noEmit.env:
VITE_BACKEND_URL=https://api.stealthsurf.space/The GET /public/status endpoint is public — no tokens required.
Open http://localhost:3100/?demo=1 (or ?mock=1) to render src/mockStatus.ts
instead of hitting the API. The current mock showcases the planned-maintenance
banner.
src/
├── main.tsx # entry: ConfigProvider + AppRoot (iOS, light/dark)
├── App.tsx # polling, state, layout
├── api.ts # fetchPublicStatus + demo toggle
├── mockStatus.ts # frozen StatusSnapshot for demo mode
├── types.ts # shared domain types
├── components/
│ ├── StatusHero.tsx # title, description, status pill
│ ├── IncidentBanner.tsx # unified banner: down / maintenance
│ ├── CategoryAccordion.tsx
│ ├── ServerRow.tsx
│ ├── UpdatedAtLabel.tsx
│ └── FooterLinks.tsx # Telegram / Docs / Updates / GitHub / Support
├── utils/
│ ├── statusHelpers.ts
│ └── getRelativeTime.ts
└── assets/
└── global.scss # all `.status-*` styles, dark + mobile — single file
public/
├── favicon.ico
├── icon.png
├── share.jpg
├── manifest.json
└── robots.txt
index.html # meta tags, OG, Twitter card, Umami analytics
tsconfig.json # strict TypeScript
vite.config.mjs # Vite + VKUI cssm alias
biome.json
- Tabs for indentation, double quotes (enforced by Biome).
- Strict TypeScript. No
any.import typefor type-only imports. - Comments and JSDoc — English. UI strings — Russian.
- Colors come from
--vkui--color_*tokens so light/dark "just works". - After changes:
npm run format→npm run typecheck→npm run build.
AI-agent rules live in .claude/rules/:
code-style.mdproject-workflow.mdcomponent-patterns.mdapi-patterns.mdstyling.md
See also: