<?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>DEV Community: ryan senn</title>
    <description>The latest articles on DEV Community by ryan senn (@ryansenn).</description>
    <link>https://dev.to/ryansenn</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%2F2226%2F1097394.jpeg</url>
      <title>DEV Community: ryan senn</title>
      <link>https://dev.to/ryansenn</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ryansenn"/>
    <language>en</language>
    <item>
      <title>Integrating a Ghost blog with an elixir reverse proxy in Phoenix</title>
      <dc:creator>ryan senn</dc:creator>
      <pubDate>Wed, 27 May 2020 03:12:53 +0000</pubDate>
      <link>https://dev.to/ryansenn/integrating-a-ghost-blog-with-an-elixir-reverse-proxy-in-phoenix-4naf</link>
      <guid>https://dev.to/ryansenn/integrating-a-ghost-blog-with-an-elixir-reverse-proxy-in-phoenix-4naf</guid>
      <description>&lt;p&gt;After thinking about it for a while, I decided to take the jump and actually start a blog. The blog will be about tech and SEO.&lt;/p&gt;

&lt;p&gt;I have published my very first blog post, which is &lt;a href="https://seoapps.dev/blog/integrating-a-ghost-blog-with-elixir-phoenix"&gt;my journey of integrating the blog itself into my Phoenix based application&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I thought it would be fun to write the very first post about how I set up the blog, on the blog :)&lt;/p&gt;

&lt;p&gt;It is a 7 minutes read.&lt;/p&gt;

&lt;p&gt;A real reverse proxy such as nginx would probably be preferable, but I wanted to see how it would work just in Elixir.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Google keyword rank checker</title>
      <dc:creator>ryan senn</dc:creator>
      <pubDate>Fri, 08 May 2020 04:24:54 +0000</pubDate>
      <link>https://dev.to/ryansenn/google-keyword-rank-checker-25l5</link>
      <guid>https://dev.to/ryansenn/google-keyword-rank-checker-25l5</guid>
      <description>&lt;h2&gt;
  
  
  Tracking websites that are not on the first page
&lt;/h2&gt;

&lt;p&gt;If you are trying to rank a new website, you know how tricky it can be to monitor progress. I've spent way more time trying to find my website on page 6 or 7 on google than I would like to admit.&lt;br&gt;
There are a few tools out there that will do this for you. I found them however slow and full of ads. Even worse, they hide the actual submit button and make other buttons look like the submit button, tricking you to click on unwanted ads.&lt;/p&gt;

&lt;p&gt;As a result, I decided to create my own, lightweight, fast, and clutter free &lt;a href="https://seoapps.dev/keyword-rank"&gt;tool to check keyword rank&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JOuZ3YoK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m1qhschjh3yo5zlcld9b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JOuZ3YoK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/m1qhschjh3yo5zlcld9b.png" alt="Clean keyword rank tool"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Much better, this is my kind of interfaces!&lt;/p&gt;

&lt;p&gt;Simply enter your search keywords, the domain you want to find and the tool will show you the top 100 results within a couple of seconds, highlighting the domain you are trying to find. Nice and simple, just how I wish the existing tools would be.&lt;/p&gt;

&lt;h2&gt;
  
  
  Discovering backlinks within the top 100 search results
&lt;/h2&gt;

&lt;p&gt;While working on this tool and looking at the list of results for one of my websites (ranking on the third page at this point), I spotted a blog post about said website ranking on page 8. That sparked an idea: Wonder how many backlinks the very first result on google has from within the top 100 search results for this search term? Could I simply crawl the 100 search result pages and search for backlinks pointing to that domain?&lt;/p&gt;

&lt;h2&gt;
  
  
  Elixir to the rescue
&lt;/h2&gt;

&lt;p&gt;The answer of course is yes, it's actually quite trivial to do in Elixir which I happened to use for this. Elixir can run thousands if not millions of concurrent processes, so 100 concurrent http requests and crawling the content is a piece of cake. Elixir also has a great library to parse html called &lt;a href="https://github.com/philss/floki"&gt;floki&lt;/a&gt;, which is used by default in Phoenix test suites, so finding links and even figuring out wether they are follow or no follow is also very easy.&lt;/p&gt;

&lt;p&gt;Next I just push the discovered backlinks down to Elm using web sockets, and Elm simply updates the loading spinner and displays the results.&lt;/p&gt;

&lt;p&gt;Turns out the first search result had backlinks from 7 other pages in the top 100, with 6 of them being really easy to create for my own website.&lt;/p&gt;

&lt;p&gt;So yeah, if you are wondering why a website, be it a competitor or just out of interest &lt;a href="https://seoapps.dev/keyword-rank"&gt;is ranking so well for particular keywords, give the keyword-rank checker tool&lt;/a&gt; a go! It can help you not only understand why they are ranking as they are, it can also be used to discover potential backlink opportunities.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>freetools</category>
      <category>keywordrank</category>
      <category>google</category>
    </item>
    <item>
      <title>Text readability library in Elm</title>
      <dc:creator>ryan senn</dc:creator>
      <pubDate>Tue, 05 May 2020 07:46:28 +0000</pubDate>
      <link>https://dev.to/ryansenn/text-readability-in-elm-31co</link>
      <guid>https://dev.to/ryansenn/text-readability-in-elm-31co</guid>
      <description>&lt;p&gt;I am happy to announce the release of an Elm package that will evaluate text according to the &lt;a href="https://en.wikipedia.org/wiki/Dale%E2%80%93Chall_readability_formula"&gt;Dale-Chall&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Coleman%E2%80%93Liau_index"&gt;Coleman-Liau&lt;/a&gt; readability formula.&lt;/p&gt;

&lt;p&gt;The package can be found in the official Elm package repository: &lt;a href="https://package.elm-lang.org/packages/ryan-senn/elm-readability/latest/"&gt;https://package.elm-lang.org/packages/ryan-senn/elm-readability/latest/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The reason I created this package is part of a new project of mine. I tend to start to build tools etc. and give them up un-completed or un-polished. I have realised that the best way for me to push through is to have them released online. They basically have to leave my local environment or will be doomed and forgotten.&lt;/p&gt;

&lt;p&gt;Part of my SEO strategy at work requires me to use a Word Counter tool. There are plenty of them online that I have used, but I wanted to create my own minimalistic version going forward. A quick prototype attempt turned out successful, so I set out to build this properly. This includes splitting the readability package out of the Word Counter project and open sourcing it.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://seoapps.dev/word-counter"&gt;Word Counter tool&lt;/a&gt; is now online and it turned out just like I had hoped. I also took this opportunity to try out Bulma CSS.&lt;/p&gt;

&lt;p&gt;The Dale-Chall formula uses a list of 3k common words that are identified as simple. Luckily for me, there was an NPM package that contained the list. One tricky bit is that the list doesn't include plurals, so I needed a script to generate a list including plurals. I was in luck again as there is a NPM package that does just that. All there was left to do is remove any duplicates and write an Elm file.&lt;/p&gt;

&lt;p&gt;Another challenge was performance. Scanning the entire text, splitting it into words and search for the 6k simple words was a little heavy. Changing the simple words lookup from a List to a Dict String () helped big times.&lt;/p&gt;

&lt;p&gt;The other improvement was adding a debounce. No need to re-calculate everything on every keystroke. I found that a debounce of 200ms was a good compromise for the statistics on the right. Lucky me again, Elm has a nice library for it: jinjor/elm-debounce.&lt;/p&gt;

&lt;p&gt;My next goal is to polish a CLI tool that I built to find the google ranking of websites for certain keywords and display backlinks from other top 100 pages. It should work very nicely with Elixir/Phoenix web-sockets and Elm.&lt;/p&gt;

</description>
      <category>elm</category>
      <category>packagerelease</category>
      <category>readabilityformula</category>
    </item>
    <item>
      <title>Lottery Simulation in Elm</title>
      <dc:creator>ryan senn</dc:creator>
      <pubDate>Mon, 13 Apr 2020 04:07:28 +0000</pubDate>
      <link>https://dev.to/ryansenn/lottery-simulation-in-elm-2fgm</link>
      <guid>https://dev.to/ryansenn/lottery-simulation-in-elm-2fgm</guid>
      <description>&lt;p&gt;Hi all,&lt;/p&gt;

&lt;p&gt;A while back, I came across a &lt;a href="https://graphics.latimes.com/powerball-simulator/"&gt;cool article published by the Los Angeles Times&lt;/a&gt;, where you start with $100 and simulate playing the Powerball (written in JS).&lt;/p&gt;

&lt;p&gt;It inspired me to write an &lt;a href="https://ryansenn.dev/powerball"&gt;Australian Powerball version&lt;/a&gt; (the number of balls, barrel sizes etc are different) in Elm, which I'm hosting on my personal website. The app is pretty rough, it was to try out Elm 0.19.1 (upgrade from 0.19). I shared it on reddit on the Australian Finance sub and got overwhelmingly positive feedback.&lt;/p&gt;

&lt;p&gt;With the whole lockdown thing happening now and to keep myself busy, I decided to created a &lt;a href="https://lottosimulation.com/"&gt;website dedicated  to lottery simulations&lt;/a&gt;. It now includes all popular lotteries such as the US Powerball, US Mega Millions, Euro Jackpot, Euro Millions as well as the most popular Australian Lotteries. I have also put in more effort on the UX level.&lt;/p&gt;

&lt;p&gt;I think that Elm's strong static types really helped me during the development of this app. Not knowing much about lotteries before jumping in, there were many refactors along the way. I did not expect the European lotteries to have multiple "Powerballs" for example (called Euro numbers and Lucky stars). The application also has to support games such as OZ lotto, where there is a single barrel, and the last 2 numbers are complimentary numbers etc. Even with a lot of experience with dynamic languages such as Elixir, I think that static types and the friendly compiler messages kept me sane.&lt;/p&gt;

&lt;p&gt;All the lotteries use the same code base, the behaviour is dictated by the config that gets injected.&lt;/p&gt;

&lt;p&gt;The site is running on a simple Elixir/Phoenix backend with only a few tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rendering the pages where Elm mounts itself&lt;/li&gt;
&lt;li&gt;GenServer to crawl the current Jackpots&lt;/li&gt;
&lt;li&gt;GenServer to crawl recent draws and dividends&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have a play around to test your luck, I would love to hear about your feedback!&lt;/p&gt;

</description>
      <category>lottery</category>
      <category>simulation</category>
      <category>powerball</category>
      <category>jackpot</category>
    </item>
    <item>
      <title>If the COVID-19 stimulus package was stacked as $100 bills</title>
      <dc:creator>ryan senn</dc:creator>
      <pubDate>Fri, 10 Apr 2020 02:34:24 +0000</pubDate>
      <link>https://dev.to/ryansenn/if-the-covid-19-stimulus-package-was-stacked-as-100-bills-42gl</link>
      <guid>https://dev.to/ryansenn/if-the-covid-19-stimulus-package-was-stacked-as-100-bills-42gl</guid>
      <description>&lt;h1&gt;
  
  
  How tall is 2.2 trillions stacked as $100 bills?
&lt;/h1&gt;

&lt;p&gt;After debating with friends how tall $1 million USD stacked as $100 bills would be, I decided to run the actual math. Assuming a thickness of 0.010922 centimeters, or 0.0043 inches per bill, it turns out to be just above 1 meters (1.09m | 3.58ft), or about the height of a normal, adult size bicycle.&lt;/p&gt;

&lt;p&gt;I've decided to create a little ELM application with a slider for 1M, 10M, 100M etc. all the way to 2.2 trillions, which is how much the Reserve Bank decided to inject into the economy to fight COVID-19. Each step has an image representing how high the stack would be to make it easier to visualise.&lt;/p&gt;

&lt;p&gt;Here it is: &lt;a href="https://lottosimulation.com/covid-19/us"&gt;COVID-19 stimulus stacked as $100 notes&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the development side of things, the part that took the most time, by far, was making it work on mobile and desktop. On desktop, the slider sits at the bottom and is displayed horizontally, while on mobile the slider sits at the left and is displayed vertically. Keeping the numbers aligned with the slider was definitely a challenge.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---EeRJetT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/91wegxs1yawyqkagdi1h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---EeRJetT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/91wegxs1yawyqkagdi1h.png" alt="Desktop slider"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--32dFtJjo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/37m1f7u5uoqpn59d5dor.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--32dFtJjo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/37m1f7u5uoqpn59d5dor.png" alt="Mobile slider"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For anyone wondering, it is a HTML slider (input type="range") with a datalist. You can style the slider by removing the default styles with appearance: none (needs prefixes, I use autoprefixer with postcss to automatically prefix anything that needs it).&lt;/p&gt;

&lt;p&gt;While it is not incredibly useful or beautiful (you can probably tell that my photoshop skills are subpar), took a lot of time fiddling around with styles, I am still pretty happy with the result.&lt;/p&gt;

</description>
      <category>covid19</category>
      <category>visualisation</category>
    </item>
    <item>
      <title>Elixir AVETMISS library</title>
      <dc:creator>ryan senn</dc:creator>
      <pubDate>Wed, 26 Feb 2020 02:05:27 +0000</pubDate>
      <link>https://dev.to/ryansenn/elixir-avetmiss-library-35k0</link>
      <guid>https://dev.to/ryansenn/elixir-avetmiss-library-35k0</guid>
      <description>&lt;p&gt;In the extremely unlikely circumstances that you need to generate AVETMISS reports with Elixir, I have created a &lt;a href="https://github.com/ryan-senn/avetmiss"&gt;library&lt;/a&gt; for it.&lt;br&gt;
AVETMISS stands for "Australian Vocational Education and Training Management Information Statistical Standard". It is a report that any registered training organisation (RTO) that delivers vocational and education training (VET) have to report to the National Centre for Vocational Education Research (NCVER).&lt;br&gt;
I happen to need it for my newly founded company, &lt;a href="https://tt.edu.au/white-card-qld/brisbane"&gt;Tradie Training&lt;/a&gt;.&lt;br&gt;
It is the first time that I created an Elixir library, so it was a great way to learn about hex.pm, the package repository powering the Elixir and Erlang ecosystem.&lt;br&gt;
I have to say that the experience was very positive. Almost everything was done via very simple and straight forward CLI commands. You can add comments in the code that will be interpreted by hex.pm to generate documentation for you, although I didn't really have the time to invest in it. Something to re-visit when things quiet down a bit. I did however create a &lt;a href="https://avetmiss.readthedocs.io/en/latest/"&gt;read the docs page&lt;/a&gt; for the first time, I really wanted to figure out how it works. I didn't invest much time into it either, but knowing how it works is nice.&lt;br&gt;
I love Elixir as a language, but to me what's even more impressive is the quality of everything else. Mix, ecto, hex.pm, great documentation, transparent leadership, quality libraries for just about anything, the list goes on. Ruby is known for developer satisfaction, and in my opinion Elixir takes this to another level.&lt;br&gt;
Typing all this out really motivates me to improve the docs for the AVETMISS library, even knowing how unlikely it is that anyone but me will need it in the future.&lt;br&gt;
For anyone on the fence of giving Elixir a try, just do it! The community and ecosystems are amazing.&lt;br&gt;
To find out more about how AVETMISS works, I wrote a &lt;a href="https://rtoadvisors.com.au/articles/what-is-avetmiss"&gt;technical guide&lt;/a&gt; on it.&lt;/p&gt;

</description>
      <category>avetmiss</category>
      <category>rto</category>
      <category>elixir</category>
    </item>
    <item>
      <title>The stack powering Tradie Training White Card</title>
      <dc:creator>ryan senn</dc:creator>
      <pubDate>Tue, 25 Feb 2020 05:58:52 +0000</pubDate>
      <link>https://dev.to/ryansenn/the-stack-powering-tradie-training-white-card-fl</link>
      <guid>https://dev.to/ryansenn/the-stack-powering-tradie-training-white-card-fl</guid>
      <description>&lt;p&gt;Tradie Training officially started delivering the White Card course to customers in January 2020, but we started work on the website, student management system and training platform 6 months prior to that.&lt;br&gt;
There were a lot of considerations, including the fact that not everything needed to use the same tech stack.&lt;br&gt;
We ended up using the Elixir language with Phoenix as a framework, using umbrella applications to keep everything nice and tidy. The website is a umbrella application, the student management system is one, the administration is one as well. On top of that we've created more umbrella applications for common code such as the database layer, the PubSub layer etc. This approach turned out to be a massive win for Tradie Training.&lt;br&gt;
We leverage a recent feature of Phoenix, called LiveView, to efficiently display live dashboards and student tracking.&lt;br&gt;
With all of that said, basically Elixir powers almost everything we need. We dropped in Elm and a few other technologies when needed (signup page with client side encryption etc).&lt;/p&gt;

&lt;p&gt;You can book your &lt;a href="https://tt.edu.au/white-card-qld/brisbane"&gt;White Card in Brisbane&lt;/a&gt; or on the &lt;a href="https://tt.edu.au/white-card-qld/gold-coast"&gt;Gold Coast&lt;/a&gt; using our booking system (built in Elm &amp;amp; Elixir 😊)&lt;/p&gt;

&lt;p&gt;As you can probably guess from the stack, we love functional programming.&lt;/p&gt;

&lt;p&gt;For hosting, we ended up going with render.com. They have a great tutorial on deploying Elixir applications that we followed, and everything just worked straight away. Definitely check them out, I highly recommend them.&lt;/p&gt;

&lt;p&gt;Tradie Training is a &lt;a href="https://training.gov.au/Organisation/Details/45555"&gt;registered training organisation&lt;/a&gt; and is licensed to issue White Cards on behalf on WorkSafe Queensland.&lt;/p&gt;

</description>
      <category>language</category>
      <category>framework</category>
      <category>whitecard</category>
    </item>
  </channel>
</rss>
