1pxsolidblackhttps://1pxsolidblack.pl/2020-05-15T18:14:00+02:00capital FJARR v32020-05-15T18:14:00+02:002020-05-15T18:14:00+02:00François Schmidtstag:1pxsolidblack.pl,2020-05-15:/jarr-v3-en.html<p>First of all, the new app is available here: <a href="https://app.jarr.info">app.jarr.info</a> for you to test !</p>
<h4>Preambule</h4>
<p><span class="caps">JARR</span> is a news aggregator and reader.
<span class="caps">JARR</span> stands for <em>Just Another <span class="caps">RSS</span> Reader</em> and I’ve been personnally using and developing it for the past years.</p>
<p>After a v2 silently released several …</p><p>First of all, the new app is available here: <a href="https://app.jarr.info">app.jarr.info</a> for you to test !</p>
<h4>Preambule</h4>
<p><span class="caps">JARR</span> is a news aggregator and reader.
<span class="caps">JARR</span> stands for <em>Just Another <span class="caps">RSS</span> Reader</em> and I’ve been personnally using and developing it for the past years.</p>
<p>After a v2 silently released several years ago, this time I’m making a true release.
Before getting into the new things brought by this v3, I’ll talk a bit about what was brought by the precedent version.
The v2 introduced very discretly and only by opting-in what I called <em>clusters</em> which are grouped articles.</p>
<h2>Clusters</h2>
<p>The root idea was that <em>several feeds may reference a unique resource</em>.
On this base I implemented at the time a way to represent that in <span class="caps">JARR</span>.
At each article creation, <span class="caps">JARR</span> will list the more or less recent user’s articles and will check if they do link to the same resource.
If so, the newly created article will be added to the existing cluster, inheriting logically of its status (read or unread, liked or not).</p>
<p>The original goal was to reduce the meta-feed (the feed created by all the feeds of a user) by reducing redundancy.
It’s very useful when subscribing to <a href="https://en.wikipedia.org/wiki/Planet_(software)">planets</a>, news aggregator (like <a href="https://news.ycombinator.com/">Hacker News</a>) or even <em>subreddits</em>.</p>
<p>To add to this grouping processus only based on links, a colleague proposed to go further and to group articles based on their content so we would group article treating identical subjects. It’s done through <a href="https://en.wikipedia.org/wiki/Tf%E2%80%93idf">tf-idf</a>.
It allows for example to group articles from national news outlet which are destined by essence to treat the same subjects.</p>
<h4>Clusters: lesson learned</h4>
<p>All of this was pretty experimental, and at the time I only put in place the one option to opt in or out.
I rapidly discovered that :</p>
<ul>
<li>
<p>A feed might always have one link, and only update the resource at the end of that link.
This causes all the articles of that feed to get clustered together.
The lesson from that is that a <em>feed by feed</em> control of the clustering is needed.</p>
</li>
<li>
<p>Filing the feeds under different categories allows, among other things, to mark as read entire categories.
Clustering is independant from category and sometimes article from other categories that you wanted to read later got marked as read while marking a whole category as read.
This implies two evolutions : it’s necessary to be able to deactivate clustering for a category and it’s necessary to be able to mark only article not belonging to clusters as read.</p>
</li>
<li>
<p>The reverse is also true, when clustering on an already read article happen, the new article won’t every be shown to the user.
Knowing that we made it so that if an article is clustered with an article marked as read but not really read, <span class="caps">JARR</span> will change the read status of the whole cluster to unread.
Like the rest this behavior can be disabled feed by feed.</p>
</li>
<li>
<p>The process in charge of refreshing feed in v2 did entierly by pushing <span class="caps">HTTP</span> request.
As clustering can be a somewhat time consuming process, some problems occured :</p>
<ul>
<li>
<p>Clustering, especially through tf-idf, was creating timeout errors</p>
</li>
<li>
<p>Several clustering process were executed in parallel. This meant that potentially, article were treated at the same time and missed each other when they should have been clustered together.</p>
</li>
</ul>
</li>
<li>
<p>Introducing clusters to <span class="caps">JARR</span> brought a lot of complexity in the model.
The most recurring complaint I got from users were that feed deletion began to take an awful lot of time.
The new version bring a new workflows where, when deleted, a feed is hidden and removed by a background worker.</p>
</li>
</ul>
<h1>What’s new in <span class="caps">JARR</span> v3</h1>
<h5>Background workers</h5>
<p>On very technical and backend point of view, the new version of <span class="caps">JARR</span> runs now on Docker.
Three of them to be accurate : <a href="https://hub.docker.com/repository/docker/jaesivsm/jarr-front">one</a> to serv the Javascript <span class="caps">UI</span>, <a href="https://hub.docker.com/repository/docker/jaesivsm/jarr-server">one</a> to serv data to this <span class="caps">UI</span> and a last <a href="https://hub.docker.com/repository/docker/jaesivsm/jarr-worker">one</a> which is a multitask background worker.</p>
<p>The last one runs a <a href="http://www.celeryproject.org/">Celery</a> worker which listens on a <a href="https://www.rabbitmq.com/">RabbitMQ</a> queue.</p>
<p>Its main goal is to refresh feeds according to several configuration options.
It has also the mission to cluster all pending articles. To avoid collision only one clustering process is ran by user at the same time.
At last, the worker remove pending feed suppression. Indeed, to make the operation virtually instantaneous for the user, the deleted feed are merely hidden from the user and deleted in the background when the worker has time.</p>
<h5>The user interface</h5>
<p>I wrote the first version of the interface with React 0.14.
I did let the project aside for a while and by the time I got back to it, React was already at version 14.
Needless to say that the then-coded <span class="caps">UI</span> was not salvageable.</p>
<p>I just recently finished rewriting all from scratch.
This time, with the idea of responsiveness and mobile devices in mind.
Front-end not being among my strengths, I want to thank <a href="https://github.com/clarissecarzon">Clarisse</a> without whom the interface would still look like bootstrap from 2015.</p>
<p>I also would like to thank another old colleague of mine, who made a very insightful <a href="https://github.com/jaesivsm/JARR/issues/127">code review</a>.
You have to pay attention to the details, but reading his review was enlighting to me.</p>
<h5>Overall</h5>
<p>Here’s a more exhaustive list of what has been done:</p>
<p>User eXperience:</p>
<div>
<img src="https://1pxsolidblack.pl/img/jarr/jarr-v3.jpg"
alt="an overlook of the new interface in JARRv3"
style="width: 75%; margin: auto; display: block;" />
</div>
<ul>
<li>A better interface for building and adding feeds.
Like in the v2, <span class="caps">JARR</span> is gonna try to construct a feed from any given <span class="caps">URL</span> (without scheme : <code>reddit.com/r/france</code> or even if the <span class="caps">URL</span> doesn’t link to a <span class="caps">RSS</span> or <span class="caps">JSON</span> feed : <code>https://www.reddit.com/r/france</code>).
Not like in v2, this time the feed isn’t created as soon as the form is submited.
Instead the feed is builded by the backend and sent back in a pre-filled form to the <span class="caps">UI</span>.</li>
</ul>
<p><img src="https://1pxsolidblack.pl/img/jarr/jarr-v3-feed-building.png"
alt="Screenshot of the first feed creation form"
style="width: 300px; margin: auto; display: block;" />
</div></p>
<ul>
<li>
<p>Change in the feed deletion processus: the feedback is now instantaneous and asynchronous.</p>
</li>
<li>
<p>Clustering option at feed, category and user level :
It’s now possible to chose if the article from a feed, a category (or all the articles) can be clustered or not.
It’s also possible to disable clustering through tf-idf and article wake up (marking a read feed as unread) by clustering.</p>
</li>
</ul>
<div>
<img src="https://1pxsolidblack.pl/img/jarr/jarr-v3-edit-cluster-option.jpg"
alt="Screenshot of the article grouping options"
style="width: 300px; margin: auto; display: block;" />
</div>
<ul>
<li>Proccessed content integration (only for images of youtube link for now).
If a type of supported content is recognized, <span class="caps">JARR</span> interface will create and integration for it.</li>
</ul>
<div>
<img src="https://1pxsolidblack.pl/img/jarr/jarr-v3-img-processed-content.jpg"
alt="Screenshot of preprocessed content in the JARR interface"
style="width: 300px; margin: auto; display: block;" />
</div>
<ul>
<li>Responsive design (feed menu can be hidden and article list comes in two versions: for large screen and for narrow ones).</li>
</ul>
<div>
<img src="https://1pxsolidblack.pl/img/jarr/jarr-v3-narrow-view.jpg"
alt="Screenshot of the JARR interface in narrow mode"
style="width: 300px; margin: auto; display: block;" />
</div>
<ul>
<li>A limited integration with <a href="https://github.com/RSS-Bridge/rss-bridge"><span class="caps">RSS</span>-Bridge</a> has also been realized so that <span class="caps">JARR</span> can figure out a way to serv content for website that doesn’t provide <span class="caps">RSS</span> feed.
For now, only Twitter, Instagram and Soundcloud are supported.</li>
</ul>
<p><img src="https://1pxsolidblack.pl/img/jarr/jarr-v3-rss-bridge-integration.png"
alt="Screenshot of an instagram feed through RSS-bridge"
style="width: 300px; margin: auto; display: block;" />
</div></p>
<ul>
<li>Edition in a dedicated panel for feed, categories, and user settings.</li>
</ul>
<div>
<img src="https://1pxsolidblack.pl/img/jarr/jarr-v3-edit-user.jpg"
alt="Screenshot of edition of user settings"
style="width: 350px; margin: auto; display: block;" />
</div>
<p>Server side:</p>
<ul>
<li>From scratch rewrite of the <span class="caps">API</span> through <a href="flask-restx.readthedocs.io/">Flask-restx</a></li>
<li><span class="caps">API</span> accessible via Swagger at <a href="https://api.jarr.info/">api.jarr.info</a></li>
<li>Removing of a lot of dead code and dependencies</li>
<li>Json feeds are now supported</li>
<li>Total rewrite of the <em>crawler</em></li>
<li>Drop of <a href="http://munin-monitoring.org/">munin</a> integration for a <a href="https://prometheus.io/">prometheus</a> one</li>
</ul>
<p>This last point allows me, among other things, to see globally how <span class="caps">JARR</span> handles freshness of feeds :</p>
<div>
<img src="https://1pxsolidblack.pl/img/jarr/last-fetched-histogram.jpg"
alt="histrogram of delays between refreshing of a same feed"
style="width: 75%; margin: auto; display: block;" />
</div>
<h2>What’s to come</h2>
<p>Of course, development continues ! In priority (for the <a href="https://github.com/jaesivsm/JARR/milestone/10">v3.1</a>), I’ll work on features present in v2 and missing for v3:</p>
<ul>
<li>
<p>Import and export of <span class="caps">OPML</span> archives (<a href="https://github.com/jaesivsm/JARR/issues/130">github</a>)</p>
</li>
<li>
<p>Search through articles in the menu (<a href="https://github.com/jaesivsm/JARR/issues/129">github</a>)</p>
</li>
</ul>
<p>I still have a lot of ideas for new functionalities like orderable and drag-n-dropable categories.</p>
<p>I am also of course open to suggestions.
Don’t hesitate to comment below or open an issue on the <a href="https://github.com/jaesivsm/JARR/issues">bug tracker</a> if encounter any problem or whish for a new functionality.</p>MindYourNeighbors2017-03-07T14:57:00+02:002017-03-07T14:57:00+02:00François Schmidtstag:1pxsolidblack.pl,2017-03-07:/mindyourneighbors-en.html<p>I <a href="https://github.com/jaesivsm/MindYourNeighbors/">wrote</a>, <a href="https://pypi.python.org/pypi/MindYourNeighbors/">packaged</a> and just finished <a href="https://travis-ci.org/jaesivsm/MindYourNeighbors">testing</a> <strong>MindYourNeighbors</strong>, a piece of software which allows you to run scripts depending on your network neighborhood.</p>
<h3>Why ?</h3>
<p>Several years ago, I used <a href="https://transmissionbt.com/">transmission</a> on a machine at home; it was running constantly. Transmission has a <em>turtle</em> mode which reduce its network bandwith consumption …</p><p>I <a href="https://github.com/jaesivsm/MindYourNeighbors/">wrote</a>, <a href="https://pypi.python.org/pypi/MindYourNeighbors/">packaged</a> and just finished <a href="https://travis-ci.org/jaesivsm/MindYourNeighbors">testing</a> <strong>MindYourNeighbors</strong>, a piece of software which allows you to run scripts depending on your network neighborhood.</p>
<h3>Why ?</h3>
<p>Several years ago, I used <a href="https://transmissionbt.com/">transmission</a> on a machine at home; it was running constantly. Transmission has a <em>turtle</em> mode which reduce its network bandwith consumption when it’s activated. I triggered that mode which two <a href="https://en.wikipedia.org/wiki/Cron">cron</a> lines. I set them so they would trigger the “turtle” mode when I knew they were people at home.
For various reasons, it becomed uneasy to anticipate the period when there was nobody’s home and so, in the end, transmission was always in its <em>turtle</em> mode.</p>
<h3>And so, why ?</h3>
<p>So, instead of using cron, I wrote a small script that watches the neighbors table and decide if it can run or not a script that’ll set or unset the transmission <em>turtle</em> mode.
After that I just made it so that any script could be triggered that way following a simple configuration file.</p>
<p>After I left it ran on my home linuxbox and saw it was working fine, I <a href="https://codeclimate.com/github/jaesivsm/MindYourNeighbors">cleaned</a> it up, added some tests, build a <a href="https://pypi.python.org/pypi/MindYourNeighbors/">python egg on pipy</a> and did some nice integration on <a href="https://github.com/jaesivsm/MindYourNeighbors">github</a>.</p>
<h3>How ?</h3>
<p>The principle of the script is fairly simple. It’ll run <code>ip neigh show</code> and will analyse its output line by line. If a line has the <code>REACHABLE</code> or <code>PERMANENT</code> mark, it’s considered that we have a neighbor. It’ll then pass through some filters which will exclude it or not.</p>
<p>Filters are defined in a configuration file where all section inherit from the default section.
Here is a commented and edited version of my configuration file:</p>
<div class="highlight"><pre><span></span><code><span class="k">[DEFAULT]</span>
<span class="na">threshold</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">4</span>
<span class="c1"># by default, only my pc will be considered as a neighbor</span>
<span class="na">filter_on_machines</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">my_pc</span>
<span class="c1"># you can also do some broader filter</span>
<span class="c1"># filter_on_regex = .*192\.168\.0\..* # for example this will allow you to consider as neighbor all the IPv4 address of the class B</span>
<span class="c1"># this section allows you to register device by their mac addresses</span>
<span class="c1"># if you want to filter them by name in the</span>
<span class="c1"># filter_on_machines and filter_out_machines paramters</span>
<span class="k">[known_machines]</span>
<span class="na">my_pc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s"><mac></span>
<span class="na">my_tel</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s"><mac></span>
<span class="k">[transmission]</span>
<span class="c1"># activate the "turtle" mode when there is neighbors</span>
<span class="na">command_neighbor</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">/my/scripts/transmission-turtle true</span>
<span class="c1"># desactivate it when there is none</span>
<span class="na">command_no_neighbor</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">/my/scripts/transmission-turtle false</span>
<span class="k">[bitcoind]</span>
<span class="c1"># you can desactivate a section without having to delete it</span>
<span class="c1"># from the configuration file</span>
<span class="na">enabled</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">false</span>
<span class="na">command_neighbor</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">killall bitcoind</span>
<span class="na">command_no_neighbor</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">/opt/bitcoind -server -daemon</span>
<span class="c1"># for both section above, filters are inherited from the default section</span>
<span class="k">[wake_computer]</span>
<span class="c1"># but here, I override that default value to only filter on my_tel</span>
<span class="na">filter_on_machines</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">my_tel</span>
<span class="c1"># again, we override the default value as we don't want to wait 4 cycles</span>
<span class="na">threshold</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">2</span>
<span class="c1"># we restrict time period during which this section is activated</span>
<span class="c1"># with a cron like syntax</span>
<span class="na">cron</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">* 18-23 * * 1-5</span>
<span class="na">command_neighbor</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">wake my machine</span>
</code></pre></div>
<p>The package also provides a script that you can run from anywere: <code>myn</code>. This script, run with the <code>--output</code> and <code>--verbose</code> verbose options allows you to easily run through a buggy configuration file and analyse what you would want to match and what doesn’t match.</p>
<div class="highlight"><pre><span></span><code><span class="gp"># </span>myn<span class="w"> </span>-o<span class="w"> </span>-v
<span class="go">MindYourNeighbors: INFO - MindYourNeighbors initialized</span>
<span class="go">MindYourNeighbors: DEBUG - 'transmission' - processing section</span>
<span class="go">MindYourNeighbors: DEBUG - EXCLUDED - <mac> - MACHINE: a_random_device</span>
<span class="go">MindYourNeighbors: DEBUG - MATCH - <mac> - MACHINE: my_pc</span>
<span class="go">MindYourNeighbors: DEBUG - NO_MATCH - <mac> - MACHINE: my_tel</span>
<span class="go">MindYourNeighbors: DEBUG - cache/transmission/neighbor 2 => 2</span>
<span class="go">MindYourNeighbors: INFO - 'transmission' - cache state: {'results': ['neighbor', 'no_neighbor', 'no_neighbor', 'neighbor'], 'last_command': '/home/jaes/bin/transmission-turtle false'}</span>
<span class="go">MindYourNeighbors: INFO - 'transmission' - cache count hasn't reached threshold yet (2/4)</span>
<span class="go">MindYourNeighbors: DEBUG - section <Section: bitcoind> not enabled</span>
<span class="go">MindYourNeighbors: DEBUG - section <Section: wake_if> disabled for now</span>
</code></pre></div>
<h3>SystemD</h3>
<p>It’s possible to make SystemD daemonize MindYourNeighbors. For that, you’ll have to put this <a href="https://raw.githubusercontent.com/jaesivsm/MindYourNeighbors/master/data/mind-your-neighbors.service">file</a> in <code>/etc/systemd/system/</code> and run <code>systemctl daemon-reload</code> and <code>service mind-your-neighbors start</code>.</p>
<p>Sadly, I did not find how to package this in the correct way into the python egg. Indeed, put that file and it’s destination in the <code>setup.py</code> won’t allow a none superuser to install the egg (since they can’t write in <code>/etc/systemd/system</code>). (Yes, it is kind of a cry for help :D)</p>
<h3>What’s to come</h3>
<p>Some enhancements should be coming soon like the <a href="https://github.com/jaesivsm/MindYourNeighbors/issues/4">neighbors probing</a>, some dry run options or juste add enough test to reach a <a href="https://coveralls.io/github/jaesivsm/MindYourNeighbors?branch=master">descent coverage</a>.</p>JARR: Production Note2016-10-21T00:00:00+02:002016-10-21T00:00:00+02:00François Schmidtstag:1pxsolidblack.pl,2016-10-21:/2016-10-21-jarr-production-note-en.html<p>If you use <a href="https://jarr.info"><span class="caps">JARR</span></a> on a daily basis, and more particularly yesterday, you may have noticed some changes.</p>
<h2>Clusters</h2>
<p>Since a week or so, I pushed on my running instance the last version of the <a href="https://github.com/jaesivsm/JARR/tree/develop">develop branch</a> of <span class="caps">JARR</span>.
The main feature that this branch brings is the clusters that …</p><p>If you use <a href="https://jarr.info"><span class="caps">JARR</span></a> on a daily basis, and more particularly yesterday, you may have noticed some changes.</p>
<h2>Clusters</h2>
<p>Since a week or so, I pushed on my running instance the last version of the <a href="https://github.com/jaesivsm/JARR/tree/develop">develop branch</a> of <span class="caps">JARR</span>.
The main feature that this branch brings is the clusters that allow to group article on their source or title. I’ll talk more deeply about that later.</p>
<h2>Some <span class="caps">DB</span> problems</h2>
<p>Yesterday you may have notied some problems with your articles. As it appears a vicious bug found its way into the <span class="caps">JARR</span> code and was triggered at user deletion (which happens rarely, and that’s a relief).</p>
<p>That bug destroyed association between clusters and articles. I wrote a script that spent the night fixing that but it wasn’t without some unnecessary stress on the database:</p>
<p style="text-align: center; width: 100%; display: block;">
<img src="https://1pxsolidblack.pl/img/jarr/postgres_cache_ALL-day.png" />
<img src="https://1pxsolidblack.pl/img/jarr/postgres_locks_ALL-day.png" />
</p>Mixed Contents2016-07-23T23:01:00+02:002016-07-23T23:01:00+02:00François Schmidtstag:1pxsolidblack.pl,2016-07-23:/mixed-contents-en.html<p>Today I want to write a small bit about something that bugged me for while before I found a 20 lines of code fix that solved it all : <em>Mixed Content</em>.</p>
<p>I recently figured out many of the articles I read on <a href="https://jarr.info"><span class="caps">JARR</span></a> (my feed reader for those <a href="https://1pxsolidblack.pl/jarr-en.html">who didn’t …</a></p><p>Today I want to write a small bit about something that bugged me for while before I found a 20 lines of code fix that solved it all : <em>Mixed Content</em>.</p>
<p>I recently figured out many of the articles I read on <a href="https://jarr.info"><span class="caps">JARR</span></a> (my feed reader for those <a href="https://1pxsolidblack.pl/jarr-en.html">who didn’t follow</a>) were badly displayed. The usual and easy solution was to directly go to the website hosting the article. But it’s shame to do so if the feed is not truncated and hold every bits of data you’ll need to read the article.</p>
<p>Anyway I got into debugging mode and I realised that my web browser console were showing some errors:</p>
<p><img src="https://1pxsolidblack.pl/img/mixed-content/content-blocked.png" style="margin: auto; display: block;" alt="some blocked content (in red)" /></p>
<p>It appears that the <em>mixed contents</em> is the type of content which isn’t secured (understand, not in <span class="caps">HTTPS</span>) in a page which is (understand in <span class="caps">HTTPS</span>). Mozilla talks a bit about how firefox handles those kind of pages <a href="https://support.mozilla.org/en-US/kb/mixed-content-blocking-firefox">here</a>.</p>
<p>But I also happened to stumble upon unsecure content which was still displayed. The browser was only showing warning when displaying it and not blocking it:</p>
<p><img src="https://1pxsolidblack.pl/img/mixed-content/content-warning.png" style="margin: auto; display: block;" alt="unsecure but unblocked, a real mystery" /></p>
<p>That’s where it becomes slightly trickier, there are two types of <em>mixed content</em>, and Mozilla (again) gives details about the differences <a href="https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content">here</a>.
In a few words, <em>active</em> content is supposed to be blocked, <em>passive</em> not. <code>img</code> are supposed to be <em>passive</em> so not blocked. So why <strong>some</strong> of my images were blocked ?</p>
<p>That’s the trick, those blocked <code>ìmg</code> with there <code>src</code> attribute also had a <code>srcset</code> attribute which make <code>img</code> <em>active</em> and so blocked. As <span class="caps">JARR</span> doesn’t really need <code>srcset</code> I just implemented a small cleaner that remove those attributes when appropriate. It should close some <a href="https://github.com/jaesivsm/JARR/issues/45"><span class="caps">UX</span> problems</a>…</p>Introducing JARR v12016-04-13T23:00:00+02:002016-04-13T23:00:00+02:00François Schmidtstag:1pxsolidblack.pl,2016-04-13:/jarr-en.html<p>It’s time I (re)present to the world a project I’ve been working on for some time now. It’s a web app that agregate feeds (<span class="caps">RSS</span>/Atom) and it let you read most of them inside your browser.</p>
<p><a class="reference external" href="https://jarr.info/"><span class="caps">JARR</span></a> (and it stands for <a class="reference external" href="https://github.com/jaesivsm/JARR">Just Another Rss Reader …</a></p><p>It’s time I (re)present to the world a project I’ve been working on for some time now. It’s a web app that agregate feeds (<span class="caps">RSS</span>/Atom) and it let you read most of them inside your browser.</p>
<p><a class="reference external" href="https://jarr.info/"><span class="caps">JARR</span></a> (and it stands for <a class="reference external" href="https://github.com/jaesivsm/JARR">Just Another Rss Reader</a>).</p>
<p>Before going through the details, you can test it by yourself by creating an account on <a class="reference external" href="https://jarr.info/">my running instance</a> !</p>
<div class="section" id="the-stack">
<h2>The Stack</h2>
<p>The project runs on python3.4 and makes a heavy use of the <a class="reference external" href="http://flask.pocoo.org/">Flask</a> framework. It’s completed with the <a class="reference external" href="http://www.sqlalchemy.org/">SQLAlchemy</a> <a class="reference external" href="https://en.wikipedia.org/wiki/Object-relational_mapping"><span class="caps">ORM</span></a> which allows various <span class="caps">SQL</span> database plug. I run my own installation against a <a class="reference external" href="http://www.postgresql.org/">PostgreSQL</a> database and it works like a charm.
Concerning the <span class="caps">UI</span>, I coded the whole thing as a <a class="reference external" href="http://reactjs.net/">ReactJS</a> one page app.</p>
<p>Let’s have a look:</p>
<a class="reference external image-reference" href="https://1pxsolidblack.pl/img/jarr/full.png"><img alt="The JARR UI" src="https://1pxsolidblack.pl/img/jarr/full.png" style="width: 70%;" /></a>
</div>
<div class="section" id="a-little-tour">
<h2>A little tour</h2>
<dl class="docutils">
<dt>As you can see on the screenshot above, the <span class="caps">UI</span> is splited in three columns. From left to right:</dt>
<dd><ul class="first last simple">
<li>the first one let you see and select your categories and feeds. You can fold categories and display only feeds with unread articles or feeds which have encountered errors.</li>
<li>the second one is the article list, which will be updated when you select a feed or a category.</li>
<li>the third and last one is the category, feed, article or article you selected.</li>
</ul>
</dd>
</dl>
<p>As some feeds don’t provide content, the right panel may not be as filled as you can see on the screenshot and you may have to go directly to the source though the link on the feed title in the article list.
A better solution has also been implemented, if you have a <a class="reference external" href="https://www.readability.com/">readability</a> key you provided either at the installation or in your profile, you’ll have a little readability button in the top right corner or your article. Clicking it will retrieve a cleaned version of your content.
You can also choose in a feed options to make that retrieving automatic.
That’s especially handy for news agregator like <a class="reference external" href="https://news.ycombinator.com/">HackerNews</a>.</p>
</div>
<div class="section" id="what-s-new">
<h2>What’s new</h2>
<p>I worked a lot on the <span class="caps">UI</span>, and it feels pretty done by now. I’ll talk about it a lot below.</p>
<p>I’m working on redoing the install process so it’d be easy to bootstrap the project.</p>
<p>The crawler works pretty fine. The queue system is pretty robust and the whole thing works pretty well, it scales great against huge work loads without consumming to much ressource. The next step for it would be to make it a daemon and make it scale automatically.</p>
</div>
<div class="section" id="mobile">
<h2>Mobile</h2>
<p>The site is somewhat compatible with smaller device.</p>
<p>Here on tablets :</p>
<a class="reference external image-reference" href="https://1pxsolidblack.pl/img/jarr/small.png"><img alt="The JARR UI" src="https://1pxsolidblack.pl/img/jarr/small.png" style="width: 50%;" /></a>
<p>And on phones :</p>
<a class="reference external image-reference" href="https://1pxsolidblack.pl/img/jarr/xsmall.png"><img alt="The JARR UI" src="https://1pxsolidblack.pl/img/jarr/xsmall.png" style="width: 25%;" /></a>
</div>
<div class="section" id="what-s-down-the-road">
<h2>What’s down the road</h2>
<p>Some coming features are listed in the <a class="reference external" href="https://github.com/jaesivsm/JARR/milestones">Github milestones</a>. Most of them are obvious <span class="caps">UI</span> improvements and utilisability tweaks (as <a class="reference external" href="https://github.com/jaesivsm/JARR/issues/3">mark an article to be read later on</a> or <a class="reference external" href="https://github.com/jaesivsm/JARR/issues/8">having a nice integration for well-known feed that misbehave or are poorly formated</a>).</p>
<p>But the main thing I’d like to implement would be an intelligent grouping feature that would regroup articles in clusters. The goal would be to regroup article on the same subject (or pointing to the same resource) so a user wouldn’t be presented with the same news if it appears in multiple feeds.
It’s a feature a bit down the road, but definitively coming !</p>
</div>
<div class="section" id="history">
<h2>History</h2>
<p>The project was initially created by <a class="reference external" href="http://www.cedricbonhomme.org/">Cédric Bonhomme</a> who I thanks a lot for letting me fiddle with his project. But, as I introduced stuffs to the project that he was less and less easy with, I thought it was time for a full fork.</p>
</div>
<div class="section" id="conclusion">
<h2>Conclusion</h2>
<p>I’d be happy to see some of you install the <a class="reference external" href="https://github.com/jaesivsm/JARR">project</a> (I worked on the install script so it’s painless :) or try it on <a class="reference external" href="https://jarr.info/">my instance</a>.
Of course, I’m welcoming all critics and <a class="reference external" href="https://github.com/jaesivsm/JARR">contributions</a> !</p>
<style type='text/css'>
.reference.external.image-reference {
text-align: center; width: 100%; display: block;}
</style></div>