v9.8 release post covering SNMP support, UI simplification, limitations, and where the project is heading. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
300 lines
12 KiB
HTML
300 lines
12 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Blog — The Other Dude</title>
|
|
<meta name="description" content="Updates, insights, and the occasional rant about open source MikroTik fleet management, network operations, and building software with AI.">
|
|
<meta name="keywords" content="MikroTik blog, RouterOS fleet management, MSP blog, network management blog">
|
|
<meta name="author" content="The Other Dude">
|
|
<meta name="robots" content="index, follow">
|
|
<meta name="theme-color" content="#eae7de">
|
|
<link rel="canonical" href="https://theotherdude.net/blog/">
|
|
<link rel="icon" href="../data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'><rect x='2' y='2' width='60' height='60' rx='8' fill='none' stroke='%238B1A1A' stroke-width='2'/><path d='M32 18 L46 32 L32 46 L18 32 Z' fill='%238B1A1A'/><path d='M32 19 L38 32 L32 45 L26 32 Z' fill='%232A9D8F'/><circle cx='32' cy='32' r='5' fill='%238B1A1A'/><circle cx='32' cy='32' r='2.5' fill='%232A9D8F'/></svg>">
|
|
|
|
<!-- Open Graph -->
|
|
<meta property="og:type" content="website">
|
|
<meta property="og:title" content="Blog — The Other Dude">
|
|
<meta property="og:description" content="Updates, insights, and the occasional rant about MikroTik fleet management, network operations, and building software with AI.">
|
|
<meta property="og:url" content="https://theotherdude.net/blog/">
|
|
<meta property="og:site_name" content="The Other Dude">
|
|
|
|
<!-- Fonts -->
|
|
|
|
<link rel="stylesheet" href="../style.css?v=3">
|
|
<style>
|
|
/* Warm Precision overrides */
|
|
:root {
|
|
--background: #eae7de;
|
|
--surface: #f6f4ec;
|
|
--elevated: #f0ede4;
|
|
--border: rgba(40,36,28,0.12);
|
|
--text-primary: #1a1810;
|
|
--text-secondary: #5e5a4e;
|
|
--text-muted: #8a8578;
|
|
--accent: #8a7a48;
|
|
}
|
|
body { background-color: #eae7de; color: #1a1810; }
|
|
.site-nav { background: #e0dcd2 !important; border-bottom: 1px solid rgba(40,36,28,0.12); }
|
|
.site-nav .nav-logo span, .site-nav .nav-link, .site-nav .nav-cta { color: #1a1810 !important; }
|
|
.site-nav .nav-link:hover { color: #8a7a48 !important; }
|
|
.dark { /* prevent dark mode */ }
|
|
</style>
|
|
<style>
|
|
.blog-index {
|
|
max-width: 720px;
|
|
margin: 0 auto;
|
|
padding: 80px 24px 120px;
|
|
}
|
|
.blog-index h1 {
|
|
font-family: "Manrope", sans-serif;
|
|
font-weight: 700;
|
|
font-size: 2.5rem;
|
|
color: var(--text-primary);
|
|
margin-bottom: 8px;
|
|
}
|
|
.blog-index .blog-subtitle {
|
|
color: var(--text-muted);
|
|
font-size: 1.05rem;
|
|
margin-bottom: 48px;
|
|
}
|
|
.blog-list {
|
|
list-style: none;
|
|
padding: 0;
|
|
margin: 0;
|
|
}
|
|
.blog-list li {
|
|
border-bottom: 1px solid var(--border);
|
|
padding: 24px 0;
|
|
}
|
|
.blog-list li:first-child {
|
|
border-top: 1px solid var(--border);
|
|
}
|
|
.blog-list a {
|
|
text-decoration: none;
|
|
display: block;
|
|
}
|
|
.blog-list a:hover .blog-list-title {
|
|
color: var(--accent);
|
|
}
|
|
.blog-list-date {
|
|
color: var(--text-muted);
|
|
font-size: 13px;
|
|
margin-bottom: 4px;
|
|
}
|
|
.blog-list-title {
|
|
font-family: "Manrope", sans-serif;
|
|
font-weight: 600;
|
|
font-size: 1.25rem;
|
|
color: var(--text-primary);
|
|
margin-bottom: 6px;
|
|
transition: color 0.2s ease;
|
|
}
|
|
.blog-list-excerpt {
|
|
color: var(--text-secondary);
|
|
font-size: 0.95rem;
|
|
line-height: 1.6;
|
|
}
|
|
@media (max-width: 480px) {
|
|
.blog-index h1 { font-size: 1.8rem; }
|
|
.blog-index { padding: 60px 20px 80px; }
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<nav class="site-nav">
|
|
<div class="nav-inner container">
|
|
<a href="../index.html" class="nav-logo">
|
|
<svg class="nav-logo-mark" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="32" height="32" aria-label="The Other Dude logo">
|
|
<rect x="2" y="2" width="60" height="60" rx="8" fill="none" stroke="#8B1A1A" stroke-width="2"/>
|
|
<rect x="6" y="6" width="52" height="52" rx="5" fill="none" stroke="#F5E6C8" stroke-width="1.5"/>
|
|
<rect x="8" y="8" width="48" height="48" rx="4" fill="#8B1A1A" opacity="0.15"/>
|
|
<path d="M32 8 L56 32 L32 56 L8 32 Z" fill="none" stroke="#8B1A1A" stroke-width="2"/>
|
|
<path d="M32 13 L51 32 L32 51 L13 32 Z" fill="none" stroke="#F5E6C8" stroke-width="1.5"/>
|
|
<path d="M32 18 L46 32 L32 46 L18 32 Z" fill="#8B1A1A"/>
|
|
<path d="M32 19 L38 32 L32 45 L26 32 Z" fill="#2A9D8F"/>
|
|
<path d="M19 32 L32 26 L45 32 L32 38 Z" fill="#F5E6C8"/>
|
|
<circle cx="32" cy="32" r="5" fill="#8B1A1A"/>
|
|
<circle cx="32" cy="32" r="2.5" fill="#2A9D8F"/>
|
|
<path d="M10 10 L16 10 L10 16 Z" fill="#2A9D8F" opacity="0.7"/>
|
|
<path d="M54 10 L54 16 L48 10 Z" fill="#2A9D8F" opacity="0.7"/>
|
|
<path d="M10 54 L16 54 L10 48 Z" fill="#2A9D8F" opacity="0.7"/>
|
|
<path d="M54 54 L48 54 L54 48 Z" fill="#2A9D8F" opacity="0.7"/>
|
|
</svg>
|
|
<span>The Other Dude</span>
|
|
</a>
|
|
<div class="nav-links">
|
|
<a href="../docs.html" class="nav-link">Docs</a>
|
|
<a href="index.html" class="nav-link">Blog</a>
|
|
<a href="https://github.com/staack/the-other-dude" class="nav-link" rel="noopener">GitHub</a>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<main>
|
|
<div class="blog-index">
|
|
<h1>Blog</h1>
|
|
<p class="blog-subtitle">Updates, insights, and the occasional rant about MikroTik fleet management.</p>
|
|
|
|
<ul class="blog-list">
|
|
<li>
|
|
<a href="snmp-works.html">
|
|
<div class="blog-list-date">March 22, 2026</div>
|
|
<div class="blog-list-title">SNMP Works (And the UI Got Out of the Way)</div>
|
|
<div class="blog-list-excerpt">v9.8 adds SNMP device monitoring. It polls real devices, collects real data, and shows it alongside your MikroTik fleet. The UI also got simpler.</div>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="500-devices-broke-the-api.html">
|
|
<div class="blog-list-date">March 21, 2026</div>
|
|
<div class="blog-list-title">500 Devices Broke the API</div>
|
|
<div class="blog-list-excerpt">The API container got OOM-killed under realistic load. Here's what happened, what was wrong, and how three config changes fixed it.</div>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="not-posting-on-reddit.html">
|
|
<div class="blog-list-date">March 19, 2026</div>
|
|
<div class="blog-list-title">Why I'm Not Posting This on Reddit</div>
|
|
<div class="blog-list-excerpt">I built something and I'm not posting it on Reddit, Hacker News, or anywhere that runs on upvotes. Here's why building in public on forums is a trap.</div>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="free-tier-cap.html">
|
|
<div class="blog-list-date">March 19, 2026</div>
|
|
<div class="blog-list-title">Free Is Now Capped at 250 Devices</div>
|
|
<div class="blog-list-excerpt">The free tier moved from "basically unlimited" to 250 devices. Here's why, what it means, and what hasn't changed.</div>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="100-simulated-routers.html">
|
|
<div class="blog-list-date">March 18, 2026</div>
|
|
<div class="blog-list-title">Found a Bug Running 100 Simulated Routers</div>
|
|
<div class="blog-list-excerpt">A 100-device simulation exposed a NATS JetStream memory issue caused by message retention behavior. Here's what happened, why, and the fix.</div>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="what-you-can-do-today.html">
|
|
<div class="blog-list-date">March 17, 2026</div>
|
|
<div class="blog-list-title">What You Can Do With It Today (And What You Can't)</div>
|
|
<div class="blog-list-excerpt">An honest look at what The Other Dude actually does today. No roadmap promises, no marketing. What works, what's rough, and what's missing entirely.</div>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="not-stable-software.html">
|
|
<div class="blog-list-date">March 16, 2026</div>
|
|
<div class="blog-list-title">This Is Not Stable Software</div>
|
|
<div class="blog-list-excerpt">The Other Dude is under active development. Things break, APIs change, and that's the point. Here's why, and when stability starts mattering.</div>
|
|
</a>
|
|
</li>
|
|
<li>
|
|
<a href="why-this-exists.html">
|
|
<div class="blog-list-date">March 15, 2026</div>
|
|
<div class="blog-list-title">Why This Exists</div>
|
|
<div class="blog-list-excerpt">The story behind The Other Dude: two decades of wanting better MikroTik fleet management, AI making it possible, and why I probably won't answer your email.</div>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</main>
|
|
|
|
<footer class="site-footer">
|
|
<div class="footer-inner container">
|
|
<div class="footer-brand">
|
|
<span class="footer-logo">
|
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="24" height="24" aria-hidden="true" style="vertical-align: middle; margin-right: 8px;">
|
|
<rect x="2" y="2" width="60" height="60" rx="8" fill="none" stroke="#8B1A1A" stroke-width="2"/>
|
|
<rect x="6" y="6" width="52" height="52" rx="5" fill="none" stroke="#F5E6C8" stroke-width="1.5"/>
|
|
<rect x="8" y="8" width="48" height="48" rx="4" fill="#8B1A1A" opacity="0.15"/>
|
|
<path d="M32 18 L46 32 L32 46 L18 32 Z" fill="#8B1A1A"/>
|
|
<path d="M32 19 L38 32 L32 45 L26 32 Z" fill="#2A9D8F"/>
|
|
<path d="M19 32 L32 26 L45 32 L32 38 Z" fill="#F5E6C8"/>
|
|
<circle cx="32" cy="32" r="5" fill="#8B1A1A"/>
|
|
<circle cx="32" cy="32" r="2.5" fill="#2A9D8F"/>
|
|
</svg>
|
|
The Other Dude
|
|
</span>
|
|
<span class="footer-copy">© 2026 The Other Dude. All rights reserved.</span>
|
|
</div>
|
|
<nav class="footer-links">
|
|
<a href="../docs.html">Docs</a>
|
|
<a href="index.html">Blog</a>
|
|
<a href="https://github.com/staack/the-other-dude" rel="noopener">GitHub</a>
|
|
<a href="mailto:license@theotherdude.net">Licensing</a>
|
|
</nav>
|
|
<p style="margin-top:12px;font-size:0.75em;color:#8a8578;text-align:center;">This site uses self-hosted, cookie-free analytics to measure page views and engagement. No personal data is collected or shared with third parties.</p>
|
|
</div>
|
|
</footer>
|
|
|
|
<script>
|
|
(function() {
|
|
var h = 'https://telemetry.theotherdude.net';
|
|
var p = location.pathname;
|
|
var t = document.title;
|
|
var r = document.referrer;
|
|
|
|
// Session page count via sessionStorage.
|
|
var sc = parseInt(sessionStorage.getItem('_tc_sc') || '0', 10) + 1;
|
|
sessionStorage.setItem('_tc_sc', sc);
|
|
|
|
// UTM params.
|
|
var sp = new URLSearchParams(location.search);
|
|
var us = sp.get('utm_source') || '';
|
|
var um = sp.get('utm_medium') || '';
|
|
var uc = sp.get('utm_campaign') || '';
|
|
|
|
// Pixel URL with all params.
|
|
var params = new URLSearchParams({
|
|
p: p, t: t, r: r,
|
|
sw: screen.width, sh: screen.height,
|
|
vw: innerWidth, vh: innerHeight,
|
|
tz: new Date().getTimezoneOffset(),
|
|
dpr: devicePixelRatio || 1,
|
|
touch: navigator.maxTouchPoints > 0 ? 1 : 0,
|
|
cd: screen.colorDepth,
|
|
plt: Math.round(performance.now()),
|
|
sc: sc
|
|
});
|
|
if (us) params.set('us', us);
|
|
if (um) params.set('um', um);
|
|
if (uc) params.set('uc', uc);
|
|
|
|
var ct = navigator.connection ? navigator.connection.effectiveType : '';
|
|
if (ct) params.set('ct', ct);
|
|
|
|
new Image().src = h + '/px?' + params.toString();
|
|
|
|
// Engagement tracking.
|
|
var startTime = performance.now();
|
|
var maxScroll = 0;
|
|
|
|
function getScrollDepth() {
|
|
var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
var docHeight = Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
|
|
var winHeight = innerHeight;
|
|
if (docHeight <= winHeight) return 100;
|
|
var pct = Math.round((scrollTop + winHeight) / docHeight * 100);
|
|
return Math.min(pct, 100);
|
|
}
|
|
|
|
window.addEventListener('scroll', function() {
|
|
var d = getScrollDepth();
|
|
if (d > maxScroll) maxScroll = d;
|
|
}, {passive: true});
|
|
|
|
// Send beacon on page hide.
|
|
function sendBeacon() {
|
|
var top = Math.round(performance.now() - startTime);
|
|
var data = new URLSearchParams({p: p, top: top, sd: maxScroll});
|
|
navigator.sendBeacon(h + '/px/beacon', data);
|
|
}
|
|
|
|
document.addEventListener('visibilitychange', function() {
|
|
if (document.visibilityState === 'hidden') sendBeacon();
|
|
});
|
|
window.addEventListener('pagehide', sendBeacon);
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|