High-performance prerendering microservice for Single Page Applications (SPA)
Botview makes your client-side rendered web applications visible to search engine crawlers and social media bots by providing fully rendered HTML content. Built with NestJS and Playwright, it delivers fast, reliable prerendering with minimal resource usage.
| Feature | Description |
|---|---|
| π SEO Optimization | Makes SPA content visible to search engine crawlers (Google, Bing, Yandex, etc.) |
| π± Social Media Ready | Enables proper link previews for Facebook, Twitter, Telegram, and other platforms |
| π Framework Agnostic | Works with React, Vue, Angular, Svelte, jQuery, StencilJS, and any JavaScript framework |
| β‘ High Performance | Lightweight Chromium engine with configurable resource blocking |
| π Basic Auth Support | Prerender pages behind HTTP Basic Authentication |
| π Prometheus Metrics | Built-in monitoring with /metrics endpoint |
| π― Custom Status Codes | Control HTTP response codes via meta tags |
| π³ Docker Ready | Production-ready container with multi-stage build |
- Quick Start
- API Reference
- Configuration
- Performance Optimization
- Monitoring
- Proxy Setup
- Troubleshooting
- Development
- Contributing
- License
# Run in foreground (for testing)
docker run -it --rm -p 3000:3000 mtsrus/botview
# Run in background (for production)
docker run -d --restart always -p 3000:3000 --name botview mtsrus/botviewOpen your browser or use curl:
curl http://localhost:3000/render/https://example.com/The response will contain the fully rendered HTML of the target page.
GET /render/{url}
| Parameter | Type | Description |
|---|---|---|
url |
string | URL-encoded target page to render |
Example:
# Render a page
curl http://localhost:3000/render/https://spa-website.com/products
# URL with query parameters (must be URL-encoded)
curl "http://localhost:3000/render/https://spa-website.com/search?q=test"Response:
- Content-Type:
text/html - Status Code:
200(or custom via meta tag)
Add a meta tag to your HTML to control the response status code:
<head>
<!-- Return 301 redirect status -->
<meta name="prerender-status" content="301" />
<!-- Return 404 not found -->
<meta name="prerender-status" content="404" />
</head>GET /metrics
Returns Prometheus-formatted metrics for monitoring.
All configuration is done via environment variables:
| Variable | Default | Description |
|---|---|---|
BOTVIEW_NAV_TIMEOUT |
30000 |
Maximum navigation timeout in milliseconds (docs) |
BOTVIEW_DEFAULT_TIMEOUT |
15000 |
Default timeout for page operations in milliseconds (docs) |
BOTVIEW_WAIT_UNTIL |
networkidle |
Wait condition: load, domcontentloaded, networkidle, or commit (docs) |
| Variable | Default | Description |
|---|---|---|
BOTVIEW_VIEWPORT |
360x640 |
Browser viewport size in WIDTHxHEIGHT format |
Example:
docker run -d -p 3000:3000 \
-e BOTVIEW_VIEWPORT="1920x1080" \
mtsrus/botviewImprove performance by blocking unnecessary resources:
| Variable | Default | Description |
|---|---|---|
BOTVIEW_BLOCK_IMAGES |
true |
Block image loading |
BOTVIEW_BLOCK_STYLESHEETS |
true |
Block CSS loading |
BOTVIEW_BLOCK_FONTS |
true |
Block font loading |
BOTVIEW_BLOCK_MEDIA |
true |
Block audio/video loading |
BOTVIEW_BLOCK_URLS |
https://an.yandex.ru, https://mc.yandex.ru |
URL prefixes to block (comma/space separated) |
BOTVIEW_BLOCK_URLS_REGEX |
`` | Regex patterns to block URLs (comma/space separated) |
Example:
docker run -d -p 3000:3000 \
-e BOTVIEW_BLOCK_URLS="https://google-analytics.com,https://facebook.com/tr" \
-e BOTVIEW_BLOCK_URLS_REGEX=".*\.ads\..*,.*tracking.*" \
mtsrus/botview| Variable | Default | Description |
|---|---|---|
BOTVIEW_BASIC_AUTHS |
`` | HTTP Basic Auth credentials |
Format: url:username:password (comma or space separated for multiple entries)
docker run -d -p 3000:3000 \
-e BOTVIEW_BASIC_AUTHS="https://protected.example.com:admin:secret123" \
mtsrus/botview| Variable | Default | Description |
|---|---|---|
BOTVIEW_LOG_LEVEL |
info |
Log verbosity: trace, debug, info, warn, error, fatal |
Botview comes pre-configured for optimal performance:
- β Images blocked (reduces bandwidth)
- β Stylesheets blocked (not needed for SEO)
- β Fonts blocked (reduces requests)
- β Media files blocked (reduces load time)
- β Yandex analytics blocked (prevents timeout issues)
Block specific URLs causing slowdowns:
# Block by URL prefix
-e BOTVIEW_BLOCK_URLS="https://slow-cdn.com,https://heavy-analytics.com"
# Block by regex pattern
-e BOTVIEW_BLOCK_URLS_REGEX=".*facebook.*widget.*,.*twitter.*embed.*"docker run -d --restart always -p 3000:3000 \
--memory="512m" \
--cpus="1" \
-e BOTVIEW_NAV_TIMEOUT=20000 \
-e BOTVIEW_DEFAULT_TIMEOUT=10000 \
-e BOTVIEW_LOG_LEVEL=warn \
--name botview \
mtsrus/botviewAccess metrics at http://localhost:3000/metrics:
curl http://localhost:3000/metricsAvailable metrics include:
- Node.js process metrics (memory, CPU, event loop)
- HTTP request metrics
- Garbage collection metrics
# prometheus.yml
scrape_configs:
- job_name: 'botview'
static_configs:
- targets: ['botview:3000']
metrics_path: '/metrics'Block the /metrics endpoint from external access in production:
location /metrics {
deny all;
# or allow only internal IPs
# allow 10.0.0.0/8;
# deny all;
}Configure your reverse proxy to route bot traffic to Botview.
location / {
set $prerender 0;
# Detect search engine and social media bots
if ($http_user_agent ~* "googlebot|bingbot|yandex|baiduspider|facebookexternalhit|twitterbot|telegrambot|linkedinbot|whatsapp|slackbot|discordbot|pinterest|applebot") {
set $prerender 1;
}
# Support for escaped fragment (legacy)
if ($args ~ "_escaped_fragment_") {
set $prerender 1;
}
# Don't prerender for Botview's own requests
if ($http_user_agent ~ "Prerender") {
set $prerender 0;
}
# Don't prerender static files
if ($uri ~ "\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|pdf|zip)$") {
set $prerender 0;
}
# Route to Botview for bots
if ($prerender = 1) {
rewrite (.*) /render/$scheme://$host$1 break;
proxy_pass http://botview:3000;
}
# Route to application for regular users
if ($prerender = 0) {
proxy_pass http://app:80;
}
}version: '3.8'
services:
app:
image: your-spa-app
ports:
- "80:80"
botview:
image: mtsrus/botview
restart: always
environment:
- BOTVIEW_LOG_LEVEL=info
ports:
- "3000:3000"
nginx:
image: nginx:alpine
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
ports:
- "443:443"
depends_on:
- app
- botviewSymptom: Requests timeout with "Leaked requests" in logs.
Cause: Some network requests don't complete, blocking page load.
Solution:
-
Check logs for leaked request URLs:
docker logs botview | grep "Leaked requests"
-
Block problematic URLs:
docker run -d -p 3000:3000 \ -e BOTVIEW_BLOCK_URLS="https://problematic-url.com" \ mtsrus/botview
Solution: Limit container memory and enable resource blocking:
docker run -d --memory="512m" \
-e BOTVIEW_BLOCK_IMAGES=true \
-e BOTVIEW_BLOCK_STYLESHEETS=true \
mtsrus/botviewEnable verbose logging:
docker run -it --rm -p 3000:3000 \
-e BOTVIEW_LOG_LEVEL=debug \
mtsrus/botview- Node.js 20+ (LTS recommended)
- npm 10+
# Clone repository
git clone https://github.com/MobileTeleSystems/botview.git
cd botview
# Install dependencies
npm install
# Run in development mode
npm run start:dev
# Run tests
npm test
# Run e2e tests
npm run test:e2e
# Build for production
npm run buildsrc/
βββ main.ts # Application entry point
βββ app.module.ts # Root NestJS module
βββ config.ts # Configuration management
βββ LogLevels.ts # Log level definitions
βββ controllers/
β βββ render-controller/ # Main render endpoint
β βββ metrics/ # Prometheus metrics endpoint
βββ services/
β βββ prerender.service.ts # Core prerendering logic
β βββ json-logger.service.ts # Structured JSON logging
βββ middleware/
β βββ RequestLoggerMiddleware.ts # Request logging
βββ models/
βββ LeakedRequests.ts # Request tracking model
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
- NestJS - Progressive Node.js framework
- Playwright - Reliable browser automation
- prom-client - Prometheus client for Node.js
Made with β€οΈ by MobileTeleSystems