As a developer juggling multiple client websites, I was frustrated with traditional bookmark managers. They don't track visits, show status, or provide analytics. So I built SiteOps — a clean, local-first website monitoring dashboard.
The Problem
I needed to:
- Track which sites I visit most
- Monitor site status (up/down)
- Organize sites by project/client
- See usage patterns and analytics
- Keep everything local (no cloud, no accounts)
Existing tools were either too complex, required sign-ups, or lacked the features I needed.
The Solution: SiteOps
SiteOps is a vanilla JavaScript web app that runs entirely in your browser. All data stays local using localStorage — no backend, no database, no accounts required.
Live Demo: https://siteops-io.netlify.app
Source Code: https://github.com/inkFusionLabs/siteops
Tech Stack
- Vanilla HTML/CSS/JavaScript — No frameworks, no build process
- Chart.js — For analytics visualizations
- localStorage — Client-side data persistence
- PWA-ready — Installable as a web app
Key Features
1. Real-Time Status Monitoring
Each website card shows live status (online/offline) with visual indicators:
async checkWebsiteStatus(url) {
try {
const proxyUrl = `https://api.allorigins.win/get?url=${encodeURIComponent(url)}`;
const response = await fetch(proxyUrl, {
method: 'GET',
signal: controller.signal
});
return response.ok ? 'online' : 'offline';
} catch (error) {
return 'offline';
}
}
2. Visit Tracking & Analytics
Tracks every visit with timestamps, device types, and patterns:
visitWebsite(url) {
const website = this.websites.find(w => w.url === url);
if (website) {
website.visits = (website.visits || 0) + 1;
website.lastVisited = new Date().toISOString();
// Track device type
website.visitHistory.push({
timestamp: new Date().toISOString(),
deviceType: this.getDeviceType(),
hour: new Date().getHours()
});
this.saveWebsites();
}
window.open(url, '_blank');
}
3. Comprehensive Analytics Dashboard
Built with Chart.js to visualize:
- Visit trends over 30 days
- Category breakdowns
- Device usage (desktop/mobile/tablet)
- Most visited websites
- Peak usage hours and days
4. Local-First Architecture
All data persists in localStorage:
saveWebsites() {
localStorage.setItem('websiteTracker', JSON.stringify(this.websites));
}
loadWebsites() {
const stored = localStorage.getItem('websiteTracker');
return stored ? JSON.parse(stored) : [];
}
Challenges & Learnings
Challenge 1: CORS for Status Checking
Problem: Can't directly fetch websites due to CORS restrictions.
Solution: Used a CORS proxy service (allorigins.win) for status checks. Not perfect, but works for basic monitoring.
const proxyUrl = `https://api.allorigins.win/get?url=${encodeURIComponent(url)}`;
Learning: Browser security is strict for good reasons, but it makes client-side monitoring tricky.
Challenge 2: Responsive Design Without Frameworks
Problem: Making a complex dashboard responsive with pure CSS.
Solution: CSS Grid with repeat(auto-fit, minmax()) for flexible layouts:
.websites-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
gap: 20px;
}
Learning: Modern CSS Grid is powerful enough for most layouts without frameworks.
Challenge 3: Data Persistence
Problem: Ensuring data survives browser restarts.
Solution: localStorage with automatic save on every action. Added export/import for backup.
Learning: localStorage is reliable but has size limits (~5-10MB). For larger datasets, IndexedDB would be better.
Challenge 4: Real-Time Updates
Problem: Updating UI without page refresh.
Solution: Event-driven architecture with manual DOM updates:
renderWebsites() {
const filtered = this.getFilteredWebsites();
grid.innerHTML = filtered.map(website =>
this.createWebsiteCard(website)
).join('');
}
Learning: Vanilla JS can handle complex UIs, but state management gets tricky at scale.
Design Decisions
Why Vanilla JavaScript?
- Simplicity: No build process, no dependencies
- Performance: Fast load times, minimal bundle size
- Learning: Better understanding of fundamentals
- Portability: Works anywhere HTML/CSS/JS works
Why localStorage?
- Privacy: Data never leaves the browser
- Simplicity: No backend infrastructure needed
- Speed: Instant saves/loads
- Offline: Works without internet after first load
Why Chart.js?
- Easy integration: CDN, no build step
- Good defaults: Looks professional out of the box
- Flexible: Customizable when needed
Features That Make It Special
- 5-Star Rating System — Rate websites for quick reference
- Keyboard Shortcuts — Power-user friendly (Ctrl+N, Ctrl+F, etc.)
- Export/Import — Backup your data as JSON
- Device Tracking — See if you access sites from desktop/mobile/tablet
- Return Visit Rate — Analytics on repeat visits
- Glassmorphism UI — Modern, clean design
What I'd Do Differently
- IndexedDB — For larger datasets and better performance
- Service Worker — For true offline functionality
- WebSockets — For real-time status updates (if I added a backend)
- Testing — Add unit tests for core functionality
- TypeScript — For better code maintainability
Try It Out
Visit the live demo and:
- Add a few websites
- Visit them a few times
- Check out the analytics dashboard
- Export your data
All your data stays in your browser — completely private and local.
Open Source
SiteOps is open source and available on GitHub. Contributions welcome!
Final Thoughts
Building SiteOps taught me:
- Vanilla JS can build complex apps
- localStorage is powerful for local-first apps
- Good UX matters more than frameworks
- Sometimes the best solution is the simplest one
If you're tracking multiple websites, give SiteOps a try. And if you have feedback or suggestions, I'd love to hear them!
Tags: #javascript #webdev #productivity #opensource #pwa #localstorage #analytics #webdevelopment
Top comments (0)