DEV Community

InkFusion Labs
InkFusion Labs

Posted on

I Built a Website Tracker This Weekend — Here's What I Learned

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';
    }
}
Enter fullscreen mode Exit fullscreen mode

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');
}
Enter fullscreen mode Exit fullscreen mode

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) : [];
}
Enter fullscreen mode Exit fullscreen mode

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)}`;
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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('');
}
Enter fullscreen mode Exit fullscreen mode

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

  1. 5-Star Rating System — Rate websites for quick reference
  2. Keyboard Shortcuts — Power-user friendly (Ctrl+N, Ctrl+F, etc.)
  3. Export/Import — Backup your data as JSON
  4. Device Tracking — See if you access sites from desktop/mobile/tablet
  5. Return Visit Rate — Analytics on repeat visits
  6. Glassmorphism UI — Modern, clean design

What I'd Do Differently

  1. IndexedDB — For larger datasets and better performance
  2. Service Worker — For true offline functionality
  3. WebSockets — For real-time status updates (if I added a backend)
  4. Testing — Add unit tests for core functionality
  5. TypeScript — For better code maintainability

Try It Out

Visit the live demo and:

  1. Add a few websites
  2. Visit them a few times
  3. Check out the analytics dashboard
  4. 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)