@euvia/live
v1.0.0
Published
Self-hosted, GDPR-compliant real-time visitor analytics for Next.js and React applications
Downloads
41
Maintainers
Readme
@euvia/live
Self-hosted, GDPR-compliant real-time visitor analytics for Next.js and React applications. Track live visitors with complete privacy and no consent banners required.
Features
- GDPR/RGPD Compliant: 100% anonymous tracking with no personal data collection
- Real-time Analytics: Live visitor count, page views, and device breakdown
- Self-hosted: Complete data ownership and control
- Invisible Tracking: Zero UI footprint, no cookies, no consent banners
- High Performance: Optimized for 10,000+ concurrent connections
- Easy Integration: 2-minute setup with React components and hooks
- Privacy First: Hashed URLs, categorized user agents, ephemeral data (5-min TTL)
Why Euvia?
Traditional analytics solutions require cookie consent banners and collect personal data. Euvia is designed from the ground up to be completely anonymous and GDPR-compliant by design, eliminating the need for consent popups while providing essential live visitor insights.
Compliance Features
- Anonymous: Pages are base64-hashed, user agents categorized, screen sizes bucketed
- Ephemeral: All data stored in Redis with 5-minute TTL, no persistent logs
- First-party: Self-hosted WebSocket connection, no third-party services
- No PII: Zero personal identifiable information collected (no IP, no UUID, no cookies)
Installation
pnpm install @euvia/liveWhy pnpm?
This project uses pnpm as the recommended package manager for several reasons:
- Disk Efficiency: pnpm uses a content-addressable store, saving up to 80% disk space compared to npm/yarn
- Speed: Faster installation times due to hard-linking instead of copying files
- Strict Dependencies: Better dependency resolution prevents phantom dependencies
- Monorepo Support: Built-in workspace support for complex projects
- Security: Improved security with isolated node_modules structure
You can still use npm or yarn, but pnpm is recommended for optimal performance and consistency with the development environment.
Install pnpm:
npm install -g pnpm
# or
curl -fsSL https://get.pnpm.io/install.sh | sh -Quick Start
1. Start the Server
Using Docker (Recommended)
# Clone the repository
git clone https://github.com/Teyk0o/euvia-nodejs
cd euvia-nodejs
# Start with Docker Compose
docker-compose up -dUsing npx
# Ensure Redis is running locally
redis-server
# Start Euvia server
npx @euvia/live serverManual Setup
pnpm install @euvia/live
# Create .env file
cat > .env << EOF
PORT=3001
REDIS_URL=redis://localhost:6379
STATS_TTL=300
CORS_ORIGINS=http://localhost:3000
EOF
# Start server
pnpm run server2. Add Tracking to Your Site
// app/layout.tsx (Next.js App Router)
import { EuviaTracker } from '@euvia/live';
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<EuviaTracker serverUrl="ws://localhost:3001" />
</body>
</html>
);
}// pages/_app.tsx (Next.js Pages Router)
import { EuviaTracker } from '@euvia/live';
export default function App({ Component, pageProps }) {
return (
<>
<Component {...pageProps} />
<EuviaTracker serverUrl="ws://localhost:3001" />
</>
);
}3. View Live Stats
Using the Hook
'use client'; // Next.js 13+ App Router
import { useEuviaStats } from '@euvia/live';
export default function AdminDashboard() {
const { stats, isConnected, isLoading } = useEuviaStats({
serverUrl: 'ws://localhost:3001',
});
if (isLoading) return <div>Loading stats...</div>;
if (!stats) return <div>No data available</div>;
return (
<div>
<h1>Live Visitors: {stats.totalVisitors}</h1>
<h2>Device Breakdown</h2>
<ul>
<li>Desktop: {stats.deviceBreakdown.desktop}</li>
<li>Mobile: {stats.deviceBreakdown.mobile}</li>
<li>Tablet: {stats.deviceBreakdown.tablet}</li>
</ul>
<h2>Top Pages</h2>
<ul>
{stats.topPages.map((page) => (
<li key={page.pageHash}>
{page.originalPath}: {page.visitors} visitors
</li>
))}
</ul>
</div>
);
}Using the Component
import { EuviaLiveStats } from '@euvia/live';
export default function StatsPage() {
return (
<div>
<h1>Analytics Dashboard</h1>
<EuviaLiveStats serverUrl="ws://localhost:3001" maxPages={10} showPaths={true} />
</div>
);
}API Reference
Client Components
<EuviaTracker />
Invisible tracking component that sends visitor heartbeats.
Props:
| Prop | Type | Default | Description |
| ------------------- | ------------------------ | -------- | -------------------------------------------------- |
| serverUrl | string | required | WebSocket server URL (e.g., ws://localhost:3001) |
| heartbeatInterval | number | 60000 | Heartbeat interval in milliseconds |
| enabled | boolean | true | Enable/disable tracking |
| onConnect | () => void | - | Callback when connected |
| onDisconnect | () => void | - | Callback when disconnected |
| onError | (error: Error) => void | - | Callback on error |
<EuviaLiveStats />
Pre-built component to display live statistics.
Props:
| Prop | Type | Default | Description |
| ----------------- | --------- | -------- | ---------------------- |
| serverUrl | string | required | WebSocket server URL |
| autoConnect | boolean | true | Auto-connect on mount |
| className | string | '' | Custom CSS class |
| showPaths | boolean | true | Show unhashed paths |
| maxPages | number | 10 | Max pages to display |
| refreshInterval | number | 5000 | Stats refresh interval |
Hooks
useEuviaStats(options)
React hook for live statistics.
Options:
{
serverUrl: string;
autoConnect?: boolean;
onConnect?: () => void;
onDisconnect?: () => void;
onError?: (error: Error) => void;
}Returns:
{
stats: LiveStats | null;
isConnected: boolean;
isLoading: boolean;
error: Error | null;
refresh: () => void;
connect: () => void;
disconnect: () => void;
}Server Configuration
Environment Variables
PORT=3001 # Server port
REDIS_URL=redis://localhost:6379 # Redis connection URL
STATS_TTL=300 # Stats TTL in seconds (default: 5 minutes)
CORS_ORIGINS=* # Comma-separated allowed originsCLI Commands
# Start server with default settings
npx @euvia/live server
# Custom configuration
npx @euvia/live server \
--port 3001 \
--redis redis://localhost:6379 \
--ttl 300 \
--cors "http://localhost:3000,https://example.com"Programmatic Usage
import { createEuviaServer } from '@euvia/live/server';
const server = createEuviaServer({
port: 3001,
redisUrl: 'redis://localhost:6379',
statsTTL: 300,
corsOrigins: ['http://localhost:3000'],
broadcastInterval: 2000,
});
await server.start();
// Graceful shutdown
process.on('SIGTERM', async () => {
await server.stop();
});Type Definitions
interface VisitorData {
pageHash: string;
deviceCategory: 'mobile' | 'desktop' | 'tablet';
screenBucket: string;
timestamp: number;
}
interface LiveStats {
totalVisitors: number;
topPages: PageStats[];
deviceBreakdown: {
mobile: number;
desktop: number;
tablet: number;
};
lastUpdate: number;
}
interface PageStats {
pageHash: string;
originalPath?: string;
visitors: number;
}Production Deployment
Docker Deployment
# Build and run
docker-compose up -d
# View logs
docker-compose logs -f euvia-server
# Scale if needed
docker-compose up -d --scale euvia-server=3Environment Setup
For production, create a .env file:
NODE_ENV=production
PORT=3001
REDIS_URL=redis://your-redis-host:6379
STATS_TTL=300
CORS_ORIGINS=https://yourdomain.comNginx Reverse Proxy
upstream euvia_backend {
server localhost:3001;
}
server {
listen 443 ssl http2;
server_name analytics.yourdomain.com;
location / {
proxy_pass http://euvia_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}Performance
- Client Bundle: < 10KB gzipped (tree-shakable)
- Server Capacity: 10,000+ concurrent connections
- Latency: < 50ms response time
- Memory: ~50MB base + ~1KB per active visitor
- Redis: Optimized with pipelines and TTL-based cleanup
GDPR Compliance Guide
Euvia is designed to be GDPR-compliant by default. Here's why no consent banner is required:
Data Minimization
- No Personal Data: No IP addresses, user IDs, cookies, or fingerprinting
- Anonymized: All data is categorized and hashed before storage
- Aggregated: Only statistical aggregates are computed
Legitimate Interest
Under GDPR Article 6(1)(f), legitimate interest applies when:
- Analytics are necessary for site operation
- Privacy impact is minimal (anonymous, ephemeral)
- No unexpected processing occurs
Euvia meets all criteria as a first-party, anonymous analytics tool.
Transparency
Include this in your privacy policy:
We use self-hosted analytics (Euvia) to understand site usage. This collects anonymous data including:
- Page views (hashed URLs)
- Device categories (mobile/desktop/tablet)
- Screen size ranges
No personal information, IP addresses, or cookies are collected. Data is deleted after 5 minutes.
Development
Prerequisites
- Node.js 20+ (required)
- pnpm (recommended) - see installation above
- Redis 7+ (for local server)
- Git (for version control)
Setup
# Clone repository
git clone https://github.com/Teyk0o/euvia-nodejs
cd euvia-nodejs
# Install dependencies (auto-installs git hooks)
pnpm install
# Start development
pnpm run dev
# Run tests
pnpm test
# Run tests with coverage
pnpm run test:coverage
# Lint code
pnpm run lint
# Format code
pnpm run format
# Type check
pnpm run typecheck
# Build
pnpm run buildGit Hooks & Commit Conventions
This project uses automated quality checks and conventional commits.
Pre-commit Hooks
Automatically runs before each commit:
- ESLint: Auto-fixes TypeScript/React code issues
- Prettier: Formats all code files
- Tests: Runs tests for changed files only
- Type Check: Validates TypeScript types
Pre-push Hooks
Runs before pushing to remote:
- Full Test Suite: Ensures all tests pass
- Type Check: Complete TypeScript validation
- Security Audit: Checks for vulnerable dependencies
Commit Message Format
All commits must follow Conventional Commits:
<type>[optional scope]: <description>
[optional body]
[optional footer]Types:
feat- New featurefix- Bug fixdocs- Documentation changesstyle- Code formatting (no logic change)refactor- Code refactoringperf- Performance improvementstest- Adding/updating testsbuild- Build system or dependenciesci- CI/CD changeschore- Other changes
Examples:
feat(tracker): add reconnection callbacks
fix(server): resolve Redis connection leak
docs: update deployment guide
refactor(utils): simplify hash functionValidation: Commit messages are validated automatically. Invalid formats will be rejected:
✓ feat(tracker): add new feature
✓ fix: resolve bug
✗ Add new feature # Missing type
✗ FEAT: new feature # Uppercase not allowedBypass Hooks (Emergency Only):
git commit --no-verify -m "emergency fix"VS Code Integration
Install the Conventional Commits extension for easier commit message creation:
- Extension ID:
vivaxy.vscode-conventional-commits - Use
Ctrl+Shift+P→ "Conventional Commits"
Configuration Files
commitlint.config.js- Commit message validation.husky/- Git hooks (pre-commit, pre-push, commit-msg).lintstagedrc.json- Lint-staged configuration.prettierrc.json- Code formatting rules.pre-commit-config.yaml- Python pre-commit (alternative)
Testing
# Run all tests
pnpm test
# Watch mode
pnpm run test:watch
# Coverage report
pnpm run test:coverageTesting CI Workflows Locally
Before pushing changes, it's recommended to test GitHub Actions workflows locally using act. This helps catch CI issues early and saves time by avoiding unnecessary commits.
Install act:
# macOS
brew install act
# Linux
curl -s https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash
# Windows (with chocolatey)
choco install act-cliRun workflows locally:
# Test all workflows
act
# Test specific job
act -j test
# Test docker build
act -j docker
# Run with verbose output
act -vNote: act requires Docker to be running. You may need to provide GitHub secrets via .secrets file for certain workflows.
Architecture
┌─────────────────┐
│ Next.js App │
│ (EuviaTracker) │
└────────┬────────┘
│ WebSocket
▼
┌─────────────────┐
│ Euvia Server │
│ Express + WS │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Redis Cache │
│ (5min TTL) │
└─────────────────┘
▲
│
┌────────┴────────┐
│ Admin Client │
│ (EuviaLiveStats)│
└─────────────────┘Roadmap
- [ ] Horizontal scaling with Redis Cluster
- [ ] Historical data export (CSV, JSON)
- [ ] Custom event tracking
- [ ] Geographic regions (country-level only)
- [ ] Referrer tracking (hashed)
- [ ] Session duration estimation
- [ ] GraphQL API support
Contributing
Contributions are welcome! Please read our Contributing Guide first.
# Fork and clone
git clone https://github.com/yourusername/euvia-nodejs
cd euvia-nodejs
# Create feature branch
git checkout -b feature/amazing-feature
# Make changes and test
pnpm test
# Commit and push
git commit -m "Add amazing feature"
git push origin feature/amazing-featureLicense
MIT License - see LICENSE file for details.
Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: Wiki
Credits
Built with:
- Socket.io - Real-time WebSocket communication
- Redis - High-performance data storage
- Express - Web server framework
- TypeScript - Type-safe development
Made with privacy in mind by Euvia Contributors
