<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: RadarixAI</title>
    <description>The latest articles on Forem by RadarixAI (@radarixai).</description>
    <link>https://forem.com/radarixai</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3889516%2F90d3f932-6947-498d-bc3d-02ecd923ddd8.jpeg</url>
      <title>Forem: RadarixAI</title>
      <link>https://forem.com/radarixai</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/radarixai"/>
    <language>en</language>
    <item>
      <title>Building a Practical AI Radar — notes from the state-management trenches</title>
      <dc:creator>RadarixAI</dc:creator>
      <pubDate>Tue, 12 May 2026 13:06:11 +0000</pubDate>
      <link>https://forem.com/radarixai/building-a-practical-ai-radar-notes-from-the-state-management-trenches-2n80</link>
      <guid>https://forem.com/radarixai/building-a-practical-ai-radar-notes-from-the-state-management-trenches-2n80</guid>
      <description>&lt;p&gt;When we started building &lt;a href="https://radarix.ai/" rel="noopener noreferrer"&gt;Radarix.ai&lt;/a&gt;, the visible product was always a map: layers of public-source signals stitched together so a person can see what's happening in air, at sea, and across borders in one glance.&lt;/p&gt;

&lt;p&gt;The interesting engineering, though, didn't end up living in the map. It lived in the boring layer underneath — the part nobody tweets about: &lt;strong&gt;state&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This post is a build-log on what we've learned trying to scale a live, multi-source monitoring product without drowning in our own automation.&lt;/p&gt;




&lt;h2&gt;
  
  
  The shape of the problem
&lt;/h2&gt;

&lt;p&gt;Most of us already know we &lt;em&gt;should&lt;/em&gt; be watching more signal streams than we are: launches in our space, competitor activity, new directory listings, mentions of our project, market shifts, source data we depend on. The reason we don't is operational, not technical: doing it manually doesn't scale, and doing it semi-automatically usually devolves into a graveyard of scripts that nobody dares to touch six months later.&lt;/p&gt;

&lt;p&gt;We hit the same wall, but with a louder version of it — our domain (live public-event monitoring) means signals are noisy, fast-moving, and contradictory. So we ended up reducing the entire operation to one loop:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;collect&lt;/strong&gt; relevant signals from public sources;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;classify&lt;/strong&gt; what actually matters from what's just noise;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;produce an action queue&lt;/strong&gt; for downstream work;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;automate the repeatable follow-up checks&lt;/strong&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;keep humans in approval control for anything public-facing&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It looks obvious written out. The hard part is step 3 onwards.&lt;/p&gt;




&lt;h2&gt;
  
  
  The real bottleneck wasn't filling forms
&lt;/h2&gt;

&lt;p&gt;We expected the slow part of "growth ops" to be browser automation — captcha walls, OAuth chains, ant-bot defenses. It is annoying, but it's not the bottleneck.&lt;/p&gt;

&lt;p&gt;The bottleneck is &lt;strong&gt;maintaining state&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For every external surface we touch — directories we submit to, public profiles, content feeds, third-party listings — we need to know, &lt;em&gt;with high confidence&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;where the project is registered (and under which account);&lt;/li&gt;
&lt;li&gt;what was submitted, when, with what payload;&lt;/li&gt;
&lt;li&gt;what is pending review, and how long it's been pending;&lt;/li&gt;
&lt;li&gt;what requires a manual step we haven't done yet;&lt;/li&gt;
&lt;li&gt;which public profile copy is stale relative to current product positioning.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without that registry, every cycle re-discovers what it should already know, re-submits things that shouldn't be re-submitted, and quietly accumulates a long tail of zombie listings nobody is tracking.&lt;/p&gt;

&lt;p&gt;So early on we made a deliberate, slightly boring choice: &lt;strong&gt;one source of truth, in SQLite&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;submissions&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt;              &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;target&lt;/span&gt;          &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;-- normalized URL of the surface&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt;          &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;    &lt;span class="c1"&gt;-- queued|in_progress|submitted|pending_review|registered|blocked&lt;/span&gt;
    &lt;span class="n"&gt;last_action_at&lt;/span&gt;  &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;last_evidence&lt;/span&gt;   &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;             &lt;span class="c1"&gt;-- URL or path to evidence file&lt;/span&gt;
    &lt;span class="n"&gt;blocker_reason&lt;/span&gt;  &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;             &lt;span class="c1"&gt;-- captcha|paywall|login_required|unclear_success&lt;/span&gt;
    &lt;span class="n"&gt;payload_ref&lt;/span&gt;     &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;             &lt;span class="c1"&gt;-- pointer to the prepared payload&lt;/span&gt;
    &lt;span class="n"&gt;ai_review&lt;/span&gt;       &lt;span class="nb"&gt;TEXT&lt;/span&gt;              &lt;span class="c1"&gt;-- last AI assessment of the evidence&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That table is the spine of the whole operation. Everything else — the browser workers, the AI review steps, the cron — reads from it and writes back into it. If we lose anything else, we can rebuild. If we lose the registry, we're starting over.&lt;/p&gt;




&lt;h2&gt;
  
  
  Two cheap browser worker VPSes do more than you'd expect
&lt;/h2&gt;

&lt;p&gt;We don't run browser automation on the control plane. The control plane is a small machine that holds the database, runs cron, and orchestrates work. The actual browser work lives on two &lt;strong&gt;separate, deliberately small VPSes&lt;/strong&gt; running Playwright inside Docker.&lt;/p&gt;

&lt;p&gt;Why two?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Concurrency&lt;/strong&gt; without contention on a single Xvfb session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IP / fingerprint diversification&lt;/strong&gt; for surfaces that quietly flag a single VPS doing 50 form fills in a row.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Failover&lt;/strong&gt; when one of them has a Playwright lockup, a disk fill, or just decides to be sad.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The controller distributes jobs in balanced mode — pick the worker with the lower in-flight count, fall back to the other on health check failure. If both die at the same time, the queue stays put; nothing gets corrupted because the registry didn't get its write yet.&lt;/p&gt;

&lt;p&gt;The lesson here turned out to be surprisingly generic: &lt;strong&gt;separate "work that can fail" from "state you can't lose"&lt;/strong&gt;. Browser work fails routinely. The registry has to not.&lt;/p&gt;




&lt;h2&gt;
  
  
  AI as a reviewer, not a doer
&lt;/h2&gt;

&lt;p&gt;We tried, briefly, the obvious thing: let a model drive the browser. It "worked" in the demo sense and broke in every interesting way: hallucinated buttons that didn't exist, claimed submissions succeeded based on a flash message that was actually an error, picked the wrong account on multi-tenant surfaces.&lt;/p&gt;

&lt;p&gt;What turned out to work much better was treating the model as a &lt;strong&gt;reviewer of evidence&lt;/strong&gt;, not a driver of actions.&lt;/p&gt;

&lt;p&gt;The flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Playwright collects the deterministic evidence — screenshots, HTML snapshots, final URL after submit, any visible message.&lt;/li&gt;
&lt;li&gt;A small classifier marks the surface as &lt;code&gt;submitted_clean&lt;/code&gt;, &lt;code&gt;pending_review&lt;/code&gt;, &lt;code&gt;blocked_captcha&lt;/code&gt;, &lt;code&gt;blocked_login&lt;/code&gt;, &lt;code&gt;unclear&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;The model is given the evidence + the classifier's guess and asked: &lt;em&gt;does this evidence actually support that label, or does it tell a different story?&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;The model's verdict gets written into &lt;code&gt;ai_review&lt;/code&gt; alongside the human-readable explanation.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This split — deterministic action, probabilistic review — is the cheapest way we found to get the upside of model judgment without paying for its over-confidence. The browser worker doesn't trust the model. The model doesn't trust the browser worker. The registry, slowly, trusts both.&lt;/p&gt;




&lt;h2&gt;
  
  
  Native cron beat n8n for our use case
&lt;/h2&gt;

&lt;p&gt;We started with a fancier scheduler. We removed it within a few weeks.&lt;/p&gt;

&lt;p&gt;Not because anything was wrong with it — it's a perfectly reasonable tool. It just didn't fit our shape. Our scheduling needs are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"every two hours, run one well-defined cycle, hold a flock so it doesn't overlap";&lt;/li&gt;
&lt;li&gt;"every twelve hours, recheck the things we claimed were pending and confirm or downgrade them";&lt;/li&gt;
&lt;li&gt;"every hour, sweep memory and aggregate state into one digest";&lt;/li&gt;
&lt;li&gt;"once a day, write an audit and report it".&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That fits a &lt;code&gt;*/2 * * *&lt;/code&gt; crontab line and a &lt;code&gt;flock -n /tmp/cycle.lock ./cycle.sh&lt;/code&gt; invocation. No visual graph required. The lesson we keep relearning is &lt;strong&gt;boring beats clever&lt;/strong&gt; when the operational interface is "did the thing run? what did it write?"&lt;/p&gt;

&lt;p&gt;There's a related subtlety we got bitten by, which is worth one paragraph on its own:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When a cron job's command pipes a 25-minute pipeline into &lt;code&gt;| tail -200&lt;/code&gt; at the end, &lt;code&gt;tail&lt;/code&gt; doesn't print anything until EOF. If something downstream of cron (a runner, a watcher, an LLM CLI) has a "no output for N seconds → kill" rule, you'll kill the process before it ever produces output. Diagnosis: command runs for exactly the idle timeout, dies, no log lines. Fix: stream output directly, or emit a heartbeat line every 30–60s from a wrapper. We discovered this the unglamorous way.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Humans stay in the loop for public actions
&lt;/h2&gt;

&lt;p&gt;This is the one rule we won't compromise on, and it's why our throughput targets are deliberately modest.&lt;/p&gt;

&lt;p&gt;The system can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;prepare drafts of public posts;&lt;/li&gt;
&lt;li&gt;detect stale profile copy;&lt;/li&gt;
&lt;li&gt;queue listing updates;&lt;/li&gt;
&lt;li&gt;propose tone changes for a given audience;&lt;/li&gt;
&lt;li&gt;assemble a publish-ready payload with image, title, body, and metadata.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The system cannot:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;publish the post;&lt;/li&gt;
&lt;li&gt;create a new account on a sensitive surface;&lt;/li&gt;
&lt;li&gt;pay for placements;&lt;/li&gt;
&lt;li&gt;bypass captchas or anti-bot defenses on a paid solver;&lt;/li&gt;
&lt;li&gt;post in a community under a borrowed identity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The reason is straightforward: &lt;strong&gt;automation that publishes is hard to recall&lt;/strong&gt;. The internet remembers. Even a single misaligned post on a small subreddit can poison a launch for that surface for months. So we wire approval gates anywhere a public action would be observable, and we make the human review fast: a short summary, the exact text, the destination, and a yes/no.&lt;/p&gt;

&lt;p&gt;What surprised us was how much we &lt;em&gt;don't&lt;/em&gt; lose by doing this. Most of the throughput in submission/visibility work is in the prep — finding the right surface, finding the right copy, finding the right account, queuing the right payload. The actual "press publish" step is seconds. The bottleneck was never the human; it was every step before them.&lt;/p&gt;




&lt;h2&gt;
  
  
  A few lessons we'd give our six-month-ago selves
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Pick a source of truth on day one.&lt;/strong&gt; Not on day forty when the contradictions become unworkable. A single SQLite file is fine. The schema can grow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Separate work that fails from state that can't.&lt;/strong&gt; Browser/network failures are routine. Don't let them touch the registry directly — they go through a write step you control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use the model as a reviewer.&lt;/strong&gt; Probabilistic verdict on deterministic evidence is much more reliable than the reverse.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Heartbeat your long-running jobs.&lt;/strong&gt; Anything that runs for more than ~5 minutes without producing output will be killed by something — a runner, a sidecar, a watchdog. Print something every minute or get used to mysterious mid-pipeline deaths.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Approval gates are cheaper than retractions.&lt;/strong&gt; Build the human-in-the-loop early; it's much harder to bolt on after you have an embarrassing post you have to apologize for.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  What we're building toward
&lt;/h2&gt;

&lt;p&gt;A practical operating system for monitoring, submission, content maintenance, and public-channel updates — one that runs as a small, observable, mostly-boring stack you can reason about end to end. Not a pile of agents that surprise you. Not a no-code graph that nobody can debug at 2am.&lt;/p&gt;

&lt;p&gt;If you're building something in this space — growth ops, OSINT tooling, monitoring products, anything that has to talk to a lot of external surfaces and not lose its mind — I'd love to compare notes. The state-management trenches are lonely; everyone re-discovers them.&lt;/p&gt;

&lt;p&gt;Live product: &lt;a href="https://radarix.ai/" rel="noopener noreferrer"&gt;radarix.ai&lt;/a&gt; (free, no signup, OSINT radar covering aviation, maritime, and cross-border signals).&lt;/p&gt;

&lt;p&gt;— RadarixAI&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>automation</category>
      <category>ai</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Radarix.ai — a live OSINT radar for missiles, drones, aviation and maritime. Free.</title>
      <dc:creator>RadarixAI</dc:creator>
      <pubDate>Tue, 12 May 2026 01:12:56 +0000</pubDate>
      <link>https://forem.com/radarixai/radarixai-a-live-osint-radar-for-missiles-drones-aviation-and-maritime-free-1m6k</link>
      <guid>https://forem.com/radarixai/radarixai-a-live-osint-radar-for-missiles-drones-aviation-and-maritime-free-1m6k</guid>
      <description>&lt;p&gt;There are a lot of "war maps" online right now. Most do one of two things badly: they cover a single front (just Ukraine, just Israel-Gaza, etc.), or they're locked behind enterprise pricing nobody on the open OSINT side can afford.&lt;/p&gt;

&lt;p&gt;We started building &lt;strong&gt;&lt;a href="https://radarix.ai/" rel="noopener noreferrer"&gt;Radarix.ai&lt;/a&gt;&lt;/strong&gt; because we kept hitting the same operational gap: when an alert lands in your feed, you have &lt;em&gt;seconds&lt;/em&gt; to triangulate it across air, sea, and ground signal — and there's no one place that gives you all of those at once, in near real-time, for free.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it actually is
&lt;/h2&gt;

&lt;p&gt;Radarix.ai is a live aggregated OSINT radar. One map, multiple domains:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🚀 &lt;strong&gt;Missile alerts&lt;/strong&gt; — strikes, launches, regional warnings&lt;/li&gt;
&lt;li&gt;🛩️ &lt;strong&gt;Drone activity&lt;/strong&gt; — military UAVs, civilian anomalies, swarm reports&lt;/li&gt;
&lt;li&gt;✈️ &lt;strong&gt;Aviation&lt;/strong&gt; — ADS-B, unusual flight patterns, no-fly violations&lt;/li&gt;
&lt;li&gt;🚢 &lt;strong&gt;Maritime&lt;/strong&gt; — AIS, ship detentions, gaps, blockades, oil incidents&lt;/li&gt;
&lt;li&gt;⚠️ &lt;strong&gt;Cross-border events&lt;/strong&gt; — artillery, infiltration, military buildup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The whole point is &lt;em&gt;aggregation&lt;/em&gt;. Instead of bouncing between Flightradar24, MarineTraffic, a dozen OSINT Telegram channels, and Janes when you can afford it — you get one map.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it's free
&lt;/h2&gt;

&lt;p&gt;Right now: 100% free. No paywall, no tiers. We're not a B2B intelligence product (at least not yet). Most of the data pipelines already existed from prior work, and the marginal cost of running the public-facing map is small enough that we'd rather have &lt;em&gt;coverage&lt;/em&gt; than &lt;em&gt;revenue&lt;/em&gt; in this phase.&lt;/p&gt;

&lt;p&gt;There's also no "personal data" angle. Radarix.ai does not expose private information, does not track individuals, and has no "find this person" mode. It's situational awareness on civilian-relevant events, period.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's under the hood
&lt;/h2&gt;

&lt;p&gt;A few light tech notes (deeper write-ups in the next posts):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live air picture&lt;/strong&gt; — ADS-B feeds; we lean on open community feeds like &lt;code&gt;adsb.lol&lt;/code&gt; where licensing permits, plus standard commercial routes for fill-in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maritime layer&lt;/strong&gt; — AIS data; MarineTraffic is whitelisted in our CSP allowlist for embedded ship detail views.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OSINT layer&lt;/strong&gt; — a deduplicated, scored aggregation of conflict-relevant signal from public sources: structured news APIs, monitored Telegram channels, sanctioned-ship registers, official advisories.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verification posture&lt;/strong&gt; — pipelines explicitly flag &lt;em&gt;unverified&lt;/em&gt; events; we'd rather show "reported, unconfirmed" than fabricate certainty just to make the dashboard feel populated.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multilingual&lt;/strong&gt; — EN primary, summaries in additional languages so the map is useful outside English-speaking newsrooms.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Who this is for
&lt;/h2&gt;

&lt;p&gt;A wider net than most OSINT tools openly admit aiming at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OSINT analysts and verification teams who need a quick cross-domain pulse&lt;/li&gt;
&lt;li&gt;Journalists and war reporters tracking unfolding events&lt;/li&gt;
&lt;li&gt;Maritime traders watching for incident-driven volatility&lt;/li&gt;
&lt;li&gt;Civilians in regions of active threat who want a single "what's happening within X km of me" dashboard&lt;/li&gt;
&lt;li&gt;Security teams that don't have a six-figure intel subscription budget&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;Active work:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Faster source onboarding — when a new front opens, coverage should follow in hours, not weeks&lt;/li&gt;
&lt;li&gt;Richer aviation/maritime cross-referencing (e.g. spotting vessel-aircraft patterns that suggest intercept activity)&lt;/li&gt;
&lt;li&gt;Developer access — if you build OSINT tools and want a structured feed to subscribe to, get in touch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you work in this space — try the map at &lt;a href="https://radarix.ai/" rel="noopener noreferrer"&gt;radarix.ai&lt;/a&gt;, and tell us where it's wrong, where it's slow, and what should be on it that isn't.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This is the first build-log post from Radarix.ai. Coming next: deep dives on the data pipeline — ADS-B at scale, AIS gap detection, and OSINT signal scoring.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>osint</category>
      <category>opensource</category>
      <category>geospatial</category>
      <category>datascience</category>
    </item>
  </channel>
</rss>
