A flexible application for generating dynamic GitHub contribution widgets as SVG images. Supports serverless deployment (Netlify Functions), standalone server deployment (Express), and Docker containers. Designed to be embedded anywhere.
Tip
Try the widgets live in the Playground - customize parameters and see real-time previews!
- GitHub Widgets
- 🎨 Beautiful SVG Widgets - Animated, responsive, customizable widgets for GitHub ReadMe
- 🌈 Customizable Themes - Choose from multiple color themes for widgets
- ⚡ Fast & Cached - In-memory LRU cache with configurable TTL (default: 1 hour)
- 🔒 Secure - Optional user locking via
LOCK_GITHUB_USERenvironment variable - 🚀 Flexible Deployment - Deploy as serverless functions (Netlify), standalone server (Express), or Docker container
- 🔄 Extensible - Easy to add new widget types and API versions
- 🛠 SVG Error Handling - All errors returned as SVG images with appropriate HTTP status codes
All widgets support customizable color themes to match your style preferences.
Use the theme query parameter to select a theme for any widget:
| Theme | Description | Preview Colors |
|---|---|---|
| radical (default) | Vibrant pink and purple with dark background | Pink title, multi-color accents |
| ocean | Cool blue tones inspired by the deep sea | Cyan title, ocean blue palette |
| sunset | Warm pink and orange hues | Coral pink title, sunset gradients |
| forest | Natural green tones | Fresh green title, nature-inspired |
| midnight | Deep purple and violet shades | Purple title, night sky colors |
| monochrome | Classic black, white, and gray | Clean grayscale aesthetic |
| transparent-white | No background, light text for dark pages | White title, blue accents |
| transparent-black | No background, dark text for light pages | Black title, deep blue accents |
| transparent-radical | No background, radical theme colors | Pink title, multi-color accents |
Add the theme parameter to any widget URL:
/api/v1/timeseries-history.svg?userName=octocat&theme=oceanRadical Theme (Default):
Ocean Theme:
Sunset Theme:
Forest Theme:
Midnight Theme:
Monochrome Theme:
Transparent White Theme:
Transparent Black Theme:
Transparent Radical Theme:
- Node.js 20.x or higher (for local development)
- GitHub Personal Access Token (create one here)
- Netlify account (for serverless deployment) OR any server/hosting platform (for standalone deployment) OR Docker (for container deployment)
- Clone the repository:
git clone https://github.com/yourusername/github-widgets.git
cd github-widgets- Install dependencies:
npm install- Create a
.envfile from the example:
cp .env.example .env- Add your GitHub token to
.env:
GITHUB_TOKEN=ghp_your_token_hereOption 1: Netlify Functions (Serverless)
Run the Netlify development server:
npm run devThe API will be available at http://localhost:8888/api/v1/
Option 2: Standalone Server (Express)
Run the standalone Express server:
npm startFor development with auto-reload:
npm run dev:serverThe API will be available at http://localhost:3000/api/v1/
Health check endpoint: http://localhost:3000/health
For Netlify Functions (port 8888):
# Timeseries history - with username and date range
curl "http://localhost:8888/api/v1/timeseries-history.svg?userName=cyrus2281&range=2025-01-01:2025-10-15"
# Timeseries history - with username only (defaults to last 365 days)
curl "http://localhost:8888/api/v1/timeseries-history.svg?userName=cyrus2281"
# Experience timeline - with CSV data
CSV_DATA="company,start,end,title,logo,color%0AGoogle,2025-10,,AI/ML%20Engineer,,#4285F4"
curl "http://localhost:8888/api/v1/experience-timeline.svg?experienceCSV=${CSV_DATA}"
# Most starred repositories
curl "http://localhost:8888/api/v1/most-starred.svg?userName=torvalds&top=5"For Standalone Server (port 3000):
# Health check
curl "http://localhost:3000/health"
# Timeseries history
curl "http://localhost:3000/api/v1/timeseries-history.svg?userName=cyrus2281"
# Most starred repositories
curl "http://localhost:3000/api/v1/most-starred.svg?userName=torvalds&top=5"Netlify Functions (Serverless):
- Production:
https://your-site.netlify.app/api/v1/ - Local Development:
http://localhost:8888/api/v1/
Standalone Server (Express):
- Production:
https://your-domain.com/api/v1/(orhttp://your-server-ip:3000/api/v1/) - Local Development:
http://localhost:3000/api/v1/
Generate a GitHub contribution timeseries chart as an SVG image.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
userName |
string | Conditional* | GitHub username to generate chart for |
range |
string | Optional | Date range in format YYYY-MM-DD:YYYY-MM-DD (max 365 days) |
theme |
string | Optional | Color theme. Default radical |
*Required unless LOCK_GITHUB_USER environment variable is set.
Examples:
# Basic usage
/api/v1/timeseries-history.svg?userName=octocat
# With date range
/api/v1/timeseries-history.svg?userName=octocat&range=2024-01-01:2024-12-31
# With custom theme
/api/v1/timeseries-history.svg?userName=octocat&theme=oceanResponse:
- Content-Type:
image/svg+xml - Cache-Control:
public, max-age=3600 - X-Cache:
HITorMISS(indicates cache status)
Generate a professional experience timeline as an SVG image.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
experienceCSV |
string | Yes | URI-encoded CSV data with experience entries |
includeStartDate |
boolean | Optional | Whether to display start date labels on timeline nodes. Defaults to true. |
includeEndDate |
boolean | Optional | Whether to display end date labels on timeline nodes. Defaults to true. |
width |
number | Optional | Width of the SVG in pixels. Defaults to 1200. |
heightPerLane |
number | Optional | Height per timeline lane in pixels. Defaults to 80. |
marginTop |
number | Optional | Top margin in pixels. Defaults to 100. |
marginRight |
number | Optional | Right margin in pixels. Defaults to 30. |
marginBottom |
number | Optional | Bottom margin in pixels. Defaults to 30. |
marginLeft |
number | Optional | Left margin in pixels. Defaults to 30. |
baseFontSize |
number | Optional | Base font size in pixels for relative scaling of all text. All font sizes scale proportionally from this value. Defaults to 14. |
embedLogos |
boolean | Optional | Whether to embed company logos in the timeline. Defaults to true. |
animationTotalDuration |
number | Optional | Total duration of the animation in seconds. Defaults to 5. |
theme |
string | Optional | Color theme. Default radical |
CSV Format:
The CSV must have the following header (in this exact order):
company,start,end,title,logo,color
Field Descriptions:
company(required): Company namestart(required): Start date in formatYYYY,YYYY-MM, orYYYY-MM-DDend(optional): End date in same format as start, or empty for "present"title(optional): Job title/positionlogo(optional): URL to company logo imagecolor(optional): Hex color code for the timeline bar (e.g.,#4285F4)
Example CSV:
company,start,end,title,logo,color
Google,2025-10,,AI/ML Engineer,https://example.com/google-logo.png,#4285F4
Spotify,2024-08,2025-06,Sr Software Developer,https://example.com/spotify-logo.png,#1DB954
Netflix,2024-04,2024-12,Software Engineer - Contract,,#E50914
Amazon,2022-01,2024-08,Software Developer,https://example.com/amazon-logo.png,#FF9900
Meta,2020-06,2021-10,Web Developer,https://example.com/meta-logo.png,#0668E1Usage Examples:
# Basic example with minimal data
CSV="company,start,end,title,logo,color%0AGoogle,2025-10,,AI/ML%20Engineer,,#4285F4"
curl "http://localhost:8888/api/v1/experience-timeline.svg?experienceCSV=${CSV}"
# With multiple entries (URL encode the entire CSV)
# Use online URL encoder or encodeURIComponent() in JavaScript
# Customizing dimensions and animation
CSV="company,start,end,title,logo,color%0AGoogle,2025-10,,AI/ML%20Engineer,,#4285F4"
curl "http://localhost:8888/api/v1/experience-timeline.svg?experienceCSV=${CSV}&width=800&heightPerLane=60&animationTotalDuration=10"- Use width, margin, and font size parameters to fit your layout.
JavaScript Example:
const experienceData = `company,start,end,title,logo,color
Google,2025-10,,AI/ML Engineer,https://example.com/logo.png,#4285F4
Spotify,2024-08,2025-06,Sr Software Developer,,#1DB954`;
const encodedCSV = encodeURIComponent(experienceData);
const url = `https://your-site.netlify.app/api/v1/experience-timeline.svg?experienceCSV=${encodedCSV}`;Response:
- Content-Type:
image/svg+xml - Cache-Control:
public, max-age=3600 - X-Cache:
HITorMISS(indicates cache status)
Error Responses:
All errors are returned as SVG images with appropriate HTTP status codes:
400 Bad Request- Invalid CSV format, missing required fields, or invalid dates404 Not Found- Invalid endpoint500 Internal Server Error- Server error during SVG generation
Generate a widget displaying your most starred GitHub repositories with animated glowing borders.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
userName |
string | Conditional* | GitHub username to fetch repositories for |
top |
number | Optional | Number of repositories to display (1-10). Defaults to 3. |
title |
string | Optional | Custom title for the widget. Defaults to "Most Starred". |
animationDuration |
number | Optional | Duration of card entrance animations in seconds (0.5-10). Defaults to 3.5. |
theme |
string | Optional | Color theme. Default radical |
*Required unless LOCK_GITHUB_USER environment variable is set.
Examples:
# Basic usage - top 3 repositories (default)
/api/v1/most-starred.svg?userName=torvalds
# Custom number of repositories
/api/v1/most-starred.svg?userName=torvalds&top=5
# Custom title and theme
/api/v1/most-starred.svg?userName=torvalds&top=5&title=Top%20Projects&theme=ocean
# Custom animation duration (faster animations)
/api/v1/most-starred.svg?userName=torvalds&animationDuration=2
# All parameters
/api/v1/most-starred.svg?userName=torvalds&top=5&title=My%20Best%20Work&theme=midnight&animationDuration=4.5Response:
- Content-Type:
image/svg+xml - Cache-Control:
public, max-age=3600 - X-Cache:
HITorMISS(indicates cache status)
Error Responses:
400 Bad Request- Invalid username or top parameter out of range (1-10)404 Not Found- User not found or no repositories available500 Internal Server Error- Server error during SVG generation
Generate a comprehensive GitHub user statistics widget displaying various metrics with an animated GitHub logo.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
userName |
string | Conditional* | GitHub username to fetch statistics for |
showHandle |
boolean | Optional | Display user's GitHub handle (@username). Defaults to true. |
showStars |
boolean | Optional | Display total stars across all repositories. Defaults to true. |
showCommits |
boolean | Optional | Display total commits (all time). Defaults to true. |
showCommitsThisYear |
boolean | Optional | Display commits for the current year. Defaults to true. |
showPRs |
boolean | Optional | Display total pull requests. Defaults to true. |
showIssues |
boolean | Optional | Display total issues. Defaults to true. |
showRepos |
boolean | Optional | Display total repositories. Defaults to true. |
showContributedTo |
boolean | Optional | Display number of repositories contributed to. Defaults to true. |
showLogo |
boolean | Optional | Show/hide the GitHub logo. When hidden, widget width adjusts to 300px. Defaults to true. |
width |
number | Optional | Width of the SVG in pixels (300-1000). Defaults to 600. |
animationDuration |
number | Optional | Duration of animations in seconds (0.5-10). Defaults to 2. |
theme |
string | Optional | Color theme. Default radical |
*Required unless LOCK_GITHUB_USER environment variable is set.
Examples:
# Basic usage - all stats visible (default)
/api/v1/user-stats.svg?userName=octocat
# Show only specific stats
/api/v1/user-stats.svg?userName=octocat&showCommits=false&showIssues=false
# Custom width
/api/v1/user-stats.svg?userName=octocat&width=600
# With custom theme
/api/v1/user-stats.svg?userName=octocat&theme=ocean
# Minimal stats display
/api/v1/user-stats.svg?userName=octocat&showHandle=false&showCommitsThisYear=false&showPRs=false&showIssues=false
# Custom animation speed
/api/v1/user-stats.svg?userName=octocat&animationDuration=4
# Hide the GitHub logo (widget becomes narrower at 300px)
/api/v1/user-stats.svg?userName=octocat&showLogo=false
# All parameters combined
/api/v1/user-stats.svg?userName=octocat&width=700&theme=midnight&animationDuration=3&showCommitsThisYear=falseResponse:
- Content-Type:
image/svg+xml - Cache-Control:
public, max-age=3600 - X-Cache:
HITorMISS(indicates cache status)
Error Responses:
400 Bad Request- Invalid username, width out of range (300-1000), or animationDuration out of range (0.5-10)404 Not Found- User not found500 Internal Server Error- Server error during SVG generation
Generate a repository card widget displaying GitHub repository information similar to GitHub's pinned repositories.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
userName |
string | Conditional* | GitHub username (repository owner) |
repoName |
string | Yes | Repository name |
theme |
string | Optional | Color theme. Default radical |
showUserName |
boolean | Optional | Display the username/owner. Defaults to true. |
showLanguage |
boolean | Optional | Display the primary language. Defaults to true. |
showStars |
boolean | Optional | Display star count. Defaults to true. |
showForks |
boolean | Optional | Display fork count. Defaults to true. |
width |
number | Optional | Width of the card in pixels (300-600). Defaults to 400. |
height |
number | Optional | Height of the card in pixels (100-200). Defaults to 120. |
*Required unless LOCK_GITHUB_USER environment variable is set.
Examples:
# Basic usage
/api/v1/repository-card.svg?userName=octocat&repoName=github-widgets
# With custom theme
/api/v1/repository-card.svg?userName=octocat&repoName=github-widgets&theme=ocean
# Hide specific elements
/api/v1/repository-card.svg?userName=octocat&repoName=github-widgets&showUserName=false&showForks=false
# Custom dimensions
/api/v1/repository-card.svg?userName=octocat&repoName=github-widgets&width=500&height=150
# All parameters combined
/api/v1/repository-card.svg?userName=octocat&repoName=github-widgets&theme=midnight&width=550&height=140&showLanguage=falseResponse:
- Content-Type:
image/svg+xml - Cache-Control:
public, max-age=3600 - X-Cache:
HITorMISS(indicates cache status)
Error Responses:
400 Bad Request- Invalid username, repository name, or parameters out of range404 Not Found- Repository not found500 Internal Server Error- Server error during SVG generation
Generate a contribution streak widget displaying total contributions, current streak with animated ring, and longest streak.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
userName |
string | Conditional* | GitHub username to fetch contribution data for |
theme |
string | Optional | Color theme. Default radical |
animationDuration |
number | Optional | Duration of animations in seconds (0.5-10). Defaults to 2. |
*Required unless LOCK_GITHUB_USER environment variable is set.
Examples:
# Basic usage
/api/v1/contribution-streak.svg?userName=octocat
# With custom theme
/api/v1/contribution-streak.svg?userName=octocat&theme=ocean
# Custom animation speed
/api/v1/contribution-streak.svg?userName=octocat&animationDuration=4
# All parameters combined
/api/v1/contribution-streak.svg?userName=octocat&theme=midnight&animationDuration=3Response:
- Content-Type:
image/svg+xml - Cache-Control:
public, max-age=3600 - X-Cache:
HITorMISS(indicates cache status)
Error Responses:
400 Bad Request- Invalid username or animationDuration out of range (0.5-10)404 Not Found- User not found or no contribution data available500 Internal Server Error- Server error during SVG generation
Generate a visual skill table with technology icons as an SVG image. Icons are sourced from Simple Icons or custom URLs and are embedded directly in the SVG for compatibility with GitHub READMEs.
Query Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
skills |
string | Yes | Pipe-separated skill entries (see format below) |
columns |
number | Optional | Number of columns (1-10). Defaults to 4. |
title |
string | Optional | Title displayed above the table |
subtitle |
string | Optional | Subtitle below the title |
showTitles |
boolean | Optional | Show skill names under icons. Defaults to true. |
iconSize |
number | Optional | Icon size in pixels (16-128). Defaults to 48. |
useOriginalColors |
boolean | Optional | Use brand's original logo colors. When false, uses theme text color. Defaults to true. |
iconColor |
string | Optional | Override all icon colors with this hex value (e.g. ffffff). |
gap |
number | Optional | Spacing between cells in pixels (0-64). Defaults to 16. |
animationDuration |
number | Optional | Animation duration in seconds (0.5-10). Defaults to 1. |
theme |
string | Optional | Color theme. Default radical |
Skills Format:
Entries are separated by | (pipe). Each entry is one of:
| Format | Description | Example |
|---|---|---|
slug |
Simple Icons slug, uses brand name as title | python |
Title:slug |
Simple Icons slug with custom display title | C++:cplusplus |
Title:URL |
Custom icon URL with display title | Java:https://example.com/java.svg |
--Name-- |
Section header spanning all columns | --Programming Languages-- |
Find icon slugs at simpleicons.org.
Examples:
# Basic usage
/api/v1/skill-table.svg?skills=python|javascript|react|docker
# With section headers and title
/api/v1/skill-table.svg?skills=--Languages--|python|javascript|C%2B%2B:cplusplus|--Tools--|docker|git&title=My%20Skills&columns=3
# With custom icons and theme
/api/v1/skill-table.svg?skills=python|Java:https://example.com/java.svg|react&theme=ocean
# Themed icons (uniform color)
/api/v1/skill-table.svg?skills=python|javascript|react&useOriginalColors=falseResponse:
- Content-Type:
image/svg+xml - Cache-Control:
public, max-age=3600 - X-Cache:
HITorMISS(indicates cache status)
Error Responses:
400 Bad Request- Missing skills parameter, no valid entries, or input too long500 Internal Server Error- Server error during SVG generation
Netlify Deployment:
Standalone Server Deployment:
Netlify Deployment:
<img src="https://your-site.netlify.app/api/v1/timeseries-history.svg?userName=octocat" alt="GitHub Contributions" />Standalone Server Deployment:
<img src="https://your-domain.com/api/v1/timeseries-history.svg?userName=octocat" alt="GitHub Contributions" />GITHUB_TOKEN- GitHub Personal Access Token- Required scopes:
read:user - Create token here
- Required scopes:
-
LOCK_GITHUB_USER- Lock API to specific GitHub user- When set,
userNamequery parameter is disabled - Useful for personal deployments
- Example:
LOCK_GITHUB_USER=cyrus2281
- When set,
-
CACHE_MAX_SIZE- Maximum number of cached responses- Default:
100 - Increase for high-traffic deployments
- Default:
-
CACHE_TTL_MS- Cache time-to-live in milliseconds- Default:
3600000(1 hour) - Adjust based on update frequency needs
- Default:
-
PORT- Server port (Standalone Server only)- Default:
3000 - Only used when running the standalone Express server
- Example:
PORT=8080
- Default:
This application supports two deployment options, each with distinct advantages:
Setup:
- Via Netlify CLI:
# Login to Netlify
netlify login
# Deploy to production
npm run deploy- Via Git Integration:
- Push your code to GitHub
- Connect repository in Netlify dashboard
- Netlify will auto-deploy on push to main branch
- Set Environment Variables:
In Netlify dashboard or via CLI:
netlify env:set GITHUB_TOKEN "ghp_your_token_here"
netlify env:set LOCK_GITHUB_USER "your-username" # Optional
netlify env:set CACHE_MAX_SIZE "100" # Optional
netlify env:set CACHE_TTL_MS "3600000" # OptionalAccess your API:
https://your-site.netlify.app/api/v1/timeseries-history.svg?userName=octocat
Setup:
- Install dependencies:
npm install- Configure environment variables:
Create a .env file:
cp .env.example .envEdit .env with your configuration:
- Start the server:
Production mode:
npm startDevelopment mode (with auto-reload):
npm run dev:serverThe server will start on port 3000 (or the PORT specified in .env).
- Verify the server is running:
# Health check
curl http://localhost:3000/health
# Test an endpoint
curl "http://localhost:3000/api/v1/user-stats.svg?userName=octocat"Prerequisites:
- Docker installed (Get Docker)
- GitHub Personal Access Token (create one here)
Quick Start:
Pull and run the pre-built image from Docker Hub:
docker pull cyrus2281/github-widgets:latest
docker run -d \
--name github-widgets \
-p 3000:3000 \
-e GITHUB_TOKEN="ghp_your_token_here" \
cyrus2281/github-widgets:latestAccess your API:
http://localhost:3000/api/v1/timeseries-history.svg?userName=octocat
Health Check:
curl http://localhost:3000/healthEnvironment Variables:
Configure the container using environment variables:
| Variable | Required | Default | Description |
|---|---|---|---|
GITHUB_TOKEN |
Yes | - | GitHub Personal Access Token with read:user scope |
PORT |
No | 3000 |
Port the server listens on inside the container |
LOCK_GITHUB_USER |
No | - | Lock API to specific GitHub user (disables userName parameter) |
CACHE_MAX_SIZE |
No | 100 |
Maximum number of cached responses |
CACHE_TTL_MS |
No | 3600000 |
Cache time-to-live in milliseconds (1 hour) |
Advanced Usage:
1. Run with all configuration options:
docker run -d \
--name github-widgets \
-p 8080:3000 \
-e GITHUB_TOKEN="ghp_your_token_here" \
-e LOCK_GITHUB_USER="your-username" \
-e CACHE_MAX_SIZE="200" \
-e CACHE_TTL_MS="7200000" \
--restart unless-stopped \
cyrus2281/github-widgets:latest2. Run with custom port mapping:
# Map container port 3000 to host port 8080
docker run -d \
--name github-widgets \
-p 8080:3000 \
-e GITHUB_TOKEN="ghp_your_token_here" \
cyrus2281/github-widgets:latest
# Access at http://localhost:8080/api/v1/...3. View logs:
docker logs github-widgets
# Follow logs in real-time
docker logs -f github-widgets4. Stop and remove container:
docker stop github-widgets
docker rm github-widgetsBuilding from Source (Optional):
If you want to build the Docker image yourself:
# Clone the repository
git clone https://github.com/cyrus2281/github-widgets.git
cd github-widgets
# Build the image
docker build -t github-widgets:local .
# Run your custom build
docker run -d \
--name github-widgets \
-p 3000:3000 \
-e GITHUB_TOKEN="ghp_your_token_here" \
github-widgets:localProduction Deployment Tips:
1. Use specific version tags:
docker pull cyrus2281/github-widgets:v1.0.02. Behind a reverse proxy (Nginx, Traefik, Caddy):
# Nginx example
location /github-widgets/ {
proxy_pass http://localhost:3000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_cache_valid 200 1h;
}3. Kubernetes Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: github-widgets
spec:
replicas: 3
selector:
matchLabels:
app: github-widgets
template:
metadata:
labels:
app: github-widgets
spec:
containers:
- name: github-widgets
image: cyrus2281/github-widgets:latest
ports:
- containerPort: 3000
env:
- name: GITHUB_TOKEN
valueFrom:
secretKeyRef:
name: github-widgets-secret
key: github-token
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 10
periodSeconds: 30
readinessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 5
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: github-widgets
spec:
selector:
app: github-widgets
ports:
- port: 80
targetPort: 3000
type: LoadBalancerThe application follows a modular, extensible architecture:
- API Router - Routes requests to versioned handlers
- Handlers - Process requests and generate responses
- Services - Business logic (GitHub API, SVG generation)
- Utils - Shared utilities (cache, validation, errors)
- In-Memory LRU Cache - Fast, simple, resets on cold starts
- Cache Key Format:
timeseries-history:{username}:{startDate}:{endDate} - TTL: 1 hour (configurable)
- Max Size: 100 entries (configurable)
- Eviction: Least Recently Used (LRU)
Cache headers:
X-Cache: HIT- Response served from cacheX-Cache: MISS- Response generated fresh
- Create handler in
src/handlers/v1/new-endpoint.js:
export async function handler(event) {
// Your logic here
return {
statusCode: 200,
headers: { 'Content-Type': 'image/svg+xml' },
body: svgContent,
};
}- Add route in
netlify/functions/api.js:
case 'new-endpoint.svg':
return newEndpointHandler(event);- Add route in
server/routes.js:
router.get(['/v1/new-endpoint.svg', '/v1/new-endpoint'], wrapHandler(newEndpointHandler));- Reuse existing utilities (cache, validation, errors)
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- If adding or updating a widget endpoint, update
public/widgets-config.jsonwith the new endpoint details (name, path, query parameters, defaults, and descriptions). This file powers the interactive playground at/playground.html. - Submit a pull request
Apache-2.0 License - see LICENSE file for details