Lens

Created By
bysages2 months ago
A high-performance image proxy and web services toolkit built with modern TypeScript. Lens provides a comprehensive suite of web utilities including image processing, screenshot capture, font serving, and more.
Overview

Lens

GitHub GitHub Actions Contributor Covenant

A high-performance image proxy and web services toolkit built with modern TypeScript. Lens provides a comprehensive suite of web utilities including image processing, screenshot capture, font serving, and more.

🚀 Features

Core Services

  • 🖼️ Image Proxy: IPX-powered image processing with resize, format conversion, optimization
  • 📸 Screenshot Capture: Fast website screenshot service with resource optimization
  • 📄 Reader: Article content extraction (Markdown/HTML) with Readability
  • 🅰️ Font Service: Google Fonts compatible API with multiple providers
  • 🎨 Open Graph Images: Dynamic OG image generation
  • 🎯 Favicon Extraction: Smart favicon extraction from websites
  • 👤 Gravatar Proxy: Cached Gravatar avatar proxy with email or hash input
  • 🤖 MCP Server: Model Context Protocol server exposing all services as tools via JSON-RPC 2.0

Performance & Scalability

  • ⚡ Redis Caching: Redis-powered caching with 24-hour intelligent caching
  • 🚀 Resource Optimization: Optimized page loading with blocked unnecessary resources
  • 🛡️ Rate Limiting: Rate limiting for expensive operations
  • 🔄 Graceful Degradation: Automatic fallbacks for missing services

📦 Quick Start

Prerequisites

  • Node.js 22+
  • pnpm 10+ (recommended) or npm

Installation

# Clone the repository
git clone https://github.com/bysages/lens.git
cd lens

# Install dependencies
pnpm install

# Copy environment configuration
cp .env.example .env

Development

# Start development server
pnpm dev

# Build for production
pnpm build

# Preview production build
pnpm preview

The server will start on http://localhost:3000 by default.

🛠️ Configuration

Configuration

All configurations are optional and will gracefully degrade:

# Image proxy security
ALLOWED_DOMAINS=example.com,cdn.example.com

# Caching (significantly improves performance)
REDIS_URL=redis://localhost:6379

See .env.example for all available options.

📡 API Reference

All cached responses include X-Cache headers (HIT/MISS) and ETag headers for conditional 304 responses.

Images

Image Proxy

Transform and optimize images on-the-fly:

GET /img/{modifiers}/{image_url}

Examples:

# Resize to 300px width, convert to WebP
https://api.bysages.com/img/w_300,f_webp/https://example.com/image.jpg

# Create 200x200 square thumbnail
https://api.bysages.com/img/s_200x200,q_80/https://example.com/image.png

# Smart crop with high quality
https://api.bysages.com/img/w_400,h_300,c_fill,q_95/https://example.com/photo.jpg

Supported Modifiers:

  • w_XXX - Width
  • h_XXX - Height
  • s_XXXxYYY - Size (width x height)
  • f_FORMAT - Format (webp, jpg, png, avif)
  • q_XXX - Quality (1-100)
  • c_MODE - Crop mode (fill, fit, pad)

Performance Features:

  • Redis caching for optimal performance
  • Automatic format optimization and compression

Screenshot Capture

Capture website screenshots with Playwright-aligned options:

GET /screenshot?url={website_url}&options

Examples:

# Basic screenshot
https://api.bysages.com/screenshot?url=https://example.com

# JPEG with custom quality
https://api.bysages.com/screenshot?url=https://example.com&type=jpeg&quality=80

# Mobile screenshot with custom viewport
https://api.bysages.com/screenshot?url=https://example.com&width=375&height=667&mobile=true

# Full page capture
https://api.bysages.com/screenshot?url=https://example.com&fullPage=true

# Clip region (x,y,width,height)
https://api.bysages.com/screenshot?url=https://example.com&clip=0,0,400,300

# Transparent background
https://api.bysages.com/screenshot?url=https://example.com&omitBackground=true

# Disable animations for clean capture
https://api.bysages.com/screenshot?url=https://example.com&animations=disabled

# Custom CSS scale
https://api.bysages.com/screenshot?url=https://example.com&scale=css

# Inject custom stylesheet
https://api.bysages.com/screenshot?url=https://example.com&style=body{background:red}

Parameters:

ParameterDescriptionDefault
urlWebsite URL (required)-
widthViewport width (100-2560)1280
heightViewport height (100-1440)720
typeOutput format (png, jpeg)png
qualityImage quality, 1-100 (jpeg only)-
fullPageCapture full scrollable page (true/false)false
clipClip region as x,y,width,height-
omitBackgroundHide default white background (true/false, png only)false
scaleScreenshot scale (css for CSS pixels, device for device pixels)device
animationsAnimation handling (disabled or allow)allow
caretText caret (hide or initial)hide
styleCustom CSS stylesheet to apply-
timeoutNavigation timeout in ms (1000-30000)10000
mobileMobile viewport (true/false)false
darkModeDark mode (true/false)false
waitUntilNavigation wait condition (load, domcontentloaded, networkidle)domcontentloaded
delayAdditional delay in ms after page load (0-10000)-

Performance Notes:

  • Screenshots are cached for 1 day with rate limiting
  • Identical requests return cached results with sub-second response times
  • Resource optimization (blocking fonts, media, websockets) speeds up screenshot generation by 60-80%

Open Graph Images

Generate dynamic OG images:

GET /og?title={title}&description={description}

Examples:

# Basic OG image
https://api.bysages.com/og?title=Welcome&description=Get%20started%20with%20Lens

# Custom styling
https://api.bysages.com/og?title=Hello%20World&theme=dark&fontSize=72&width=1200&height=630

Caching:

  • Generated OG images are cached for 24 hours
  • Identical requests with same parameters return cached results instantly

Web Services

Reader (Content Extraction)

Extract rendered Markdown or HTML content from any URL:

GET /reader?url={website_url}&options

Examples:

# Extract rendered Markdown (default)
https://api.bysages.com/reader?url=https://github.com/bysages/lens

# Get HTML instead
https://api.bysages.com/reader?url=https://github.com/bysages/lens&format=html

# Wait for full page load
https://api.bysages.com/reader?url=https://github.com/bysages/lens&waitUntil=load

Parameters:

ParameterDescriptionDefault
urlWebsite URL (required)-
formatOutput format (html, markdown)markdown
waitUntilNavigation wait condition (load, domcontentloaded, networkidle)domcontentloaded
delayAdditional delay in ms after page load (0-10000)-
timeoutNavigation timeout in ms (1000-30000)10000

Favicon Extraction

Extract high-quality favicons:

GET /favicon?url={website_url}&size={size}

Examples:

# Extract favicon
https://api.bysages.com/favicon?url=github.com

# Custom size
https://api.bysages.com/favicon?url=github.com&size=64

Features:

  • Smart favicon extraction from multiple sources (PWA manifests, Apple touch icons, HTML tags)
  • 30-day server-side caching with ETag/304 support
  • Automatic fallback to generated favicon if none found

Gravatar Proxy

Get Gravatar avatars by email, MD5 hash, or path. All query parameters (except email/hash) are forwarded directly to Gravatar. You can switch from Gravatar by simply replacing the URL prefix.

GET /gravatar/{md5}?{gravatar_params}
GET /gravatar?email={email}
GET /gravatar?hash={md5}&{gravatar_params}

Examples:

# By path (drop-in replacement for Gravatar URLs)
https://api.bysages.com/gravatar/{md5}?size=200

# By email
https://api.bysages.com/gravatar?email=user@example.com

# By MD5 hash
https://api.bysages.com/gravatar?hash={md5}

# With Gravatar parameters
https://api.bysages.com/gravatar?email=user@example.com&size=200&default=identicon&rating=pg

Parameters:

  • {md5} - MD5 hash in URL path (drop-in replacement mode)
  • email - Email address (will be MD5 hashed automatically)
  • hash - Pre-computed MD5 hash (alternative to email)
  • All other parameters are forwarded to Gravatar API

MCP Server

Model Context Protocol server exposing all Lens services as tools via JSON-RPC 2.0 over HTTP.

POST /mcp

Setup with Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "lens": {
      "url": "https://api.bysages.com/mcp"
    }
  }
}

Available Tools:

ToolDescriptionReturns
readerExtract article content from a URL (Markdown/HTML)text
screenshotCapture a screenshot of a websiteimage
faviconExtract a website's faviconimage
ogGenerate a dynamic Open Graph imageimage
gravatarGet a Gravatar avatar by email or hashimage
imgTransform and optimize an image (resize, crop, convert)image

Fonts

Font Service

Google Fonts compatible API with both v1 and v2 endpoints:

GET /css?family={font_family}&display=swap
GET /css2?family={font_family}&display=swap

API Differences:

Feature/css (v1)/css2 (v2)
Multiple fontsfamily=A|B (pipe separator)family=A&family=B (repeated parameter)
Style syntaxFontName:400,700 (old)FontName:wght@400;700 (new, strict)
Variable fonts❌ Not supported✅ Full support with ranges (wght@200..900)
Base URLfonts.googleapis.com/cssfonts.googleapis.com/css2

Parameters:

  • family - Font family name (required)
  • display - Font display strategy (default: swap)
  • subset - Font subset (default: latin)
  • provider - Font provider (google, bunny, fontshare, fontsource, default: google)
  • proxy - Use proxy for font files (true/false, default: false)

Examples:

# Basic font (v1 API - pipe separator)
https://api.bysages.com/css?family=Roboto:wght@400;700|Open+Sans:wght@300;400;600&display=swap

# Multiple fonts (v2 API - repeated family parameter)
https://api.bysages.com/css2?family=Inter:wght@400;700&family=Roboto:wght@300;400&display=swap

# Variable fonts with weight range (v2 only)
https://api.bysages.com/css2?family=Inter:wght@200..800&display=swap

# Font metadata
https://api.bysages.com/webfonts?sort=popularity&category=sans-serif

Recommendations:

  • Use /css for legacy compatibility with old Google Fonts syntax
  • Use /css2 for modern applications with variable fonts and better optimization
  • Both endpoints support all font providers (Google, Bunny, Fontshare, Fontsource)

🏗️ Architecture

Lens is built with modern web standards and follows clean architecture principles:

Core Technologies

  • Runtime: Node.js 22+ with Nitro
  • Language: TypeScript with strict type safety
  • Image Proxy: IPX with Sharp
  • Browser Automation: Playwright with Crawlee BrowserPool
  • Caching: Redis with unstorage

Design Principles

  • KISS (Keep It Simple): Simple, focused solutions over complex abstractions
  • DRY (Don't Repeat Yourself): Shared utilities and configurations
  • Graceful Degradation: Fallbacks for missing dependencies
  • Type Safety: Comprehensive TypeScript coverage
  • Performance First: Optimized for speed and efficiency

🚀 Deployment

Prerequisites

  • Node.js 22+ runtime
  • pnpm 10+ package manager
  • Redis (optional, for distributed caching)

Production Deployment

# Build the application
pnpm run build

# Start production server
pnpm run preview

Option 1: Using Docker Compose

# Copy environment variables
cp .env.example .env

# Edit .env file to configure your settings
# nano .env

# Start the application
docker-compose up -d

# View logs
docker-compose logs -f app

# Stop the application
docker-compose down

The application will be available at http://localhost:3000

The stack includes:

  • Lens application on port 3000
  • Redis for distributed caching (optional but recommended)

Option 2: Using Docker Run

# Pull the official image
docker pull bysages/lens:latest

# Run container with host network (recommended for accurate IP logging)
docker run -d \
  --name lens \
  --network host \
  --env-file .env \
  --restart unless-stopped \
  bysages/lens:latest

# View logs
docker logs -f lens

# Stop the container
docker stop lens
docker rm lens

Option 3: Build from Source

# Build Docker image
docker build -t lens .

# Run container
docker run -d \
  --name lens \
  --network host \
  --env-file .env \
  --restart unless-stopped \
  lens

Environment Variables

All configurations are optional:

# Image Proxy Security
ALLOWED_DOMAINS=example.com,cdn.example.com

# Caching (significantly improves performance)
REDIS_URL=redis://localhost:6379

See .env.example for all available options.

📄 License

MIT License - see LICENSE file for details.


Built with ❤️ by By Sages

Server Config

{
  "mcpServers": {
    "lens": {
      "url": "https://api.bysages.com/mcp"
    }
  }
}
Project Info
Created At
2 months ago
Updated At
a month ago
Author Name
bysages
Star
-
Language
-
License
-
Category
Tags

Recommend Servers

View All
Alloy

2 days ago
Bring your real authenticated browser session to AI coding agents. Local-first MCP server + Chrome MV3 extension. No cloud. No telemetry.
@Cubenest

peek records the user's actual logged-in browser (DOM via rrweb, console events, network metadata, optional response bodies via opt-in Deep capture) through a Chrome MV3 extension. The extension ships events through a native-messaging stdio bridge to a local MCP server (peek-mcp), which persists them to a SQLite database at ~/.peek/sessions.db. AI coding agents (Claude Code, Cursor, Cline, Windsurf) read sessions from the database via 10 MCP tools: Tool What it does list_recent_sessions List recently recorded sessions (id, origin, ts, event count). get_session_summary LLM-readable narrative summary of a session. get_session_console_errors Console errors recorded in a session. get_session_network_errors Failed/notable network requests in a session. get_user_action_before_error Last N user actions before a console error. generate_playwright_repro Generate a runnable Playwright test from a session. get_dom_snapshot Reconstruct the DOM at a given timestamp. query_dom_history Timeline of attribute/text changes for a selector. request_authorization Side-panel consent for write actions (Level 3). execute_action Dispatch a UI action (gated by permission level + destructive blocklist). Why local-first matters Every other "browser session for AI" tool ships to a vendor cloud. peek's SQLite + extension live on the user's machine — no remote endpoints, no telemetry. The privacy policy (docs/peek/PRIVACY_POLICY.md) is the source of truth. Install # 1. Add the MCP server to Claude Code claude mcp add peek -- npx -y @peekdev/mcp # 2. Install the Chrome extension from the Chrome Web Store # (link added once the CWS listing is approved)

8 hours ago
Crevio

a day ago