<?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: Tito</title>
    <description>The latest articles on DEV Community by Tito (@titonobre).</description>
    <link>https://dev.to/titonobre</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%2F61432%2F6cba7873-8f65-4206-8310-ed81c61771d4.png</url>
      <title>DEV Community: Tito</title>
      <link>https://dev.to/titonobre</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/titonobre"/>
    <language>en</language>
    <item>
      <title>Storybook Addon AngularJS (1.x)</title>
      <dc:creator>Tito</dc:creator>
      <pubDate>Sun, 26 Aug 2018 15:57:31 +0000</pubDate>
      <link>https://dev.to/titonobre/storybook-addon-angularjs-5c71</link>
      <guid>https://dev.to/titonobre/storybook-addon-angularjs-5c71</guid>
      <description>&lt;p&gt;A few weeks ago I published the package &lt;a href="https://www.npmjs.com/package/storybook-addon-angularjs"&gt;storybook-addon-angularjs&lt;/a&gt; to help create stories for Storybook with AngularJS components.&lt;/p&gt;

&lt;p&gt;Features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple syntax&lt;/li&gt;
&lt;li&gt;Supports integration with other addons like &lt;code&gt;knobs&lt;/code&gt; and  &lt;code&gt;actions&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Tweet with the first announcement and a small screen capture:&lt;/p&gt;

&lt;p&gt;Liquid error: internal&lt;/p&gt;

&lt;p&gt;Creating a story with an AngularJS component is as simple as this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;storiesOf&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@storybook/html&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;withKnobs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@storybook/addon-knobs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@storybook/addon-actions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;forModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;storybook-addon-angularjs&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;storiesOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Components/Demo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addDecorator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;withKnobs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;forModule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;myApp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;compile&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jane&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;range&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;min&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;step&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onEvt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;clicked&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;compile&lt;/span&gt;&lt;span class="s2"&gt;`&amp;lt;demo-component
                       name="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"
                       foo="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"
                       on-ev="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;onEvt&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;(num, name)"&amp;gt;&amp;lt;/demo-component&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This depends on Storybook 4+ and the HTML Addon.&lt;/p&gt;

&lt;p&gt;The code for the addon:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/titonobre"&gt;
        titonobre
      &lt;/a&gt; / &lt;a href="https://github.com/titonobre/storybook-addon-angularjs"&gt;
        storybook-addon-angularjs
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A simple addon to create Storybook stories with AngularJS components.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Storybook Addon for AngularJS (1.x)&lt;/h1&gt;
&lt;p&gt;&lt;a href="https://www.npmjs.com/package/storybook-addon-angularjs" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/294c1bcb473ceafd4c846fb0c60b77d1a00a58e02ace2e533776c7a46483041c/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f73746f7279626f6f6b2d6164646f6e2d616e67756c61726a732e737667" alt="npm"&gt;&lt;/a&gt;
&lt;a href="https://www.npmjs.com/package/storybook-addon-angularjs" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/998ea7e3f692d5e6802f232c0e6497b2c7e834c5af8ce7eeed88e4491e58f748/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f64742f73746f7279626f6f6b2d6164646f6e2d616e67756c61726a732e737667" alt="npm"&gt;&lt;/a&gt;
&lt;a href="https://github.com/titonobre/storybook-addon-angularjs/issues"&gt;&lt;img src="https://camo.githubusercontent.com/2f3411045da11015539c40b8c246c5e1d7afc4876b941e76b6578ba780d2e7c8/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f7469746f6e6f6272652f73746f7279626f6f6b2d6164646f6e2d616e67756c61726a732e737667" alt="GitHub issues"&gt;&lt;/a&gt;
&lt;a href="https://github.com/titonobre/storybook-addon-angularjs/blob/master/LICENSE"&gt;&lt;img src="https://camo.githubusercontent.com/653ee65f951cc8d176746b2f4c714ec14ccb9dee27a23efed56b59651da1777b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f7469746f6e6f6272652f73746f7279626f6f6b2d6164646f6e2d616e67756c61726a732e737667" alt="GitHub"&gt;&lt;/a&gt;
&lt;a href="https://storybook.js.org/" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/bfb8b00b290e35fb87f98349e9edf76db8d3dbf05e8f184d1cd3566c1dcb0aa4/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f73746f7279626f6f6b2d342532422d6666343738352e737667" alt="Storybook"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;
This addon is intended to be used with &lt;code&gt;@storybook/html&lt;/code&gt;, available since Storybook 4.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
Installation&lt;/h2&gt;
&lt;p&gt;Use your favorite 📦 package manager to install the addon in your project's &lt;code&gt;devDependencies&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;npm:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;npm install --save-dev storybook-addon-angularjs&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Yarn:&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;yarn add --dev storybook-addon-angularjs&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
Usage&lt;/h2&gt;
&lt;p&gt;This addon is flexible enough to let you choose how you want to write stories.&lt;/p&gt;
&lt;p&gt;Your stories can be as simple as this:&lt;/p&gt;
&lt;div class="highlight highlight-source-js js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;export&lt;/span&gt; &lt;span class="pl-k"&gt;default&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-c1"&gt;title&lt;/span&gt;: &lt;span class="pl-s"&gt;"QuoteCard"&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
  &lt;span class="pl-c1"&gt;decorators&lt;/span&gt;: &lt;span class="pl-kos"&gt;[&lt;/span&gt;&lt;span class="pl-en"&gt;withAngularJs&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;"myApp"&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;]&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;export&lt;/span&gt; &lt;span class="pl-k"&gt;const&lt;/span&gt; &lt;span class="pl-en"&gt;simpleTemplate&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt; &lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-c1"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="pl-s"&gt;`&lt;/span&gt;
&lt;span class="pl-s"&gt;  &amp;lt;quote-card author="'Me'"&amp;gt;&lt;/span&gt;
&lt;span class="pl-s"&gt;    It works with a simple template!&lt;/span&gt;
&lt;span class="pl-s"&gt;  &amp;lt;/quote-card&amp;gt;&lt;/span&gt;
&lt;span class="pl-s"&gt;`&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;But you may choose something more advanced:&lt;/p&gt;
&lt;div class="highlight highlight-source-js js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-s1"&gt;withKnobs&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-s1"&gt;text&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;"@storybook/addon-knobs"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-s1"&gt;action&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;"@storybook/addon-actions"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt; &lt;span class="pl-s1"&gt;html&lt;/span&gt;&lt;span class="pl-kos"&gt;,&lt;/span&gt; &lt;span class="pl-s1"&gt;withAngularJs&lt;/span&gt; &lt;span class="pl-kos"&gt;}&lt;/span&gt; &lt;span class="pl-k"&gt;from&lt;/span&gt; &lt;span class="pl-s"&gt;"storybook-addon-angularjs"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-k"&gt;class&lt;/span&gt; &lt;span class="pl-v"&gt;MockedAppService&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-en"&gt;constructor&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
    &lt;span class="pl-smi"&gt;this&lt;/span&gt;&lt;span class="pl-kos"&gt;.&lt;/span&gt;&lt;span class="pl-c1"&gt;message&lt;/span&gt; &lt;span class="pl-c1"&gt;=&lt;/span&gt;&lt;/pre&gt;…
&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/titonobre/storybook-addon-angularjs"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;A working example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i3JOwpme--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-ba8488d21cd8ee1fee097b8410db9deaa41d0ca30b004c0c63de0a479114156f.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/titonobre"&gt;
        titonobre
      &lt;/a&gt; / &lt;a href="https://github.com/titonobre/storybook-addon-angularjs-example"&gt;
        storybook-addon-angularjs-example
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A working example with storybook-addon-angularjs. Moved to: https://github.com/titonobre/storybook-addon-angularjs
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
Storybook Addon for AngularJS (1.x) Example&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;&lt;br&gt;
This repository was merged into &lt;a href="https://github.com/titonobre/storybook-addon-angularjs"&gt;&lt;code&gt;storybook-addon-angularjs&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/titonobre/storybook-addon-angularjs-example"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;Feedback is appreciated.&lt;br&gt;
Thanks for reading.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>storybook</category>
      <category>angular</category>
    </item>
    <item>
      <title>MineSweeper Party</title>
      <dc:creator>Tito</dc:creator>
      <pubDate>Thu, 24 May 2018 23:10:56 +0000</pubDate>
      <link>https://dev.to/titonobre/minesweeper-party-2d2h</link>
      <guid>https://dev.to/titonobre/minesweeper-party-2d2h</guid>
      <description>&lt;h1&gt;
  
  
  What I built
&lt;/h1&gt;

&lt;p&gt;Well, I built a MineSweeper game that allows multiple players to play the same game at the same time. No turns, no waiting. Just tap tap boom! 💥&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fayeq0kqlpg4xif3bjxam.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fayeq0kqlpg4xif3bjxam.png" alt="dotenv" width="800" height="1380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Like the classic versions, the instructions are very simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tap/Click on a tile to reveal it;&lt;/li&gt;
&lt;li&gt;Tap/Click and Hold on a tile to lock it with a flag 🚩;&lt;/li&gt;
&lt;li&gt;Reveal all the safe tiles to win.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;The games are played on a channel, which is identified by a URL. Each channel allow infinite number of random games but only one at a time.&lt;/p&gt;

&lt;p&gt;There are 4 pre-defined channels with increasing level of difficulty: easy/medium/hard/extreme.&lt;/p&gt;

&lt;p&gt;Other channels can be created with a random id, much like YouTube does: &lt;a href="https://minesweeper-party.herokuapp.com/dQw4w9WgXcQ" rel="noopener noreferrer"&gt;https://minesweeper-party.herokuapp.com/dQw4w9WgXcQ&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All these channels can be shared with other users. So let the games begin.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Pusher is used
&lt;/h2&gt;

&lt;p&gt;When the user joins a game, the application subscribes to a Pusher channel to receive notifications of changes (reveal/flag) from other users playing the same game.&lt;/p&gt;

&lt;p&gt;When the users reveals or flags a tile, a request is made to the server and a notification is sent to all the subscribers of the same game/channel. Since the client also have the game engine, the local state is updated optimistically before the responses from the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo Link
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://minesweeper-party.herokuapp.com/" rel="noopener noreferrer"&gt;https://minesweeper-party.herokuapp.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm using a free Heroku Dyno that goes to sleep after not being used for a while. It might take a few seconds to wake it up the first time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Link to Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/titonobre/minesweeper-party" rel="noopener noreferrer"&gt;https://github.com/titonobre/minesweeper-party&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  How I built it
&lt;/h1&gt;

&lt;p&gt;This project was implemented in TypeScript, using Angular as the frontend framework and Express for the server. The frontend application is a &lt;a href="https://dev.to/t/pwa"&gt;PWA&lt;/a&gt; and uses a ServiceWorker to cache assets on the client device.&lt;/p&gt;

&lt;p&gt;The share button is using the &lt;a href="https://dev.to/philnash/the-web-share-api"&gt;Web Share API&lt;/a&gt;, only supported in recent versions of Google Chrome for Android.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Application&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://angular.io/" rel="noopener noreferrer"&gt;Angular&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ReactiveX/rxjs" rel="noopener noreferrer"&gt;RxJS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/pusher-js" rel="noopener noreferrer"&gt;Pusher Client&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Server&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;Express&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/package/pusher" rel="noopener noreferrer"&gt;Pusher&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://heroku.com/" rel="noopener noreferrer"&gt;Heroku&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Other Noteworthy Tools&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cli.angular.io/" rel="noopener noreferrer"&gt;Angular CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;npm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/motdotla/dotenv" rel="noopener noreferrer"&gt;dotenv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/fgnass/node-dev" rel="noopener noreferrer"&gt;node-dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/imagemin/imagemin" rel="noopener noreferrer"&gt;imagemin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/shakiba/svgexport" rel="noopener noreferrer"&gt;svgexport&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/mysticatea/npm-run-all" rel="noopener noreferrer"&gt;npm-run-all&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Issues
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The name of the project
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;There are only two hard things in Computer Science: cache invalidation and naming things.&lt;br&gt;
&lt;em&gt;-- Phil Karlton&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No comments here! 🙄&lt;/p&gt;

&lt;h1&gt;
  
  
  Additional Resources/Info
&lt;/h1&gt;

&lt;p&gt;It is worth to mention that the initial inspiration for the game engine was based on the work done by &lt;a href="https://www.jvandemo.com/how-to-build-minesweeper-using-angular-2-and-immutable-js/" rel="noopener noreferrer"&gt;Jurgen Van de Moere&lt;/a&gt; and &lt;a href="https://github.com/cjohansen/react-sweeper" rel="noopener noreferrer"&gt;Christian Johansen&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Future Work
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Expandable Mine Field&lt;/strong&gt; - The Game engine supports configurable grid sizes but I think it would be a great challenge to support a kind of expandable grid (maybe "infinite").&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Have Data Persistence&lt;/strong&gt; - Currently the games are not persisted and are lost if the server restarts or goes to sleep. Some kind of storage would be nice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Allow Custom Difficulty&lt;/strong&gt; - Configurable grid sizes and number of mines could be a nice addition.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Add some kind of ranking&lt;/strong&gt; - It's not easy to finish a game with others playing the same game. Give points to the best players on a channel would make things more interesting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;P2P&lt;/strong&gt; - Pusher allows clients to send messages through the websocket to other clients. This could be nice to avoid the communication with the game server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Share on all devices&lt;/strong&gt; - Although the Web Share API is awesome and very simple to use. It would be nice to use an alternative while other browsers don't support it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Offline Mode&lt;/strong&gt; - Since the purpose of the contest was to use Pusher I removed the offline mode but it is very simple to add back.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Beware and don't step on a mine...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4pupm649cjhq7107nmet.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4pupm649cjhq7107nmet.png" alt="land mine" width="100" height="52"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>pushercontest</category>
      <category>angular</category>
      <category>pusher</category>
      <category>pwa</category>
    </item>
  </channel>
</rss>
