A real-time analytics and monitoring platform for the Xandeum network. This dashboard provides insights into pNode status, network health, storage usage, and performance metrics, similar to Solana validator dashboards.
Xandeum is building a scalable storage layer for Solana dApps. This analytics platform monitors the network of pNodes by:
- Retrieving real-time pNode data from the Xandeum gossip network via pRPC (pNode RPC) calls
- Storing historical snapshots in a PostgreSQL database
- Displaying analytics through an intuitive web interface
- Providing detailed node-level metrics and network-wide statistics
-
Network Overview
- Total nodes, active nodes, and network health score
- Real-time status distribution (active, inactive, syncing)
- Storage usage visualization (used vs available)
- Average uptime statistics
- Global node geographic distribution with world map visualization
-
Historical Trends
- Network activity over time (1 hour to 30 days)
- Active nodes trend
- Storage usage trends
- Configurable time ranges
-
Node Management
- Sortable and searchable node table
- Grouped by public key with multiple addresses
- Storage capacity and usage per node
- Version tracking
-
Node Detail Pages
- Individual node metrics and status
- Latency tracking over time
- Storage usage per address
- Version history
- Uptime and last seen information
- Activity Timeline (active/inactive periods visualization)
- Activity Heatmap (7x24 grid showing activity patterns)
- Downtime Report (incident history and MTTR analysis)
- Geographic Location Map (node location visualization with historical tracking)
-
3D Globe Visualization
- Interactive 3D globe map showing global node distribution
- Real-time node location tracking with geographic coordinates
- Visual connections between node locations (same node at different locations)
- Hover tooltips with IP, location, and node count
- Clickable nodes with detailed information sheets
- Full-screen map view at
/maproute
-
UI/UX
- Dark/light theme support
- Responsive design
- Real-time data updates
- Interactive charts and visualizations
- Loading states and error handling
- Globe button on home page for quick map access
- Next.js 16 - React framework with App Router
- React 19 - UI library
- TypeScript - Type safety
- Tailwind CSS 4 - Styling
- shadcn/ui - UI component library
- Recharts - Charting library
- Three.js - 3D graphics library
- React Three Fiber - React renderer for Three.js
- React Three Drei - Useful helpers for React Three Fiber
- next-themes - Theme management with dark/light mode
- TanStack Query - Data fetching and caching
- TanStack Table - Data table with sorting/filtering
- Next.js API Routes - Server-side API endpoints
- PostgreSQL - Database for historical snapshots
- Drizzle ORM - Type-safe database queries
- Zod - Schema validation
- Vercel Analytics - Analytics tracking
- JSON-RPC 2.0 - Communication with Xandeum pRPC endpoints
Xandeum Network (pRPC)
↓
Telegram Bot (Cron) → POST /api/snapshot (every 1 minute)
↓
PostgreSQL Database (Historical Snapshots)
↓
Next.js API Routes
↓
React Components (TanStack Query)
↓
User Interface
-
RPC Client Service (
services/rpc-client.service.ts)- Handles JSON-RPC 2.0 communication
- Automatic failover across multiple Xandeum endpoints
- Timeout and error handling
-
Database Service (
services/pods-db.service.ts)- Stores pod snapshots
- Retrieves historical data
- Network statistics aggregation
- Cleanup operations
-
API Service (
services/api.service.ts)- Transforms pod data to node format
- Calculates network statistics
- Status determination logic
-
IP Geolocation Service (
services/ip-geolocation.service.ts)- Automatic IP extraction from node addresses
- IP geolocation lookup via ip-api.com
- Rate limiting and batch processing
- Geographic data caching and aggregation
-
3D Globe Components (
components/)Globe3D- Interactive 3D globe with Three.jsNodeWorldMap- Global node distribution visualizationNodeLocationMap- Individual node location history- Sphere coordinate conversion (lat/lng to 3D)
- Arc connections between locations using Bezier curves
- Hover tooltips and clickable node markers
- Theme-aware rendering
-
React Hooks (
hooks/)useNodes- Fetch all nodesuseNodeMetrics- Fetch node-specific metricsuseNodeActivity- Fetch node activity periodsuseNodeHeatmap- Fetch node activity heatmapuseNetworkStats- Network-wide statisticsuseNetworkHistory- Historical trendsuseNodesGeolocation- Fetch all nodes geolocation datauseNodeGeolocation- Fetch specific node geolocation data
- Node.js 20+ (or Bun)
- PostgreSQL database
- Access to Xandeum pRPC endpoints
- Clone the repository
git clone https://github.com/Code-Parth/xandeum-analytics-ui.git
cd xandeum-analytics-ui- Install dependencies
bun install
# or
bun install- Set up environment variables
Copy .env.example to .env and fill in the required values:
cp .env.example .env- Set up the database
# Generate migration files
bun run db:generate
# Run migrations
bun run db:migrate
# Or push schema directly (development)
bun run db:push- Start the development server
bun run devOpen http://localhost:3000 in your browser.
Create a .env file in the root directory:
# Database
DATABASE_URL="postgresql://user:password@localhost:5432/xandeum_analytics"
# Cron secret for snapshot API authentication
# Generate with: openssl rand -hex 32
CRON_SECRET="your-random-secret-here"
# RPC timeout (optional, default: 10000ms)
RPC_TIMEOUT_MS=10000- DATABASE_URL: PostgreSQL connection string
- CRON_SECRET: Secret token for authenticating snapshot API calls (used by the Telegram bot)
- RPC_TIMEOUT_MS: Timeout for RPC calls in milliseconds (default: 10000)
The database consists of two main tables:
address- Node address (IP:port)pubkey- Public key identifierversion- Node software versionlastSeenTimestamp- Last seen timestampuptime- Uptime in secondsstorageCommitted- Committed storage capacitystorageUsed- Used storagestorageUsagePercent- Storage usage percentagesnapshotTimestamp- When the snapshot was taken
ip- IP address (IPv4/IPv6)status- Success or fail status from IP APIcountry/countryCode- Country informationregion/regionName- Regional informationcity- City namelat/lon- Geographic coordinatestimezone- Timezone informationisp/org- ISP and organization detailsasInfo- Autonomous System information
# Generate migration from schema changes
bun run db:generate
# Run migrations
bun run db:migrate
# Push schema directly (development only)
bun run db:push
# Open Drizzle Studio (database GUI)
bun run db:studioGET /api/health- Health check endpointGET /api/pods/latest- Get latest pod snapshotGET /api/pods/history- Get historical pod dataGET /api/nodes/[pubkey]/metrics- Get node metrics historyGET /api/nodes/[pubkey]/activity- Get node activity periods (active/inactive)GET /api/nodes/[pubkey]/heatmap- Get node activity heatmap dataGET /api/nodes/[pubkey]/geolocation- Get node geographic location data with historyGET /api/geolocation- Get all nodes geolocation data for world mapPOST /api/rpc- Proxy for JSON-RPC calls
POST /api/snapshot- Create new snapshot (called by cron)POST /api/cleanup- Cleanup old snapshots (90+ days)
# Get latest snapshot
curl http://localhost:3000/api/pods/latest
# Create snapshot (requires auth)
curl -X POST http://localhost:3000/api/snapshot \
-H "Authorization: Bearer YOUR_CRON_SECRET"
# Health check
curl http://localhost:3000/api/healthThis application relies on external cron jobs to collect and store network snapshots. The cron job system is implemented as a separate Telegram bot that periodically calls the snapshot API.
For detailed information about setting up and running the cron job system, please refer to the separate Telegram bot repository:
The Telegram bot:
- Calls
POST /api/snapshotevery 1 minute - Authenticates using the
CRON_SECRETenvironment variable - Handles errors and retries
- Provides monitoring and alerts via Telegram
- The Telegram bot calls
/api/snapshotevery minute - The API fetches current pod data from Xandeum pRPC endpoints
- Data is validated and stored in PostgreSQL
- The dashboard displays the latest snapshot data
The cleanup endpoint (POST /api/cleanup) should be called every 90 days to remove old snapshots:
curl -X POST http://localhost:3000/api/cleanup \
-H "Authorization: Bearer YOUR_CRON_SECRET"The platform includes automatic IP geolocation tracking and an interactive 3D globe to visualize the global distribution of network nodes.
- Automatic IP Detection: When new node snapshots are created, the system extracts unique IP addresses from node addresses
- Geolocation Lookup: New IPs are automatically queried using the ip-api.com free API
- Data Storage: Geographic coordinates, ISP info, and location details are cached in the
ip_geolocationtable - 3D Globe Visualization: The dashboard displays an interactive 3D globe showing node distribution with real-time rendering
- Visual Connections: Arc lines connect locations where the same node (pubkey) has been observed at different IPs
The IP API integration respects the following limits:
- 45 requests per minute (free tier limit)
- 100 IPs per batch request
- Automatic rate limiting and request spacing
- Cached lookups to avoid redundant API calls
- Interactive 3D Globe: Real-time rotating globe with WebGL rendering using Three.js
- Global Node Distribution: Full-screen map view at
/mapshowing all network nodes - Visual Connections: Arc paths connecting locations where the same node has operated
- Country Statistics: Node counts grouped by country with ISO codes
- Historical Tracking: First seen and last seen timestamps for each location
- Node-Specific Maps: Individual node detail pages show all geographic locations where that node has operated
- Smart Aggregation: Multiple addresses from the same IP are intelligently grouped
- Interactive Elements:
- Hover tooltips showing IP, location, and node count
- Clickable nodes opening detail sheets with full information
- Auto-rotating globe with manual orbit controls (pan, zoom, rotate)
- Theme Support: Automatically adapts colors and styling for light and dark modes
- Geolocation is performed on IP addresses only (no personal data)
- Uses the free ip-api.com service for lookups
- Data includes: country, region, city, coordinates, ISP, and timezone
- All data is cached locally to minimize external API calls
# Development
bun run dev # Start development server
# Build
bun run build # Build for production
bun run start # Start production server
# Code Quality
bun run lint # Run ESLint
bun run lint:fix # Fix ESLint errors and format
bun run typecheck # TypeScript type checking
# Database
bun run db:generate # Generate migrations
bun run db:migrate # Run migrations
bun run db:push # Push schema (dev only)
bun run db:studio # Open Drizzle Studio- Make changes to the codebase
- Run
bun run typecheckto check for TypeScript errors - Run
bun run lintto check for linting issues - Test locally with
bun run dev - If schema changes are made, run
bun run db:generateandbun run db:migrate
app/- Next.js App Router pages and API routescomponents/- React componentshooks/- Custom React hooksservices/- Business logic and API servicesdb/- Database schema and migrationstypes/- TypeScript type definitionsschemas/- Zod validation schemasconfig/- Configuration filesutils/- Utility functions
-
Connect your repository to Vercel
-
Set environment variables in Vercel dashboard:
DATABASE_URLCRON_SECRETRPC_TIMEOUT_MS(optional)
-
Deploy
Vercel will automatically:
- Build the Next.js application
- Run database migrations (if configured)
- Deploy to production
For production deployments, ensure migrations are run:
# On your deployment platform or CI/CD
bun run db:migrateAfter deploying the main application:
- Deploy the Telegram bot (see separate repository)
- Configure the bot with:
- Your application URL
CRON_SECRETvalue- Snapshot interval (recommended: 1 minute)
xandeum-analytics-ui/
├── app/
│ ├── api/ # API routes
│ │ ├── cleanup/ # Cleanup endpoint
│ │ ├── geolocation/ # Global geolocation data
│ │ ├── health/ # Health check
│ │ ├── nodes/ # Node metrics, activity, heatmap, geolocation
│ │ ├── pods/ # Pod data endpoints
│ │ ├── rpc/ # RPC proxy
│ │ └── snapshot/ # Snapshot creation
│ ├── map/ # Full-screen 3D globe page
│ │ └── page.tsx # Interactive globe with node locations
│ ├── node/[pubkey]/ # Node detail pages
│ ├── page.tsx # Dashboard home
│ ├── layout.tsx # Root layout
│ └── globals.css # Global styles
├── components/
│ ├── ui/ # shadcn/ui components
│ │ ├── world-map.tsx # 2D world map visualization component
│ │ └── theme-toggle-button.tsx # Theme switcher
│ ├── globe-3d.tsx # 3D globe component (Three.js)
│ ├── node-world-map.tsx # Global nodes 3D globe map
│ ├── node-location-map.tsx # Individual node 3D location map
│ ├── activity-timeline.tsx
│ ├── activity-heatmap.tsx
│ ├── downtime-report.tsx
│ ├── wrapper.tsx # Theme-aware layout wrapper
│ └── chart-info-hover.tsx
├── config/
│ └── endpoints.ts # Xandeum RPC endpoints
├── constants/
│ └── index.ts
├── db/
│ ├── migrations/ # Database migrations
│ ├── schema.ts # Drizzle schema
│ └── index.ts # Database connection
├── docs/
│ └── METRICS_DOCUMENTATION.md # Charts & calculations docs
├── hooks/ # React hooks
│ ├── useNodes.ts
│ ├── useNodeMetrics.ts
│ ├── useNodeActivity.ts
│ ├── useNodeHeatmap.ts
│ ├── useNodesGeolocation.ts # Global geolocation data
│ ├── useNodeGeolocation.ts # Per-node geolocation
│ └── index.ts
├── lib/
│ └── utils.ts # Utility functions
├── provider/ # React providers
├── schemas/ # Zod schemas
├── services/ # Business logic
├── theme/ # Theme configuration
├── types/ # TypeScript types
└── utils/ # Utility functions
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Run tests and linting (
bun run lintandbun run typecheck) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow TypeScript best practices
- Use ESLint and Prettier (configured)
- Write descriptive commit messages
- Add comments for complex logic
This project is licensed under the MIT License.
- Metrics Documentation: Comprehensive guide explaining all charts, calculations, and data sources used in the analytics platform.
- Xandeum Network: xandeum.network
- Xandeum Documentation: docs.xandeum.network
- Xandeum Discord: discord.gg/uqRSmmM5m
- Live Analytics Dashboard: xandeum-analytics-ui.vercel.app
- Cron Bot Repository: xandeum-analytics-cron-bot
- Issue Tracker: GitHub Issues
- Next.js 16: nextjs.org/docs
- React 19: react.dev
- Three.js: threejs.org/docs
- React Three Fiber: docs.pmnd.rs/react-three-fiber
- React Three Drei: github.com/pmndrs/drei
- next-themes: github.com/pacocoursey/next-themes
- Drizzle ORM: orm.drizzle.team
- TanStack Query: tanstack.com/query
- shadcn/ui: ui.shadcn.com
- Tailwind CSS: tailwindcss.com
- IP Geolocation API: ip-api.com - Free IP geolocation service
- Rate limit: 45 requests/minute
- Batch endpoint: 100 IPs per request
- Fields: country, region, city, coordinates, ISP, timezone
- Thanks to Bernie Blume for helpful clarifications and insights about Xandeum’s architecture
- Built for the Xandeum Labs analytics platform challenge on Superteam Earn
- Inspired by Solana validator dashboards (stakewiz.com, topvalidators.app, validators.app)
Note: This platform is designed to monitor the Xandeum network of pNodes and provide analytics similar to Solana validator dashboards based on provided data